Merge branch 'feature/reactjs-container-component-with-mobx' into feature/mobile-apps-on-reactjs
# Conflicts: # apps/documenteditor/mobile/locale/en.json # apps/documenteditor/mobile/src/components/app.jsx # apps/documenteditor/mobile/src/components/settings/Settings.jsx # apps/documenteditor/mobile/src/components/settings/document-settings/DocumentSettings.jsx # apps/documenteditor/mobile/src/js/routes.js # apps/documenteditor/mobile/src/pages/home.jsx # apps/documenteditor/mobile/src/store/reducers/root.js # apps/documenteditor/mobile/src/store/store.js
This commit is contained in:
commit
b041083933
|
@ -1,17 +1,17 @@
|
||||||
import React, { useState } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { resetUsers } from '../store/actions/actions.js'
|
|
||||||
import Notifications from '../../utils/notifications.js'
|
import Notifications from '../../utils/notifications.js'
|
||||||
|
import {observer, inject} from "mobx-react"
|
||||||
|
|
||||||
const Collaboration = () => {
|
|
||||||
const onChangeEditUsers = (users) => {
|
@inject('users')
|
||||||
const store = Common.Store.get();
|
class CollaborationController extends Component {
|
||||||
store.dispatch(resetUsers(Object.values(users)));
|
constructor(props){
|
||||||
};
|
super(props)
|
||||||
|
|
||||||
Common.Notifications.on('engineCreated', api => {
|
Common.Notifications.on('engineCreated', api => {
|
||||||
// this.api = api;
|
// this.api = api;
|
||||||
api.asc_registerCallback('asc_onAuthParticipantsChanged', onChangeEditUsers);
|
api.asc_registerCallback('asc_onAuthParticipantsChanged', this.onChangeEditUsers.bind(this));
|
||||||
api.asc_registerCallback('asc_onParticipantsChanged', onChangeEditUsers);
|
api.asc_registerCallback('asc_onParticipantsChanged', this.onChangeEditUsers.bind(this));
|
||||||
// this.api.asc_registerCallback('asc_onAddComment', _.bind(this.onApiAddComment, this));
|
// this.api.asc_registerCallback('asc_onAddComment', _.bind(this.onApiAddComment, this));
|
||||||
// this.api.asc_registerCallback('asc_onAddComments', _.bind(this.onApiAddComments, this));
|
// this.api.asc_registerCallback('asc_onAddComments', _.bind(this.onApiAddComments, this));
|
||||||
// this.api.asc_registerCallback('asc_onChangeCommentData', _.bind(this.onApiChangeCommentData, this));
|
// this.api.asc_registerCallback('asc_onChangeCommentData', _.bind(this.onApiChangeCommentData, this));
|
||||||
|
@ -20,11 +20,16 @@ const Collaboration = () => {
|
||||||
// this.api.asc_registerCallback('asc_onShowComment', _.bind(this.apiShowComments, this));
|
// this.api.asc_registerCallback('asc_onShowComment', _.bind(this.apiShowComments, this));
|
||||||
// this.api.asc_registerCallback('asc_onHideComment', _.bind(this.apiHideComments, this));
|
// this.api.asc_registerCallback('asc_onHideComment', _.bind(this.apiHideComments, this));
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
setApi(api) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChangeEditUsers(users) {
|
||||||
|
const storeUsers = this.props.users;
|
||||||
|
storeUsers.reset(users);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export {Collaboration as CollaborationController}
|
export default CollaborationController;
|
|
@ -1,8 +0,0 @@
|
||||||
export const RESET_USERS = 'RESET_USERS';
|
|
||||||
|
|
||||||
export const resetUsers = list => {
|
|
||||||
return {
|
|
||||||
type: RESET_USERS,
|
|
||||||
payload: list
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,11 +1,10 @@
|
||||||
import * as actionTypes from './actions/actions'
|
|
||||||
|
|
||||||
const usersReducer = (state = [], action) => {
|
import {observable, action} from 'mobx';
|
||||||
if (action.type == actionTypes.RESET_USERS) {
|
|
||||||
return [...action.payload];
|
export class storeUsers {
|
||||||
|
@observable users = []
|
||||||
|
|
||||||
|
@action reset(users) {
|
||||||
|
this.users = Object.values(users)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default usersReducer
|
|
|
@ -1,24 +1,34 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component, useEffect } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { observer, inject } from "mobx-react";
|
||||||
import { Popover, List, ListItem, Navbar, NavTitle, NavRight } from 'framework7-react';
|
import { Popover, List, ListItem, Navbar, NavTitle, NavRight } from 'framework7-react';
|
||||||
import { Sheet, Toolbar, BlockTitle, Link, Page, View, Icon } from 'framework7-react';
|
import { Sheet, Toolbar, BlockTitle, Link, Page, View, Icon } from 'framework7-react';
|
||||||
|
import { f7 } from 'framework7-react';
|
||||||
import { withTranslation, useTranslation } from 'react-i18next';
|
import { withTranslation, useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const PageUsers = () => {
|
@inject('users')
|
||||||
const { t } = useTranslation();
|
@observer
|
||||||
const userlist = useSelector(state => state.users);
|
class PageUsers extends Component {
|
||||||
|
constructor(props){
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { t } = this.props;
|
||||||
|
const userlist = this.props.users;
|
||||||
return (
|
return (
|
||||||
<Page name="collab__users">
|
<Page name="collab__users">
|
||||||
<Navbar title="Users" backLink="Back"></Navbar>
|
<Navbar title="Users" backLink="Back"></Navbar>
|
||||||
<BlockTitle>{t("Collaboration.textEditUser")}</BlockTitle>
|
<BlockTitle>{t("Collaboration.textEditUser")}</BlockTitle>
|
||||||
<List className="coauth__list">
|
<List className="coauth__list">
|
||||||
{userlist.map((model, i) => (
|
{userlist.users.map((model, i) => (
|
||||||
<ListItem title={model.asc_getUserName()} key={i}>
|
<ListItem title={model.asc_getUserName()} key={i}>
|
||||||
<Icon slot="media" icon="coauth__list__icon" style={{ backgroundColor:model.asc_getColor() }}></Icon>
|
<Icon slot="media" icon="coauth__list__icon"
|
||||||
|
style={{backgroundColor: model.asc_getColor()}}></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
</Page>)
|
</Page>)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PageCollaboration = () => {
|
const PageCollaboration = () => {
|
||||||
|
@ -68,7 +78,7 @@ class CollaborationSheet extends Component {
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Sheet className="collab__sheet" push>
|
<Sheet className="coauth__sheet" push onSheetClosed={e => this.props.onclosed()}>
|
||||||
<View>
|
<View>
|
||||||
<PageCollaboration />
|
<PageCollaboration />
|
||||||
</View>
|
</View>
|
||||||
|
@ -77,5 +87,25 @@ class CollaborationSheet extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CollaborationView = props => {
|
||||||
|
useEffect(() => {
|
||||||
|
f7.sheet.open('.coauth__sheet');
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// component will unmount
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onviewclosed = () => {
|
||||||
|
if ( props.onclosed ) props.onclosed();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CollaborationSheet onclosed={onviewclosed} />
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageusers = withTranslation()(PageUsers);
|
||||||
// export withTranslation()(CollaborationPopover);
|
// export withTranslation()(CollaborationPopover);
|
||||||
export {CollaborationPopover, CollaborationSheet, PageCollaboration, PageUsers, }
|
export {CollaborationPopover, CollaborationSheet, PageCollaboration, pageusers as PageUsers}
|
||||||
|
export default CollaborationView;
|
||||||
|
|
52
apps/common/mobile/resources/less/common-ios.less
Normal file
52
apps/common/mobile/resources/less/common-ios.less
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
.device-ios {
|
||||||
|
.popover__titled {
|
||||||
|
.popover-inner {
|
||||||
|
//border-radius: var(--f7-popover-border-radius);
|
||||||
|
|
||||||
|
> .view {
|
||||||
|
border-radius: var(--f7-popover-border-radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-bg {
|
||||||
|
//-webkit-backdrop-filter: none;
|
||||||
|
backdrop-filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list:first-child {
|
||||||
|
li:first-child {
|
||||||
|
a {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list:last-child {
|
||||||
|
li:last-child {
|
||||||
|
a {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--f7-navbar-border-color, var(--f7-bars-border-color));
|
||||||
|
display: block;
|
||||||
|
//z-index: 15;
|
||||||
|
top: auto;
|
||||||
|
right: auto;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
transform-origin: 50% 100%;
|
||||||
|
transform: scaleY(calc(1 / var(--f7-device-pixel-ratio)));
|
||||||
|
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
apps/common/mobile/resources/less/common-material.less
Normal file
12
apps/common/mobile/resources/less/common-material.less
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
.device-android {
|
||||||
|
.popover__titled {
|
||||||
|
.list:last-child {
|
||||||
|
li:last-child {
|
||||||
|
a {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
apps/common/mobile/utils/device.jsx
Normal file
41
apps/common/mobile/utils/device.jsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { f7 } from 'framework7-react';
|
||||||
|
|
||||||
|
class Device {
|
||||||
|
constructor(){
|
||||||
|
const ua = navigator.userAgent,
|
||||||
|
isMobile = /Mobile(\/|\s|;)/.test(ua);
|
||||||
|
|
||||||
|
this.isPhone = /(iPhone|iPod)/.test(ua) ||
|
||||||
|
(!/(Silk)/.test(ua) && (/(Android)/.test(ua) && (/(Android 2)/.test(ua) || isMobile))) ||
|
||||||
|
(/(BlackBerry|BB)/.test(ua) && isMobile) ||
|
||||||
|
/(Windows Phone)/.test(ua);
|
||||||
|
|
||||||
|
this.isTablet = !this.isPhone && (/iPad/.test(ua) || /Android/.test(ua) || /(RIM Tablet OS)/.test(ua) ||
|
||||||
|
(/MSIE 10/.test(ua) && /; Touch/.test(ua)));
|
||||||
|
}
|
||||||
|
|
||||||
|
get phone() {
|
||||||
|
return this.isPhone
|
||||||
|
}
|
||||||
|
|
||||||
|
get tablet() {
|
||||||
|
return this.isTablet
|
||||||
|
}
|
||||||
|
|
||||||
|
get sailfish() {
|
||||||
|
return /Sailfish/.test(navigator.userAgent) || /Jolla/.test(navigator.userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
get android() {
|
||||||
|
return f7.device.android;
|
||||||
|
}
|
||||||
|
|
||||||
|
get ios() {
|
||||||
|
return f7.device.ios;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const device = new Device();
|
||||||
|
export {device as Device};
|
|
@ -19,5 +19,40 @@
|
||||||
},
|
},
|
||||||
"Collaboration": {
|
"Collaboration": {
|
||||||
"textEditUser": "Users who are editing the file:"
|
"textEditUser": "Users who are editing the file:"
|
||||||
|
},
|
||||||
|
"Edit": {
|
||||||
|
"textClose": "Close",
|
||||||
|
"textBack": "Back",
|
||||||
|
"textText": "Text",
|
||||||
|
"textParagraph": "Paragraph",
|
||||||
|
"textTable": "Table",
|
||||||
|
"textFooter": "Footer",
|
||||||
|
"textHeader": "Header",
|
||||||
|
"textShape": "Shape",
|
||||||
|
"textImage": "Image",
|
||||||
|
"textChart": "Chart",
|
||||||
|
"textHyperlink": "Hyperlink",
|
||||||
|
"textSelectObjectToEdit": "Select object to edit",
|
||||||
|
"textSettings": "Settings",
|
||||||
|
"textFontColor": "Font Color",
|
||||||
|
"textHighlightColor": "Highlight Color",
|
||||||
|
"textAdditionalFormatting": "Additional Formatting",
|
||||||
|
"textAdditional": "Additional",
|
||||||
|
"textBullets": "Bullets",
|
||||||
|
"textNumbers": "Numbers",
|
||||||
|
"textLineSpacing": "Line Spacing",
|
||||||
|
"textFonts": "Fonts",
|
||||||
|
"textAuto": "Auto",
|
||||||
|
"textPt": "pt",
|
||||||
|
"textSize": "Size",
|
||||||
|
"textAuto": "Auto",
|
||||||
|
"textStrikethrough": "Strikethrough",
|
||||||
|
"textDoubleStrikethrough": "Double Strikethrough",
|
||||||
|
"textSuperscript": "Superscript",
|
||||||
|
"textSubscript": "Subscript",
|
||||||
|
"textSmallCaps": "Small Caps",
|
||||||
|
"textAllCaps": "All Caps",
|
||||||
|
"textLetterSpacing": "Letter Spacing",
|
||||||
|
"textNone": "None"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { App, Panel, View, Popup, Page, Navbar, NavRight, Link, Block, BlockTitle, List, ListItem } from 'framework7-react';
|
|
||||||
|
|
||||||
import i18n from '../js/i18n';
|
import {App,Panel,Views,View,Popup,Page,Navbar,Toolbar,NavRight,Link,Block,BlockTitle,List,ListItem,ListInput,ListButton,BlockFooter} from 'framework7-react';
|
||||||
|
|
||||||
import routes from '../js/routes';
|
import routes from '../js/routes';
|
||||||
|
|
||||||
import { initApi } from '../store/actions/actions';
|
|
||||||
|
|
||||||
import '../../../../common/Gateway.js';
|
import '../../../../common/Gateway.js';
|
||||||
import '../../../../common/main/lib/util/utils.js';
|
import '../../../../common/main/lib/util/utils.js';
|
||||||
import { CollaborationController } from '../../../../common/mobile/lib/controller/Collaboration.jsx';
|
|
||||||
import Notifications from '../../../../common/mobile/utils/notifications.js'
|
import Notifications from '../../../../common/mobile/utils/notifications.js'
|
||||||
|
import MainController from '../controller/Main';
|
||||||
|
|
||||||
class ComponentApp extends React.Component {
|
export default class extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -23,20 +19,12 @@ class ComponentApp extends React.Component {
|
||||||
name: 'Desktop Editor', // App name
|
name: 'Desktop Editor', // App name
|
||||||
theme: 'auto', // Automatic theme detection
|
theme: 'auto', // Automatic theme detection
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// App routes
|
// App routes
|
||||||
routes: routes,
|
routes: routes,
|
||||||
},
|
},
|
||||||
// Login screen demo data
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.Notifications = new Notifications();
|
Common.Notifications = new Notifications();
|
||||||
|
|
||||||
Common.Controllers = {};
|
|
||||||
Common.Controllers.Collaboration = new CollaborationController();
|
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -70,6 +58,7 @@ class ComponentApp extends React.Component {
|
||||||
|
|
||||||
{/* Your main view, should have "view-main" class */}
|
{/* Your main view, should have "view-main" class */}
|
||||||
<View main className="safe-areas" url="/" />
|
<View main className="safe-areas" url="/" />
|
||||||
|
<MainController ref="mainController" />
|
||||||
|
|
||||||
{/* Popup */}
|
{/* Popup */}
|
||||||
<Popup id="my-popup">
|
<Popup id="my-popup">
|
||||||
|
@ -89,168 +78,12 @@ class ComponentApp extends React.Component {
|
||||||
</App>
|
</App>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
alertLoginData() {
|
|
||||||
this.$f7.dialog.alert('Username: ' + this.state.username + '<br>Password: ' + this.state.password, () => {
|
|
||||||
this.$f7.loginScreen.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.$f7ready((f7) => {
|
this.$f7ready((f7) => {
|
||||||
// Call F7 APIs here
|
// Call F7 APIs here
|
||||||
});
|
});
|
||||||
|
|
||||||
const script = document.createElement("script");
|
this.refs.mainController.initSdk();
|
||||||
script.src = "../../../../sdkjs/develop/sdkjs/word/scripts.js";
|
|
||||||
script.async = true;
|
|
||||||
script.onload = () => {
|
|
||||||
let dep_scripts = ['../../../vendor/xregexp/xregexp-all-min.js',
|
|
||||||
'../../../vendor/sockjs/sockjs.min.js',
|
|
||||||
'../../../vendor/jszip/jszip.min.js',
|
|
||||||
'../../../vendor/jszip-utils/jszip-utils.min.js'];
|
|
||||||
dep_scripts.push(...sdk_scripts);
|
|
||||||
|
|
||||||
const promise_get_script = (scriptpath) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const script = document.createElement("script");
|
|
||||||
script.src = scriptpath;
|
|
||||||
script.onload = () => {
|
|
||||||
console.log('loaded ' + scriptpath);
|
|
||||||
resolve('ok');
|
|
||||||
};
|
|
||||||
script.onerror = () => {
|
|
||||||
console.log('error ' + scriptpath);
|
|
||||||
reject('error');
|
|
||||||
};
|
|
||||||
|
|
||||||
document.body.appendChild(script);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadConfig = data => {
|
|
||||||
let me = this;
|
|
||||||
console.log('load config');
|
|
||||||
|
|
||||||
me.editorConfig = Object.assign({}, this.editorConfig, data.config);
|
|
||||||
me.appOptions.user = Common.Utils.fillUserInfo(me.editorConfig.user, me.editorConfig.lang, "Local.User"/*me.textAnonymous*/);
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadDocument = data => {
|
|
||||||
this.permissions = {};
|
|
||||||
this.document = data.doc;
|
|
||||||
|
|
||||||
let docInfo = {};
|
|
||||||
|
|
||||||
if (data.doc) {
|
|
||||||
this.permissions = Object.assign(this.permissions, data.doc.permissions);
|
|
||||||
|
|
||||||
let _permissions = Object.assign({}, data.doc.permissions),
|
|
||||||
_user = new Asc.asc_CUserInfo();
|
|
||||||
_user.put_Id(this.appOptions.user.id);
|
|
||||||
_user.put_FullName(this.appOptions.user.fullname);
|
|
||||||
|
|
||||||
docInfo = new Asc.asc_CDocInfo();
|
|
||||||
docInfo.put_Id(data.doc.key);
|
|
||||||
docInfo.put_Url(data.doc.url);
|
|
||||||
docInfo.put_Title(data.doc.title);
|
|
||||||
docInfo.put_Format(data.doc.fileType);
|
|
||||||
docInfo.put_VKey(data.doc.vkey);
|
|
||||||
docInfo.put_Options(data.doc.options);
|
|
||||||
docInfo.put_UserInfo(_user);
|
|
||||||
docInfo.put_CallbackUrl(this.editorConfig.callbackUrl);
|
|
||||||
docInfo.put_Token(data.doc.token);
|
|
||||||
docInfo.put_Permissions(_permissions);
|
|
||||||
docInfo.put_EncryptedInfo(this.editorConfig.encryptionKeys);
|
|
||||||
|
|
||||||
// var enable = !this.editorConfig.customization || (this.editorConfig.customization.macros!==false);
|
|
||||||
// docInfo.asc_putIsEnabledMacroses(!!enable);
|
|
||||||
// enable = !this.editorConfig.customization || (this.editorConfig.customization.plugins!==false);
|
|
||||||
// docInfo.asc_putIsEnabledPlugins(!!enable);
|
|
||||||
|
|
||||||
// let type = /^(?:(pdf|djvu|xps))$/.exec(data.doc.fileType);
|
|
||||||
// if (type && typeof type[1] === 'string') {
|
|
||||||
// this.permissions.edit = this.permissions.review = false;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
this.api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
|
|
||||||
// this.api.asc_registerCallback('asc_onLicenseChanged', _.bind(this.onLicenseChanged, this));
|
|
||||||
// this.api.asc_registerCallback('asc_onRunAutostartMacroses', _.bind(this.onRunAutostartMacroses, this));
|
|
||||||
this.api.asc_setDocInfo(docInfo);
|
|
||||||
this.api.asc_getEditorPermissions(this.editorConfig.licenseUrl, this.editorConfig.customerId);
|
|
||||||
|
|
||||||
// Common.SharedSettings.set('document', data.doc);
|
|
||||||
|
|
||||||
// if (data.doc) {
|
|
||||||
// DE.getController('Toolbar').setDocumentTitle(data.doc.title);
|
|
||||||
// if (data.doc.info) {
|
|
||||||
// data.doc.info.author && console.log("Obsolete: The 'author' parameter of the document 'info' section is deprecated. Please use 'owner' instead.");
|
|
||||||
// data.doc.info.created && console.log("Obsolete: The 'created' parameter of the document 'info' section is deprecated. Please use 'uploaded' instead.");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEditorPermissions = params => {
|
|
||||||
let me = this;
|
|
||||||
const licType = params.asc_getLicenseType();
|
|
||||||
|
|
||||||
me.appOptions.canLicense = (licType === Asc.c_oLicenseResult.Success || licType === Asc.c_oLicenseResult.SuccessLimit);
|
|
||||||
// me.appOptions.canEdit = (me.permissions.edit !== false || me.permissions.review === true) && // can edit or review
|
|
||||||
// (me.editorConfig.canRequestEditRights || me.editorConfig.mode !== 'view') && // if mode=="view" -> canRequestEditRights must be defined
|
|
||||||
// (!me.appOptions.isReviewOnly || me.appOptions.canLicense) && // if isReviewOnly==true -> canLicense must be true
|
|
||||||
// me.isSupportEditFeature();
|
|
||||||
// me.appOptions.isEdit = me.appOptions.canLicense && me.appOptions.canEdit && me.editorConfig.mode !== 'view';
|
|
||||||
|
|
||||||
// me.api.asc_setViewMode(!me.appOptions.isEdit);
|
|
||||||
me.api.asc_setViewMode(false);
|
|
||||||
me.api.asc_LoadDocument();
|
|
||||||
me.api.Resize();
|
|
||||||
};
|
|
||||||
|
|
||||||
const _process_array = (array, fn) => {
|
|
||||||
let results = [];
|
|
||||||
return array.reduce(function(p, item) {
|
|
||||||
return p.then(function() {
|
|
||||||
return fn(item).then(function(data) {
|
|
||||||
results.push(data);
|
|
||||||
return results;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, Promise.resolve());
|
|
||||||
};
|
|
||||||
|
|
||||||
_process_array(dep_scripts, promise_get_script)
|
|
||||||
.then ( result => {
|
|
||||||
this.api = new Asc.asc_docs_api({
|
|
||||||
'id-view' : 'editor_sdk',
|
|
||||||
'mobile' : true,
|
|
||||||
// 'translate': translate
|
|
||||||
});
|
|
||||||
|
|
||||||
this.appOptions = {};
|
|
||||||
|
|
||||||
Common.Gateway.on('init', loadConfig);
|
|
||||||
// Common.Gateway.on('showmessage', _.bind(me.onExternalMessage, me));
|
|
||||||
Common.Gateway.on('opendocument', loadDocument);
|
|
||||||
Common.Gateway.appReady();
|
|
||||||
|
|
||||||
Common.Notifications.trigger('engineCreated', this.api);
|
|
||||||
const { initApi } = this.props;
|
|
||||||
initApi(this.api);
|
|
||||||
}, error => {
|
|
||||||
console.log('promise failed ' + error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
script.onerror = () => {
|
|
||||||
console.log('error');
|
|
||||||
};
|
|
||||||
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => bindActionCreators({
|
|
||||||
initApi
|
|
||||||
}, dispatch);
|
|
||||||
|
|
||||||
export default connect(undefined, mapDispatchToProps)(ComponentApp);
|
|
||||||
|
|
|
@ -1,57 +1,162 @@
|
||||||
import React, {Component} from 'react';
|
import React, {useState, useEffect} from 'react';
|
||||||
import {
|
import {observer, inject} from "mobx-react";
|
||||||
Page,
|
import { Page, Navbar, NavRight, NavLeft, NavTitle, Link, Sheet, Tabs, Tab, View } from 'framework7-react';
|
||||||
Navbar,
|
import { f7 } from 'framework7-react';
|
||||||
NavRight,
|
import { useTranslation } from 'react-i18next';
|
||||||
NavLeft,
|
import EditTextController from "./controller/EditText";
|
||||||
Link,
|
|
||||||
Popup,
|
|
||||||
Tabs,
|
|
||||||
Tab
|
|
||||||
} from 'framework7-react';
|
|
||||||
import EditText from "./EditText";
|
|
||||||
import EditParagraph from "./EditParagraph";
|
import EditParagraph from "./EditParagraph";
|
||||||
|
|
||||||
export default class EditContainer extends Component {
|
const EmptyEditLayout = () => {
|
||||||
constructor(props) {
|
const { t } = useTranslation();
|
||||||
super(props);
|
return (
|
||||||
this.state = {
|
<Page>
|
||||||
popupOpened: false,
|
<div className="content-block inset">
|
||||||
};
|
<div className="content-block-inner">
|
||||||
}
|
<p>{t("Edit.textSelectObjectToEdit")}</p>
|
||||||
render() {
|
</div>
|
||||||
const editors = ['text', 'paragraph'];//, 'table', 'header', 'shape', 'image', 'chart', 'hyperlink'];
|
</div>
|
||||||
const tabLinks = editors.map((item, index) =>
|
</Page>
|
||||||
<Link key={"de-tablink-" + item} tabLink={"#" + item} tabLinkActive={index === 0}>{item}</Link>
|
)
|
||||||
);
|
};
|
||||||
const tabs = editors.map((item, index) =>
|
|
||||||
<Tab key={"de-tab-" + item} id={item} className="page-content" tabActive={index === 0}>
|
const EditLayoutNavbar = ({ editors }) => {
|
||||||
{item === 'text' && <EditText />}
|
const { t } = useTranslation();
|
||||||
{item === 'paragraph' && <EditParagraph />}
|
|
||||||
{/*{item === 'table' && <EditTable />}
|
|
||||||
{item === 'header' && <EditHeader />}
|
|
||||||
{item === 'shape' && <EditShape />}
|
|
||||||
{item === 'image' && <EditImage />}
|
|
||||||
{item === 'chart' && <EditChart />}
|
|
||||||
{item === 'hyperlink' && <EditHyperlink />}*/}
|
|
||||||
</Tab>
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<Popup className="edit-popup" opened={this.state.popupOpened} onPopupClosed={() => this.setState({popupOpened : false})}>
|
|
||||||
<Page pageContent={false}>
|
|
||||||
<Navbar>
|
<Navbar>
|
||||||
|
{
|
||||||
|
editors.length > 1 ?
|
||||||
<NavLeft tabbar>
|
<NavLeft tabbar>
|
||||||
{tabLinks}
|
{editors.map((item, index) => <Link key={"de-link-" + item.id} tabLink={"#" + item.id} tabLinkActive={index === 0}>{item.caption}</Link>)}
|
||||||
</NavLeft>
|
</NavLeft> :
|
||||||
|
<NavTitle>{ editors[0].caption }</NavTitle>
|
||||||
|
}
|
||||||
<NavRight>
|
<NavRight>
|
||||||
<Link popupClose=".edit-popup">Close</Link>
|
<Link sheetClose>{t("Edit.textClose")}</Link>
|
||||||
</NavRight>
|
</NavRight>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditLayoutContent = ({ editors }) => {
|
||||||
|
if (editors.length > 1) {
|
||||||
|
return (
|
||||||
<Tabs animated>
|
<Tabs animated>
|
||||||
{tabs}
|
{editors.map((item, index) =>
|
||||||
|
<Tab key={"de-tab-" + item.id} id={item.id} className="page-content" tabActive={index === 0}>
|
||||||
|
{item.component}
|
||||||
|
</Tab>
|
||||||
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
{editors[0].component}
|
||||||
</Page>
|
</Page>
|
||||||
</Popup>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EditSheet = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const settings = props.storeFocusObjects.settings;
|
||||||
|
const headerType = props.storeFocusObjects.headerType;
|
||||||
|
let editors = [];
|
||||||
|
if (settings.length < 1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textSettings"),
|
||||||
|
component: <EmptyEditLayout />
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (settings.indexOf('text') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textText"),
|
||||||
|
id: 'edit-text',
|
||||||
|
component: <EditTextController />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('paragraph') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textParagraph"),
|
||||||
|
id: 'edit-paragraph',
|
||||||
|
component: <EditParagraph />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/*if (settings.indexOf('table') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textTable"),
|
||||||
|
id: 'edit-table',
|
||||||
|
component: <EditTable />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('header') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: headerType==2 ? t("Edit.textFooter") : t("Edit.textHeader"),
|
||||||
|
id: 'edit-header',
|
||||||
|
component: <EditHeader />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('shape') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textShape"),
|
||||||
|
id: 'edit-shape',
|
||||||
|
component: <EditShape />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('image') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textImage"),
|
||||||
|
id: 'edit-image',
|
||||||
|
component: <EditImage />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('chart') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textChart"),
|
||||||
|
id: 'edit-chart',
|
||||||
|
component: <EditChart />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (settings.indexOf('hyperlink') > -1) {
|
||||||
|
editors.push({
|
||||||
|
caption: t("Edit.textHyperlink"),
|
||||||
|
id: 'edit-link',
|
||||||
|
component: <EditHyperlink />
|
||||||
|
})
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sheet className="edit__sheet" push onSheetClosed={e => props.onclosed()}>
|
||||||
|
<View>
|
||||||
|
<Page pageContent={false}>
|
||||||
|
<EditLayoutNavbar editors={editors} />
|
||||||
|
<EditLayoutContent editors={editors} />
|
||||||
|
</Page>
|
||||||
|
</View>
|
||||||
|
</Sheet>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const HOC_EditSheet = inject("storeFocusObjects")(observer(EditSheet));
|
||||||
|
|
||||||
|
const EditOptions = props => {
|
||||||
|
useEffect(() => {
|
||||||
|
f7.sheet.open('.edit__sheet');
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// component will unmount
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onsheetclosed = () => {
|
||||||
|
if ( props.onclosed ) props.onclosed();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HOC_EditSheet onclosed={onsheetclosed} />
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditOptions;
|
||||||
|
|
|
@ -1,96 +1,301 @@
|
||||||
import React, {Component, Fragment} from 'react';
|
import React, {Fragment, useState} from 'react';
|
||||||
import {
|
import {observer, inject} from "mobx-react";
|
||||||
List,
|
import {List, ListItem, Icon, Row, Col, Button, Page, Navbar, Segmented, BlockTitle} from 'framework7-react';
|
||||||
ListItem,
|
import { useTranslation } from 'react-i18next';
|
||||||
Icon,
|
|
||||||
Row,
|
|
||||||
Col,
|
|
||||||
Button
|
|
||||||
} from 'framework7-react';
|
|
||||||
|
|
||||||
export default class EditText extends Component {
|
const PageFonts = props => {
|
||||||
constructor(props) {
|
const { t } = useTranslation();
|
||||||
super(props);
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const size = storeTextSettings.fontSize;
|
||||||
|
const displaySize = typeof size === 'undefined' ? t('Edit.textAuto') : size + ' ' + t('Edit.textPt');
|
||||||
|
const curFontName = storeTextSettings.fontName;
|
||||||
|
const fonts = storeTextSettings.fontsArray;
|
||||||
|
const [vlFonts, setVlFonts] = useState({
|
||||||
|
vlData: {
|
||||||
|
items: [],
|
||||||
}
|
}
|
||||||
render() {
|
});
|
||||||
const textFontColor = "Font Color";
|
const renderExternal = (vl, vlData) => {
|
||||||
const textHighlightColor = "Highlight Color";
|
setVlFonts((prevState) => {
|
||||||
const textAdditionalFormatting = "Additional Formatting";
|
let fonts = [...prevState.vlData.items];
|
||||||
const textBullets = "Bullets";
|
fonts.splice(vlData.fromIndex, vlData.toIndex, ...vlData.items);
|
||||||
const textNumbers = "Numbers";
|
return {vlData: {
|
||||||
const textLineSpacing = "Line Spacing";
|
items: fonts,
|
||||||
|
}}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<Navbar title={t('Edit.textFonts')} backLink={t('Edit.textBack')} />
|
||||||
|
<List>
|
||||||
|
<ListItem title={t('Edit.textSize')}>
|
||||||
|
<div slot='after-start'>{displaySize}</div>
|
||||||
|
<div slot='after'>
|
||||||
|
<Segmented>
|
||||||
|
<Button outline className='decrement' onClick={() => {props.changeFontSize(size, true)}}> - </Button>
|
||||||
|
<Button outline className='increment' onClick={() => {props.changeFontSize(size, false)}}> + </Button>
|
||||||
|
</Segmented>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
<BlockTitle>{t('Edit.textFonts')}</BlockTitle>
|
||||||
|
<List virtualList virtualListParams={{
|
||||||
|
items: fonts,
|
||||||
|
renderExternal: renderExternal
|
||||||
|
}}>
|
||||||
|
<ul>
|
||||||
|
{vlFonts.vlData.items.map((item, index) => (
|
||||||
|
<ListItem
|
||||||
|
key={index}
|
||||||
|
radio
|
||||||
|
checked={curFontName === item.name}
|
||||||
|
title={item.name}
|
||||||
|
style={{fontFamily: `${item.name}`}}
|
||||||
|
onClick={() => {props.changeFontFamily(item.name)}}
|
||||||
|
></ListItem>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
const fontName = 'Arial';
|
const PageAdditionalFormatting = props => {
|
||||||
const fontSize = '11pt';
|
const { t } = useTranslation();
|
||||||
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const storeFocusObjects = props.storeFocusObjects;
|
||||||
|
const paragraph = storeFocusObjects.paragraphObject;
|
||||||
|
const isStrikeout = paragraph.get_Strikeout();
|
||||||
|
const isDStrikeout = paragraph.get_DStrikeout();
|
||||||
|
const isSuperscript = storeTextSettings.isSuperscript;
|
||||||
|
const isSubscript = storeTextSettings.isSubscript;
|
||||||
|
const isSmallCaps = paragraph.get_SmallCaps();
|
||||||
|
const isAllCaps = paragraph.get_AllCaps();
|
||||||
|
const letterSpacing = Common.Utils.Metric.fnRecalcFromMM(paragraph.get_TextSpacing());
|
||||||
|
return(
|
||||||
|
<Page>
|
||||||
|
<Navbar title={t('Edit.textAdditional')} backLink={t('Edit.textBack')} />
|
||||||
|
<List>
|
||||||
|
<ListItem title={t('Edit.textStrikethrough')} radio checked={isStrikeout} onClick={() => {props.onAdditionalStrikethrough('strikeout', !isStrikeout)}}/>
|
||||||
|
<ListItem title={t('Edit.textDoubleStrikethrough')} radio checked={isDStrikeout} onClick={() => {props.onAdditionalStrikethrough('dbStrikeout', !isDStrikeout)}}/>
|
||||||
|
<ListItem title={t('Edit.textSuperscript')} radio checked={isSuperscript} onClick={() => {props.onAdditionalScript('superscript', !isSuperscript)}}/>
|
||||||
|
<ListItem title={t('Edit.textSubscript')} radio checked={isSubscript} onClick={() => {props.onAdditionalScript('subscript', !isSubscript)}}/>
|
||||||
|
<ListItem title={t('Edit.textSmallCaps')} radio checked={isSmallCaps} onClick={() => {props.onAdditionalCaps('small', !isSmallCaps)}}/>
|
||||||
|
<ListItem title={t('Edit.textAllCaps')} radio checked={isAllCaps} onClick={() => {props.onAdditionalCaps('all', !isAllCaps)}}/>
|
||||||
|
</List>
|
||||||
|
<List>
|
||||||
|
<ListItem title={t('Edit.textLetterSpacing')}>
|
||||||
|
<div slot='after-start'>{letterSpacing + ' ' + Common.Utils.Metric.getCurrentMetricName()}</div>
|
||||||
|
<div slot='after'>
|
||||||
|
<Segmented>
|
||||||
|
<Button outline className='decrement' onClick={() => {props.changeLetterSpacing(letterSpacing, true)}}> - </Button>
|
||||||
|
<Button outline className='increment' onClick={() => {props.changeLetterSpacing(letterSpacing, false)}}> + </Button>
|
||||||
|
</Segmented>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
import bulletImg1 from '../../../resources/img/bullets/bullet-01.png';
|
||||||
|
import bulletImg2 from '../../../resources/img/bullets/bullet-02.png';
|
||||||
|
import bulletImg3 from '../../../resources/img/bullets/bullet-03.png';
|
||||||
|
import bulletImg4 from '../../../resources/img/bullets/bullet-04.png';
|
||||||
|
import bulletImg5 from '../../../resources/img/bullets/bullet-05.png';
|
||||||
|
import bulletImg6 from '../../../resources/img/bullets/bullet-06.png';
|
||||||
|
import bulletImg7 from '../../../resources/img/bullets/bullet-07.png';
|
||||||
|
const PageBullets = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const bulletArrays = [
|
||||||
|
[
|
||||||
|
{type: -1, thumb: ''},
|
||||||
|
{type: 1, thumb: bulletImg1},
|
||||||
|
{type: 2, thumb: bulletImg2},
|
||||||
|
{type: 3, thumb: bulletImg3}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{type: 4, thumb: bulletImg4},
|
||||||
|
{type: 5, thumb: bulletImg5},
|
||||||
|
{type: 6, thumb: bulletImg6},
|
||||||
|
{type: 7, thumb: bulletImg7}
|
||||||
|
]
|
||||||
|
];
|
||||||
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const typeBullets = storeTextSettings.typeBullets;
|
||||||
|
return(
|
||||||
|
<Page>
|
||||||
|
<Navbar title={t('Edit.textBullets')} backLink={t('Edit.textBack')} />
|
||||||
|
{bulletArrays.map((bullets, index) => (
|
||||||
|
<ul className="row" style={{listStyle: 'none'}} key={'bullets-' + index}>
|
||||||
|
{bullets.map((bullet) => (
|
||||||
|
<li key={'bullet-' + bullet.type} data-type={bullet.type} className={bullet.type === typeBullets ? 'active' : ''} onClick={() => {props.onBullet(bullet.type)}}>
|
||||||
|
{bullet.thumb.length < 1 ?
|
||||||
|
<div className="thumb" style={{position: 'relative'}}>
|
||||||
|
<label>{t('Edit.textNone')}</label>
|
||||||
|
</div> :
|
||||||
|
<div className="thumb" style={{height: '70px', width: '70px', backgroundImage: `url("${bullet.thumb}")`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center'}}></div>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
))}
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
import numberImg1 from '../../../resources/img/numbers/number-01.png';
|
||||||
|
import numberImg2 from '../../../resources/img/numbers/number-02.png';
|
||||||
|
import numberImg3 from '../../../resources/img/numbers/number-03.png';
|
||||||
|
import numberImg4 from '../../../resources/img/numbers/number-04.png';
|
||||||
|
import numberImg5 from '../../../resources/img/numbers/number-05.png';
|
||||||
|
import numberImg6 from '../../../resources/img/numbers/number-06.png';
|
||||||
|
import numberImg7 from '../../../resources/img/numbers/number-07.png';
|
||||||
|
const PageNumbers = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const numberArrays = [
|
||||||
|
[
|
||||||
|
{type: -1, thumb: ''},
|
||||||
|
{type: 4, thumb: numberImg1},
|
||||||
|
{type: 5, thumb: numberImg2},
|
||||||
|
{type: 6, thumb: numberImg3}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{type: 1, thumb: numberImg4},
|
||||||
|
{type: 2, thumb: numberImg5},
|
||||||
|
{type: 3, thumb: numberImg6},
|
||||||
|
{type: 7, thumb: numberImg7}
|
||||||
|
]
|
||||||
|
];
|
||||||
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const typeNumbers = storeTextSettings.typeNumbers;
|
||||||
|
return(
|
||||||
|
<Page>
|
||||||
|
<Navbar title={t('Edit.textNumbers')} backLink={t('Edit.textBack')} />
|
||||||
|
{numberArrays.map((numbers, index) => (
|
||||||
|
<ul className="row" style={{listStyle: 'none'}} key={'numbers-' + index}>
|
||||||
|
{numbers.map((number) => (
|
||||||
|
<li key={'number-' + number.type} data-type={number.type} className={number.type === typeNumbers ? 'active' : ''} onClick={() => {props.onNumber(number.type)}}>
|
||||||
|
{number.thumb.length < 1 ?
|
||||||
|
<div className="thumb" style={{position: 'relative'}}>
|
||||||
|
<label>{t('Edit.textNone')}</label>
|
||||||
|
</div> :
|
||||||
|
<div className="thumb" style={{height: '70px', width: '70px', backgroundImage: `url("${number.thumb}")`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center'}}></div>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
))}
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageLineSpacing = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const lineSpacing = storeTextSettings.lineSpacing;
|
||||||
|
return(
|
||||||
|
<Page>
|
||||||
|
<Navbar title={t('Edit.textLineSpacing')} backLink={t('Edit.textBack')} />
|
||||||
|
<List>
|
||||||
|
<ListItem radio checked={lineSpacing === 1.0} title={1.0} onClick={() => {props.onLineSpacing(1.0)}}></ListItem>
|
||||||
|
<ListItem radio checked={lineSpacing === 1.15} title={1.15} onClick={() => {props.onLineSpacing(1.15)}}></ListItem>
|
||||||
|
<ListItem radio checked={lineSpacing === 1.5} title={1.5} onClick={() => {props.onLineSpacing(1.5)}}></ListItem>
|
||||||
|
<ListItem radio checked={lineSpacing === 2.0} title={2.0} onClick={() => {props.onLineSpacing(2.0)}}></ListItem>
|
||||||
|
<ListItem radio checked={lineSpacing === 2.5} title={2.5} onClick={() => {props.onLineSpacing(2.5)}}></ListItem>
|
||||||
|
<ListItem radio checked={lineSpacing === 3.0} title={3.0} onClick={() => {props.onLineSpacing(3.0)}}></ListItem>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditText = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const storeTextSettings = props.storeTextSettings;
|
||||||
|
const fontName = storeTextSettings.fontName || t('Edit.textFonts');
|
||||||
|
const fontSize = storeTextSettings.fontSize;
|
||||||
|
const displaySize = typeof fontSize === 'undefined' ? t('Edit.textAuto') : fontSize + ' ' + t('Edit.textPt');
|
||||||
|
const isBold = storeTextSettings.isBold;
|
||||||
|
const isItalic = storeTextSettings.isItalic;
|
||||||
|
const isUnderline = storeTextSettings.isUnderline;
|
||||||
|
const isStrikethrough = storeTextSettings.Strikethrough;
|
||||||
|
const paragraphAlign = storeTextSettings.paragraphAlign;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<List>
|
<List>
|
||||||
<ListItem title={fontName} link="#" after={fontSize}></ListItem>
|
<ListItem title={fontName} link="/edit-text-fonts/" after={displaySize} routeProps={{
|
||||||
|
changeFontSize: props.changeFontSize,
|
||||||
|
changeFontFamily: props.changeFontFamily
|
||||||
|
}}/>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<a className={'button' + (isBold ? ' active' : '')} onClick={() => { props.toggleBold(!isBold)}}><b>B</b></a>
|
||||||
<Button>Button</Button>
|
<a className={'button' + (isItalic ? ' active' : '')} onClick={() => {props.toggleItalic(!isItalic)}}><i>I</i></a>
|
||||||
</Col>
|
<a className={'button' + (isUnderline ? ' active' : '')} onClick={() => {props.toggleUnderline(!isUnderline)}} style={{textDecoration: "underline"}}>U</a>
|
||||||
<Col>
|
<a className={'button' + (isStrikethrough ? ' active' : '')} onClick={() => {props.toggleStrikethrough(!isStrikethrough)}} style={{textDecoration: "line-through"}}>S</a>
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textFontColor} link="#">
|
<ListItem title={t("Edit.textFontColor")} link="#">
|
||||||
<Icon slot="media" icon="icon-text-color"></Icon>
|
<Icon slot="media" icon="icon-text-color"></Icon>
|
||||||
<span className="color-preview"></span>
|
<span className="color-preview"></span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textHighlightColor} link="#">
|
<ListItem title={t("Edit.textHighlightColor")} link="#">
|
||||||
<Icon slot="media" icon="icon-text-selection"></Icon>
|
<Icon slot="media" icon="icon-text-selection"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textAdditionalFormatting} link="#">
|
<ListItem title={t("Edit.textAdditionalFormatting")} link="/edit-text-add-formatting/" routeProps={{
|
||||||
|
onAdditionalStrikethrough: props.onAdditionalStrikethrough,
|
||||||
|
onAdditionalCaps: props.onAdditionalCaps,
|
||||||
|
onAdditionalScript: props.onAdditionalScript,
|
||||||
|
changeLetterSpacing: props.changeLetterSpacing
|
||||||
|
}}>
|
||||||
<Icon slot="media" icon="icon-text-additional"></Icon>
|
<Icon slot="media" icon="icon-text-additional"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
<List>
|
<List>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<a className={'button' + (paragraphAlign === 'left' ? ' active' : '')} onClick={() => {props.onParagraphAlign('left')}}>left</a>
|
||||||
<Button>Button</Button>
|
<a className={'button' + (paragraphAlign === 'center' ? ' active' : '')} onClick={() => {props.onParagraphAlign('center')}}>center</a>
|
||||||
</Col>
|
<a className={'button' + (paragraphAlign === 'right' ? ' active' : '')} onClick={() => {props.onParagraphAlign('right')}}>right</a>
|
||||||
<Col>
|
<a className={'button' + (paragraphAlign === 'just' ? ' active' : '')} onClick={() => {props.onParagraphAlign('just')}}>just</a>
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<a className='button' onClick={() => {props.onParagraphMove(true)}}>moveleft</a>
|
||||||
<Button>Button</Button>
|
<a className='button' onClick={() => {props.onParagraphMove(false)}}>moveright</a>
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button>Button</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textBullets} link="#">
|
<ListItem title={t("Edit.textBullets")} link='/edit-text-bullets/' routeProps={{
|
||||||
|
onBullet: props.onBullet
|
||||||
|
}}>
|
||||||
<Icon slot="media" icon="icon-bullets"></Icon>
|
<Icon slot="media" icon="icon-bullets"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textNumbers} link="#">
|
<ListItem title={t("Edit.textNumbers")} link='/edit-text-numbers/' routeProps={{
|
||||||
|
onNumber: props.onNumber
|
||||||
|
}}>
|
||||||
<Icon slot="media" icon="icon-numbers"></Icon>
|
<Icon slot="media" icon="icon-numbers"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={textLineSpacing} link="#">
|
<ListItem title={t("Edit.textLineSpacing")} link='/edit-text-line-spacing/' routeProps={{
|
||||||
|
onLineSpacing: props.onLineSpacing
|
||||||
|
}}>
|
||||||
<Icon slot="media" icon="icon-linespacing"></Icon>
|
<Icon slot="media" icon="icon-linespacing"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EditTextContainer = inject("storeTextSettings", "storeFocusObjects")(observer(EditText));
|
||||||
|
const PageFontsContainer = inject("storeTextSettings", "storeFocusObjects")(observer(PageFonts));
|
||||||
|
const PageAddFormattingContainer = inject("storeTextSettings", "storeFocusObjects")(observer(PageAdditionalFormatting));
|
||||||
|
const PageBulletsContainer = inject("storeTextSettings")(observer(PageBullets));
|
||||||
|
const PageNumbersContainer = inject("storeTextSettings")(observer(PageNumbers));
|
||||||
|
const PageLineSpacingContainer = inject("storeTextSettings")(observer(PageLineSpacing));
|
||||||
|
|
||||||
|
export {EditTextContainer as EditText,
|
||||||
|
PageFontsContainer as PageFonts,
|
||||||
|
PageAddFormattingContainer as PageAdditionalFormatting,
|
||||||
|
PageBulletsContainer as PageBullets,
|
||||||
|
PageNumbersContainer as PageNumbers,
|
||||||
|
PageLineSpacingContainer as PageLineSpacing};
|
|
@ -0,0 +1,195 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import { EditText } from '../EditText'
|
||||||
|
|
||||||
|
class EditTextController extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
api && api.UpdateInterfaceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
changeFontSize(curSize, isDecrement) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
let size = curSize;
|
||||||
|
if (isDecrement) {
|
||||||
|
typeof size === 'undefined' ? api.FontSizeOut() : size = Math.max(1, --size);
|
||||||
|
} else {
|
||||||
|
typeof size === 'undefined' ? api.FontSizeIn : size = Math.min(100, ++size);
|
||||||
|
}
|
||||||
|
if (typeof size !== 'undefined') {
|
||||||
|
api.put_TextPrFontSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeFontFamily(name) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api && name) {
|
||||||
|
api.put_TextPrFontName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleBold(value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_TextPrBold(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleItalic(value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_TextPrItalic(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleUnderline(value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_TextPrUnderline(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleStrikethrough(value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_TextPrStrikeout(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional
|
||||||
|
|
||||||
|
onAdditionalStrikethrough(type, value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
if ('strikeout' === type) {
|
||||||
|
api.put_TextPrStrikeout(value);
|
||||||
|
} else {
|
||||||
|
api.put_TextPrDStrikeout(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdditionalCaps(type, value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
const paragraphProps = new Asc.asc_CParagraphProperty();
|
||||||
|
if ('small' === type) {
|
||||||
|
paragraphProps.put_AllCaps(false);
|
||||||
|
paragraphProps.put_SmallCaps(value);
|
||||||
|
} else {
|
||||||
|
paragraphProps.put_AllCaps(value);
|
||||||
|
paragraphProps.put_SmallCaps(false);
|
||||||
|
}
|
||||||
|
api.paraApply(paragraphProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdditionalScript(type, value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
if ('superscript' === type) {
|
||||||
|
api.put_TextPrBaseline(value ? 1 : 0);
|
||||||
|
} else {
|
||||||
|
api.put_TextPrBaseline(value ? 2 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeLetterSpacing(curSpacing, isDecrement) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
let spacing = curSpacing;
|
||||||
|
if (isDecrement) {
|
||||||
|
spacing = Math.max(-100, --spacing);
|
||||||
|
} else {
|
||||||
|
spacing = Math.min(100, ++spacing);
|
||||||
|
}
|
||||||
|
const properties = new Asc.asc_CParagraphProperty();
|
||||||
|
properties.put_TextSpacing(Common.Utils.Metric.fnRecalcToMM(spacing));
|
||||||
|
api.paraApply(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onParagraphAlign(type) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
let value;
|
||||||
|
switch (type) {
|
||||||
|
case 'just':
|
||||||
|
value = 3;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
value = 0;
|
||||||
|
break;
|
||||||
|
case 'center':
|
||||||
|
value = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
api.put_PrAlign(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onParagraphMove(isLeft) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
if (isLeft) {
|
||||||
|
api.DecreaseIndent();
|
||||||
|
} else {
|
||||||
|
api.IncreaseIndent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBullet(type) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_ListType(0, parseInt(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onNumber(type) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
api.put_ListType(1, parseInt(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLineSpacing(value) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
if (api) {
|
||||||
|
const LINERULE_AUTO = 1;
|
||||||
|
api.put_PrLineSpacing(LINERULE_AUTO, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<EditText changeFontSize={this.changeFontSize}
|
||||||
|
changeFontFamily={this.changeFontFamily}
|
||||||
|
toggleBold={this.toggleBold}
|
||||||
|
toggleItalic={this.toggleItalic}
|
||||||
|
toggleUnderline={this.toggleUnderline}
|
||||||
|
toggleStrikethrough={this.toggleStrikethrough}
|
||||||
|
onAdditionalStrikethrough={this.onAdditionalStrikethrough}
|
||||||
|
onAdditionalCaps={this.onAdditionalCaps}
|
||||||
|
onAdditionalScript={this.onAdditionalScript}
|
||||||
|
changeLetterSpacing={this.changeLetterSpacing}
|
||||||
|
onParagraphAlign={this.onParagraphAlign}
|
||||||
|
onParagraphMove={this.onParagraphMove}
|
||||||
|
onBullet={this.onBullet}
|
||||||
|
onNumber={this.onNumber}
|
||||||
|
onLineSpacing={this.onLineSpacing}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditTextController;
|
|
@ -1,39 +1,65 @@
|
||||||
import React, { Component } from 'react';
|
import React, {Component, useEffect} from 'react';
|
||||||
import { View, Page, Navbar, NavRight, Link, Popup, Icon, ListItem, List } from 'framework7-react';
|
import {View,Page,Navbar,NavRight,Link,Popup,Popover,Icon,ListItem,List} from 'framework7-react';
|
||||||
import { withTranslation } from 'react-i18next';
|
import { withTranslation } from 'react-i18next';
|
||||||
import {changePageOrient} from "../../store/actions/actions";
|
import {f7} from 'framework7-react';
|
||||||
|
import {Device} from '../../../../../common/mobile/utils/device'
|
||||||
|
|
||||||
class Settings extends Component {
|
import DocumentSettingsController from "../settings/controller/DocumentSettings.jsx";
|
||||||
constructor(props) {
|
import Margins from "../settings/document-settings/Margins.jsx";
|
||||||
super(props);
|
import DocumentFormats from "../settings/document-settings/DocumentFormats.jsx";
|
||||||
this.state = {
|
|
||||||
popupOpened: false,
|
const routes = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: 'TSettingsView'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/document-settings/',
|
||||||
|
component: DocumentSettingsController,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/margins/',
|
||||||
|
component: Margins,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/document-formats/',
|
||||||
|
component: DocumentFormats,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const SettingsList = withTranslation()(props => {
|
||||||
|
const {t} = props;
|
||||||
|
const _t = t('ViewSettings', {returnObjects: true});
|
||||||
|
const navbar = <Navbar title={t('ViewSettings.textSettings')}>
|
||||||
|
{!props.inPopover && <NavRight><Link popupClose=".settings-popup">{t('ViewSettings.textDone')}</Link></NavRight>}
|
||||||
|
</Navbar>;
|
||||||
|
|
||||||
|
const onoptionclick = page => {
|
||||||
|
if ( props.onOptionClick )
|
||||||
|
props.onOptionClick(page)
|
||||||
};
|
};
|
||||||
}
|
|
||||||
render() {
|
useEffect(() => {
|
||||||
const { t } = this.props;
|
});
|
||||||
const _trarr = t('ViewSettings', {returnObjects: true});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popup className="settings-popup" opened={this.state.popupOpened} onPopupClosed={() => this.setState({popupOpened : false})}>
|
<View style={props.style} stackPages={true} routes={routes}>
|
||||||
<View>
|
|
||||||
<Page>
|
<Page>
|
||||||
<Navbar title={t('ViewSettings.textSettings')}>
|
{navbar}
|
||||||
<NavRight>
|
|
||||||
<Link popupClose=".settings-popup">{t('ViewSettings.textDone')}</Link>
|
|
||||||
</NavRight>
|
|
||||||
</Navbar>
|
|
||||||
<List>
|
<List>
|
||||||
<ListItem title={_trarr.textFindAndReplace}>
|
{!props.inPopover &&
|
||||||
|
<ListItem title={_t.textFindAndReplace}>
|
||||||
<Icon slot="media" icon="icon-search"></Icon>
|
<Icon slot="media" icon="icon-search"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={_trarr.textDocumentSettings} link="/document-settings/">
|
}
|
||||||
|
<ListItem link="#" title={_t.textDocumentSettings} onClick={onoptionclick.bind(this, '/document-settings/')}>
|
||||||
<Icon slot="media" icon="icon-doc-setup"></Icon>
|
<Icon slot="media" icon="icon-doc-setup"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={_trarr.textApplicationSettings} link="#">
|
<ListItem title={_t.textApplicationSettings} link="#">
|
||||||
<Icon slot="media" icon="icon-app-settings"></Icon>
|
<Icon slot="media" icon="icon-app-settings"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={_trarr.textDownload} link="#">
|
<ListItem title={_t.textDownload} link="#">
|
||||||
<Icon slot="media" icon="icon-download"></Icon>
|
<Icon slot="media" icon="icon-download"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={t('ViewSettings.textPrint')}>
|
<ListItem title={t('ViewSettings.textPrint')}>
|
||||||
|
@ -51,9 +77,56 @@ class Settings extends Component {
|
||||||
</List>
|
</List>
|
||||||
</Page>
|
</Page>
|
||||||
</View>
|
</View>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
class SettingsView extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.onoptionclick = this.onoptionclick.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onoptionclick(page){
|
||||||
|
this.$f7.views.current.router.navigate(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const show_popover = this.props.usePopover;
|
||||||
|
return (
|
||||||
|
show_popover ?
|
||||||
|
<Popover id="settings-popover" className="popover__titled" onPopoverClosed={() => this.props.onclosed()}>
|
||||||
|
<SettingsList inPopover={true} onOptionClick={this.onoptionclick} style={{height: '410px'}} />
|
||||||
|
</Popover> :
|
||||||
|
<Popup className="settings-popup" onPopupClosed={() => this.props.onclosed()}>
|
||||||
|
<SettingsList onOptionClick={this.onoptionclick} />
|
||||||
</Popup>
|
</Popup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Settings = props => {
|
||||||
|
useEffect(() => {
|
||||||
|
if ( Device.phone )
|
||||||
|
f7.popup.open('.settings-popup');
|
||||||
|
else f7.popover.open('#settings-popover', '#btn-settings');
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// component will unmount
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const onviewclosed = () => {
|
||||||
|
if ( props.onclosed )
|
||||||
|
props.onclosed();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withTranslation()(Settings);
|
// if ( Device.phone ) {
|
||||||
|
// return <SettingsPopup onclosed={onviewclosed} />
|
||||||
|
// }
|
||||||
|
|
||||||
|
return <SettingsView usePopover={!Device.phone} onclosed={onviewclosed} />
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Settings;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import DocumentSettings from '../document-settings/DocumentSettings'
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentSettingsController extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageOrientation(value){
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
api.change_PageOrient(value=='portrait');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<DocumentSettings onPageOrientation={this.onPageOrientation} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentSettingsController;
|
|
@ -1,27 +1,35 @@
|
||||||
import React from 'react';
|
import React, {Component} from 'react';
|
||||||
|
import {observer, inject} from "mobx-react";
|
||||||
import {Page,Navbar,List,ListItem,BlockTitle} from 'framework7-react';
|
import {Page,Navbar,List,ListItem,BlockTitle} from 'framework7-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const PageDocumentSettings = (props) => {
|
const DocumentSettings = props => {
|
||||||
const { t } = useTranslation();
|
const textDocumentSettings = "Document Settings";
|
||||||
|
const textBack = "Back";
|
||||||
|
const textOrientation = "Orientation";
|
||||||
|
const textPortrait = "Portrait";
|
||||||
|
const textLandscape = "Landscape";
|
||||||
|
const textFormat = "Format";
|
||||||
|
const textMargins = "Margins";
|
||||||
|
|
||||||
const format = "A4";
|
const format = "A4";
|
||||||
const formatSize = "21 cm x 29.7 cm";
|
const formatSize = "21 cm x 29.7 cm";
|
||||||
|
|
||||||
|
const storeSettings = props.storeDocumentSettings;
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<Navbar title={t('ViewSettings.textDocumentSettings')} backLink={t('ViewSettings.textBack')} />
|
<Navbar title={textDocumentSettings} backLink={textBack} />
|
||||||
<BlockTitle>{t('ViewSettings.textOrientation')}</BlockTitle>
|
<BlockTitle>{textOrientation}</BlockTitle>
|
||||||
<List>
|
<List>
|
||||||
<ListItem checkbox title={t('ViewSettings.textPortrait')} name="orientation-checkbox" checked={props.isPortrait} onClick={(e) => props.changePageOrient(true)}></ListItem>
|
<ListItem radio title={textPortrait} name="orientation-checkbox" checked={storeSettings.isPortrait} onClick={e => props.onPageOrientation('portrait')}></ListItem>
|
||||||
<ListItem checkbox title={t('ViewSettings.textLandscape')} name="orientation-checkbox" checked={!props.isPortrait} onClick={(e) => props.changePageOrient(false)}></ListItem>
|
<ListItem radio title={textLandscape} name="orientation-checkbox" checked={!storeSettings.isPortrait} onClick={e => props.onPageOrientation('landscape')}></ListItem>
|
||||||
</List>
|
</List>
|
||||||
<BlockTitle>{t('ViewSettings.textFormat')}</BlockTitle>
|
<BlockTitle>{textFormat}</BlockTitle>
|
||||||
<List mediaList>
|
<List mediaList>
|
||||||
<ListItem title={format} subtitle={formatSize} link="/document-formats/"></ListItem>
|
<ListItem title={format} subtitle={formatSize} link="/document-formats/"></ListItem>
|
||||||
<ListItem checkbox title={t('ViewSettings.textMargins')} link="/margins/"></ListItem>
|
<ListItem checkbox title={textMargins} link="/margins/"></ListItem>
|
||||||
</List>
|
</List>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PageDocumentSettings;
|
export default inject("storeDocumentSettings")(observer(DocumentSettings));
|
||||||
|
|
228
apps/documenteditor/mobile/src/controller/Main.jsx
Normal file
228
apps/documenteditor/mobile/src/controller/Main.jsx
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
|
||||||
|
import React, {Component} from 'react'
|
||||||
|
import {inject} from "mobx-react";
|
||||||
|
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
|
||||||
|
|
||||||
|
@inject("storeDocumentSettings", "storeFocusObjects", "storeTextSettings")
|
||||||
|
class MainController extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
initSdk() {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "../../../../sdkjs/develop/sdkjs/word/scripts.js";
|
||||||
|
script.async = true;
|
||||||
|
script.onload = () => {
|
||||||
|
let dep_scripts = ['../../../vendor/xregexp/xregexp-all-min.js',
|
||||||
|
'../../../vendor/sockjs/sockjs.min.js',
|
||||||
|
'../../../vendor/jszip/jszip.min.js',
|
||||||
|
'../../../vendor/jszip-utils/jszip-utils.min.js'];
|
||||||
|
dep_scripts.push(...sdk_scripts);
|
||||||
|
|
||||||
|
const promise_get_script = (scriptpath) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = scriptpath;
|
||||||
|
script.onload = () => {
|
||||||
|
resolve('ok');
|
||||||
|
};
|
||||||
|
script.onerror = () => {
|
||||||
|
reject('error');
|
||||||
|
};
|
||||||
|
|
||||||
|
document.body.appendChild(script);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadConfig = data => {
|
||||||
|
let me = this;
|
||||||
|
console.log('load config');
|
||||||
|
|
||||||
|
me.editorConfig = Object.assign({}, this.editorConfig, data.config);
|
||||||
|
me.appOptions.user = Common.Utils.fillUserInfo(me.editorConfig.user, me.editorConfig.lang, "Local.User"/*me.textAnonymous*/);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadDocument = data => {
|
||||||
|
this.permissions = {};
|
||||||
|
this.document = data.doc;
|
||||||
|
|
||||||
|
let docInfo = {};
|
||||||
|
|
||||||
|
if (data.doc) {
|
||||||
|
this.permissions = Object.assign(this.permissions, data.doc.permissions);
|
||||||
|
|
||||||
|
let _permissions = Object.assign({}, data.doc.permissions),
|
||||||
|
_user = new Asc.asc_CUserInfo();
|
||||||
|
_user.put_Id(this.appOptions.user.id);
|
||||||
|
_user.put_FullName(this.appOptions.user.fullname);
|
||||||
|
|
||||||
|
docInfo = new Asc.asc_CDocInfo();
|
||||||
|
docInfo.put_Id(data.doc.key);
|
||||||
|
docInfo.put_Url(data.doc.url);
|
||||||
|
docInfo.put_Title(data.doc.title);
|
||||||
|
docInfo.put_Format(data.doc.fileType);
|
||||||
|
docInfo.put_VKey(data.doc.vkey);
|
||||||
|
docInfo.put_Options(data.doc.options);
|
||||||
|
docInfo.put_UserInfo(_user);
|
||||||
|
docInfo.put_CallbackUrl(this.editorConfig.callbackUrl);
|
||||||
|
docInfo.put_Token(data.doc.token);
|
||||||
|
docInfo.put_Permissions(_permissions);
|
||||||
|
docInfo.put_EncryptedInfo(this.editorConfig.encryptionKeys);
|
||||||
|
|
||||||
|
// var enable = !this.editorConfig.customization || (this.editorConfig.customization.macros!==false);
|
||||||
|
// docInfo.asc_putIsEnabledMacroses(!!enable);
|
||||||
|
// enable = !this.editorConfig.customization || (this.editorConfig.customization.plugins!==false);
|
||||||
|
// docInfo.asc_putIsEnabledPlugins(!!enable);
|
||||||
|
|
||||||
|
// let type = /^(?:(pdf|djvu|xps))$/.exec(data.doc.fileType);
|
||||||
|
// if (type && typeof type[1] === 'string') {
|
||||||
|
// this.permissions.edit = this.permissions.review = false;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
|
||||||
|
// this.api.asc_registerCallback('asc_onLicenseChanged', _.bind(this.onLicenseChanged, this));
|
||||||
|
// this.api.asc_registerCallback('asc_onRunAutostartMacroses', _.bind(this.onRunAutostartMacroses, this));
|
||||||
|
this.api.asc_setDocInfo(docInfo);
|
||||||
|
this.api.asc_getEditorPermissions(this.editorConfig.licenseUrl, this.editorConfig.customerId);
|
||||||
|
|
||||||
|
// Common.SharedSettings.set('document', data.doc);
|
||||||
|
|
||||||
|
// if (data.doc) {
|
||||||
|
// DE.getController('Toolbar').setDocumentTitle(data.doc.title);
|
||||||
|
// if (data.doc.info) {
|
||||||
|
// data.doc.info.author && console.log("Obsolete: The 'author' parameter of the document 'info' section is deprecated. Please use 'owner' instead.");
|
||||||
|
// data.doc.info.created && console.log("Obsolete: The 'created' parameter of the document 'info' section is deprecated. Please use 'uploaded' instead.");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEditorPermissions = params => {
|
||||||
|
let me = this;
|
||||||
|
const licType = params.asc_getLicenseType();
|
||||||
|
|
||||||
|
me.appOptions.canLicense = (licType === Asc.c_oLicenseResult.Success || licType === Asc.c_oLicenseResult.SuccessLimit);
|
||||||
|
// me.appOptions.canEdit = (me.permissions.edit !== false || me.permissions.review === true) && // can edit or review
|
||||||
|
// (me.editorConfig.canRequestEditRights || me.editorConfig.mode !== 'view') && // if mode=="view" -> canRequestEditRights must be defined
|
||||||
|
// (!me.appOptions.isReviewOnly || me.appOptions.canLicense) && // if isReviewOnly==true -> canLicense must be true
|
||||||
|
// me.isSupportEditFeature();
|
||||||
|
// me.appOptions.isEdit = me.appOptions.canLicense && me.appOptions.canEdit && me.editorConfig.mode !== 'view';
|
||||||
|
|
||||||
|
// me.api.asc_setViewMode(!me.appOptions.isEdit);
|
||||||
|
me.api.asc_setViewMode(false);
|
||||||
|
me.api.asc_LoadDocument();
|
||||||
|
me.api.Resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
const _process_array = (array, fn) => {
|
||||||
|
let results = [];
|
||||||
|
return array.reduce(function(p, item) {
|
||||||
|
return p.then(function() {
|
||||||
|
return fn(item).then(function(data) {
|
||||||
|
results.push(data);
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, Promise.resolve());
|
||||||
|
};
|
||||||
|
|
||||||
|
_process_array(dep_scripts, promise_get_script)
|
||||||
|
.then ( result => {
|
||||||
|
this.api = new Asc.asc_docs_api({
|
||||||
|
'id-view' : 'editor_sdk',
|
||||||
|
'mobile' : true,
|
||||||
|
// 'translate': translate
|
||||||
|
});
|
||||||
|
|
||||||
|
this.appOptions = {};
|
||||||
|
this.bindEvents();
|
||||||
|
|
||||||
|
Common.Gateway.on('init', loadConfig);
|
||||||
|
// Common.Gateway.on('showmessage', _.bind(me.onExternalMessage, me));
|
||||||
|
Common.Gateway.on('opendocument', loadDocument);
|
||||||
|
Common.Gateway.appReady();
|
||||||
|
|
||||||
|
Common.Notifications.trigger('engineCreated', this.api);
|
||||||
|
Common.EditorApi = {get: () => this.api};
|
||||||
|
}, error => {
|
||||||
|
console.log('promise failed ' + error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
script.onerror = () => {
|
||||||
|
console.log('error');
|
||||||
|
};
|
||||||
|
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEvents() {
|
||||||
|
const storeSettings = this.props.storeDocumentSettings;
|
||||||
|
this.api.asc_registerCallback('asc_onPageOrient', isPortrait => {
|
||||||
|
storeSettings.isPortrait = isPortrait === true;
|
||||||
|
});
|
||||||
|
const storeFocusObjects = this.props.storeFocusObjects;
|
||||||
|
this.api.asc_registerCallback('asc_onFocusObject', objects => {
|
||||||
|
storeFocusObjects.resetFocusObjects(objects);
|
||||||
|
});
|
||||||
|
|
||||||
|
const storeTextSettings = this.props.storeTextSettings;
|
||||||
|
this.api.asc_registerCallback('asc_onInitEditorFonts', (fonts, select) => {
|
||||||
|
storeTextSettings.initEditorFonts(fonts, select);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onFontFamily', (font) => {
|
||||||
|
storeTextSettings.resetFontName(font);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onFontSize', (size) => {
|
||||||
|
storeTextSettings.resetFontSize(size);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onBold', (isBold) => {
|
||||||
|
storeTextSettings.resetIsBold(isBold);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onItalic', (isItalic) => {
|
||||||
|
storeTextSettings.resetIsItalic(isItalic);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onUnderline', (isUnderline) => {
|
||||||
|
storeTextSettings.resetIsUnderline(isUnderline);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onStrikeout', (isStrikeout) => {
|
||||||
|
storeTextSettings.resetIsStrikeout(isStrikeout);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onVerticalAlign', (typeBaseline) => {
|
||||||
|
storeTextSettings.resetTypeBaseline(typeBaseline);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onListType', (data) => {
|
||||||
|
let type = data.get_ListType();
|
||||||
|
let subtype = data.get_ListSubType();
|
||||||
|
storeTextSettings.resetListType(type);
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
storeTextSettings.resetBullets(subtype);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
storeTextSettings.resetNumbers(subtype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onPrAlign', (align) => {
|
||||||
|
storeTextSettings.resetParagraphAlign(align);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onTextColor', (color) => {
|
||||||
|
storeTextSettings.resetTextColor(color);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onParaSpacingLine', (vc) => {
|
||||||
|
storeTextSettings.resetLineSpacing(vc);
|
||||||
|
});
|
||||||
|
this.api.asc_registerCallback('asc_onTextShd', (shd) => {
|
||||||
|
let color = shd.get_Color();
|
||||||
|
storeTextSettings.resetBackgroundColor(color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <CollaborationController />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MainController;
|
3
apps/documenteditor/mobile/src/css/app-ios.less
Normal file
3
apps/documenteditor/mobile/src/css/app-ios.less
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
.device-ios {
|
||||||
|
}
|
12
apps/documenteditor/mobile/src/css/app-material.less
Normal file
12
apps/documenteditor/mobile/src/css/app-material.less
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
@themeColor: #446995; // (64,102,215)
|
||||||
|
@themeColorLight: #a2bdde;
|
||||||
|
@navBarIconColor: #fff;
|
||||||
|
|
||||||
|
|
||||||
|
.device-android {
|
||||||
|
--f7-navbar-bg-color: @themeColor;
|
||||||
|
--f7-navbar-link-color: @navBarIconColor;
|
||||||
|
--f7-navbar-text-color: @navBarIconColor;
|
||||||
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
|
|
||||||
@import '../../../../common/mobile/resources/less/collaboration.less';
|
@import '../../../../common/mobile/resources/less/collaboration.less';
|
||||||
|
@import '../../../../common/mobile/resources/less/common-ios.less';
|
||||||
|
@import '../../../../common/mobile/resources/less/common-material.less';
|
||||||
|
@import './app-material.less';
|
||||||
|
@import './app-ios.less';
|
||||||
|
|
||||||
/* Left Panel right border when it is visible by breakpoint */
|
/* Left Panel right border when it is visible by breakpoint */
|
||||||
.panel-left.panel-in-breakpoint:before {
|
.panel-left.panel-in-breakpoint:before {
|
||||||
|
@ -32,3 +36,7 @@
|
||||||
content: '';
|
content: '';
|
||||||
z-index: 6000;
|
z-index: 6000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--f7-popover-width: 360px;
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
|
const isAndroid = /Android/.test(navigator.userAgent);
|
||||||
|
if ( isAndroid && navigator.platform == 'Win32' )
|
||||||
|
// Framework7 doesn't set Device.android flag when navigator.platform == 'Win32', change it for debug
|
||||||
|
navigator.__defineGetter__('platform', () => 'Win32Debug');
|
||||||
|
|
||||||
const getUrlParams = () => {
|
const getUrlParams = () => {
|
||||||
let e,
|
let e,
|
||||||
a = /\+/g, // Regex for replacing addition symbol with a space
|
a = /\+/g, // Regex for replacing addition symbol with a space
|
||||||
|
@ -53,7 +58,7 @@
|
||||||
logo = /*params["headerlogo"] ? encodeUrlParam(params["headerlogo"]) : */null,
|
logo = /*params["headerlogo"] ? encodeUrlParam(params["headerlogo"]) : */null,
|
||||||
logoOO = null;
|
logoOO = null;
|
||||||
if (!logo) {
|
if (!logo) {
|
||||||
logoOO = /Android/.test(navigator.userAgent) ? "../../common/mobile/resources/img/header/header-logo-android.png" : "../../common/mobile/resources/img/header/header-logo-ios.png";
|
logoOO = isAndroid ? "../../common/mobile/resources/img/header/header-logo-android.png" : "../../common/mobile/resources/img/header/header-logo-ios.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
window.frameEditorId = params["frameEditorId"];
|
window.frameEditorId = params["frameEditorId"];
|
||||||
|
@ -62,7 +67,7 @@
|
||||||
|
|
||||||
let brendpanel = document.getElementsByClassName('brendpanel')[0];
|
let brendpanel = document.getElementsByClassName('brendpanel')[0];
|
||||||
if (brendpanel) {
|
if (brendpanel) {
|
||||||
if (/Android/.test(navigator.userAgent)) {
|
if ( isAndroid ) {
|
||||||
brendpanel.classList.add('android');
|
brendpanel.classList.add('android');
|
||||||
}
|
}
|
||||||
brendpanel.classList.add('visible');
|
brendpanel.classList.add('visible');
|
||||||
|
@ -74,7 +79,7 @@
|
||||||
elem.style.opacity = 1;
|
elem.style.opacity = 1;
|
||||||
}
|
}
|
||||||
var placeholder = document.getElementsByClassName('placeholder')[0];
|
var placeholder = document.getElementsByClassName('placeholder')[0];
|
||||||
if (placeholder && /Android/.test(navigator.userAgent)) {
|
if (placeholder && isAndroid) {
|
||||||
placeholder.classList.add('android');
|
placeholder.classList.add('android');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ import App from '../components/app.jsx';
|
||||||
import { I18nextProvider } from 'react-i18next';
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import i18n from './i18n';
|
import i18n from './i18n';
|
||||||
|
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'mobx-react'
|
||||||
import { store } from '../store/store.js'
|
import { stores } from '../store/mainStore'
|
||||||
|
|
||||||
// Init F7 React Plugin
|
// Init F7 React Plugin
|
||||||
Framework7.use(Framework7React)
|
Framework7.use(Framework7React)
|
||||||
|
@ -33,7 +33,7 @@ Framework7.use(Framework7React)
|
||||||
// Mount React App
|
// Mount React App
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
<Provider store={store}>
|
<Provider {...stores}>
|
||||||
<Suspense fallback="loading">
|
<Suspense fallback="loading">
|
||||||
<App />
|
<App />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
import HomePage from '../pages/home.jsx';
|
import HomePage from '../pages/home.jsx';
|
||||||
import { DocumentSettings } from "../controllers/Settings";
|
|
||||||
import Margins from "../components/settings/document-settings/Margins.jsx";
|
|
||||||
import DocumentFormats from "../components/settings/document-settings/DocumentFormats.jsx";
|
|
||||||
|
|
||||||
import LeftPage1 from '../pages/left-page-1.jsx';
|
import LeftPage1 from '../pages/left-page-1.jsx';
|
||||||
import LeftPage2 from '../pages/left-page-2.jsx';
|
import LeftPage2 from '../pages/left-page-2.jsx';
|
||||||
|
@ -11,31 +8,39 @@ import RequestAndLoad from '../pages/request-and-load.jsx';
|
||||||
|
|
||||||
import { PageCollaboration, PageUsers } from '../../../../common/mobile/lib/view/Collaboration.jsx';
|
import { PageCollaboration, PageUsers } from '../../../../common/mobile/lib/view/Collaboration.jsx';
|
||||||
|
|
||||||
|
// Edit text
|
||||||
|
import { PageFonts, PageAdditionalFormatting, PageBullets, PageNumbers, PageLineSpacing } from "../components/edit/EditText";
|
||||||
|
|
||||||
var routes = [
|
var routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: HomePage,
|
component: HomePage,
|
||||||
},
|
},
|
||||||
|
//Edit text
|
||||||
{
|
{
|
||||||
path: '/document-settings/',
|
path: '/edit-text-fonts/',
|
||||||
component: DocumentSettings
|
component: PageFonts,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/edit-text-add-formatting/',
|
||||||
|
component: PageAdditionalFormatting,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/edit-text-bullets/',
|
||||||
|
component: PageBullets,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/edit-text-numbers/',
|
||||||
|
component: PageNumbers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/edit-text-line-spacing/',
|
||||||
|
component: PageLineSpacing,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/users/',
|
path: '/users/',
|
||||||
component: PageUsers
|
component: PageUsers
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/collab-main/',
|
|
||||||
component: PageCollaboration
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/margins/',
|
|
||||||
component: Margins,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/document-formats/',
|
|
||||||
component: DocumentFormats,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/left-page-1/',
|
path: '/left-page-1/',
|
||||||
component: LeftPage1,
|
component: LeftPage1,
|
||||||
|
|
|
@ -1,32 +1,48 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import {
|
import { Page, View, Navbar, NavLeft, NavRight, Link, Icon } from 'framework7-react';
|
||||||
Page,
|
|
||||||
View,
|
|
||||||
Navbar,
|
|
||||||
NavLeft,
|
|
||||||
NavTitle,
|
|
||||||
NavTitleLarge,
|
|
||||||
NavRight,
|
|
||||||
Link,
|
|
||||||
Toolbar,
|
|
||||||
Block,
|
|
||||||
BlockTitle,
|
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
Row,
|
|
||||||
Col,
|
|
||||||
Button,
|
|
||||||
Icon, Popup
|
|
||||||
} from 'framework7-react';
|
|
||||||
|
|
||||||
import EditPopup from '../components/edit/Edit';
|
import EditOptions from '../components/edit/Edit.jsx';
|
||||||
import SettingsPopup from '../components/settings/Settings';
|
import Settings from '../components/settings/Settings.jsx';
|
||||||
import { CollaborationPopover, CollaborationSheet } from '../../../../common/mobile/lib/view/Collaboration.jsx';
|
import CollaborationView from '../../../../common/mobile/lib/view/Collaboration.jsx'
|
||||||
|
|
||||||
export default class Home extends Component {
|
export default class Home extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
editOptionsVisible: false,
|
||||||
|
settingsVisible: false,
|
||||||
|
collaborationVisible: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleClickToOpenOptions = opts => {
|
||||||
|
this.setState(state => {
|
||||||
|
if ( opts == 'edit' )
|
||||||
|
return {editOptionsVisible: true};
|
||||||
|
else
|
||||||
|
if ( opts == 'settings' )
|
||||||
|
return {settingsVisible: true};
|
||||||
|
else
|
||||||
|
if ( opts == 'coauth' )
|
||||||
|
return {collaborationVisible: true}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleOptionsViewClosed = opts => {
|
||||||
|
(async () => {
|
||||||
|
await 1 && this.setState(state => {
|
||||||
|
if ( opts == 'edit' )
|
||||||
|
return {editOptionsVisible: false};
|
||||||
|
else
|
||||||
|
if ( opts == 'settings' )
|
||||||
|
return {settingsVisible: false};
|
||||||
|
else
|
||||||
|
if ( opts == 'coauth' )
|
||||||
|
return {collaborationVisible: false}
|
||||||
|
})
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log(this.$f7router)
|
console.log(this.$f7router)
|
||||||
return (
|
return (
|
||||||
|
@ -36,22 +52,29 @@ export default class Home extends Component {
|
||||||
<div slot="before-inner" className="main-logo"><Icon icon="icon-logo"></Icon></div>
|
<div slot="before-inner" className="main-logo"><Icon icon="icon-logo"></Icon></div>
|
||||||
<NavLeft>
|
<NavLeft>
|
||||||
<Link>Undo</Link>
|
<Link>Undo</Link>
|
||||||
<Link>Redu</Link>
|
<Link>Redo</Link>
|
||||||
</NavLeft>
|
</NavLeft>
|
||||||
<NavRight>
|
<NavRight>
|
||||||
<Link href={false} popupOpen=".edit-popup">Edit</Link>
|
<Link href={false} onClick={e => this.handleClickToOpenOptions('edit')}>Edit</Link>
|
||||||
{/*<Link href={false} popoverOpen=".collab__popover">Users</Link>*/}
|
<Link href={false} onClick={e => this.handleClickToOpenOptions('coauth')}>Users</Link>
|
||||||
<Link href={false} sheetOpen=".collab__sheet">Users</Link>
|
<Link href={false} onClick={e => this.handleClickToOpenOptions('settings')} id='btn-settings'>Settings</Link>
|
||||||
<Link href={false} popupOpen=".settings-popup">Settings</Link>
|
|
||||||
</NavRight>
|
</NavRight>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
{/* Page content */}
|
{/* Page content */}
|
||||||
<View id="editor_sdk">
|
<View id="editor_sdk">
|
||||||
</View>
|
</View>
|
||||||
<EditPopup />
|
{
|
||||||
<SettingsPopup />
|
!this.state.editOptionsVisible ? null :
|
||||||
<CollaborationPopover />
|
<EditOptions onclosed={this.handleOptionsViewClosed.bind(this, 'edit')} />
|
||||||
<CollaborationSheet />
|
}
|
||||||
|
{
|
||||||
|
!this.state.settingsVisible ? null :
|
||||||
|
<Settings onclosed={this.handleOptionsViewClosed.bind(this, 'settings')} />
|
||||||
|
}
|
||||||
|
{
|
||||||
|
!this.state.collaborationVisible ? null :
|
||||||
|
<CollaborationView onclosed={this.handleOptionsViewClosed.bind(this, 'coauth')} />
|
||||||
|
}
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
6
apps/documenteditor/mobile/src/store/documentSettings.js
Normal file
6
apps/documenteditor/mobile/src/store/documentSettings.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
import {action, observable} from 'mobx';
|
||||||
|
|
||||||
|
export class storeDocumentSettings {
|
||||||
|
@observable isPortrait = true
|
||||||
|
}
|
60
apps/documenteditor/mobile/src/store/focusObjects.js
Normal file
60
apps/documenteditor/mobile/src/store/focusObjects.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import {action, observable, computed} from 'mobx';
|
||||||
|
|
||||||
|
export class storeFocusObjects {
|
||||||
|
@observable _focusObjects = [];
|
||||||
|
@observable _headerType = 1;
|
||||||
|
|
||||||
|
@action resetFocusObjects (objects) {
|
||||||
|
this._focusObjects = objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get settings() {
|
||||||
|
let _settings = [];
|
||||||
|
for (let object of this._focusObjects) {
|
||||||
|
let type = object.get_ObjectType();
|
||||||
|
if (Asc.c_oAscTypeSelectElement.Paragraph === type) {
|
||||||
|
_settings.push('text', 'paragraph');
|
||||||
|
} else if (Asc.c_oAscTypeSelectElement.Table === type) {
|
||||||
|
_settings.push('table');
|
||||||
|
} else if (Asc.c_oAscTypeSelectElement.Image === type) {
|
||||||
|
if (object.get_ObjectValue().get_ChartProperties()) {
|
||||||
|
// Exclude shapes if chart exist
|
||||||
|
let si = _settings.indexOf('shape');
|
||||||
|
si < 0 ? _settings.push('chart') : _settings.splice(si,1,'chart');
|
||||||
|
} else if (object.get_ObjectValue().get_ShapeProperties() && !_settings.includes('chart')) {
|
||||||
|
_settings.push('shape');
|
||||||
|
} else {
|
||||||
|
_settings.push('image');
|
||||||
|
}
|
||||||
|
} else if (Asc.c_oAscTypeSelectElement.Hyperlink === type) {
|
||||||
|
_settings.push('hyperlink');
|
||||||
|
} else if (Asc.c_oAscTypeSelectElement.Header === type) {
|
||||||
|
_settings.push('header');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _settings.filter((value, index, self) => self.indexOf(value) === index);
|
||||||
|
}
|
||||||
|
@computed get headerType() {
|
||||||
|
for (let object of this._focusObjects) {
|
||||||
|
let type = object.get_ObjectType();
|
||||||
|
if (Asc.c_oAscTypeSelectElement.Header === type) {
|
||||||
|
return object.get_ObjectValue().get_Type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._headerType;
|
||||||
|
}
|
||||||
|
@computed get paragraphObject() {
|
||||||
|
let paragraphs = [];
|
||||||
|
for (let object of this._focusObjects) {
|
||||||
|
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||||
|
paragraphs.push(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paragraphs.length > 0) {
|
||||||
|
let object = paragraphs[paragraphs.length - 1]; // get top
|
||||||
|
return object.get_ObjectValue();
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
apps/documenteditor/mobile/src/store/mainStore.js
Normal file
13
apps/documenteditor/mobile/src/store/mainStore.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
import {storeDocumentSettings} from './documentSettings';
|
||||||
|
import {storeFocusObjects} from "./focusObjects";
|
||||||
|
import {storeUsers} from '../../../../common/mobile/lib/store/users';
|
||||||
|
import {storeTextSettings} from "./textSettings";
|
||||||
|
|
||||||
|
export const stores = {
|
||||||
|
storeFocusObjects: new storeFocusObjects(),
|
||||||
|
storeDocumentSettings: new storeDocumentSettings(),
|
||||||
|
users: new storeUsers(),
|
||||||
|
storeTextSettings: new storeTextSettings()
|
||||||
|
};
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { combineReducers } from 'redux';
|
|
||||||
import apiReducer from "./initApi";
|
|
||||||
import usersReducer from '../../../../../common/mobile/lib/store/users'
|
|
||||||
import settingsReducer from './settings'
|
|
||||||
|
|
||||||
export const initialState = {
|
|
||||||
users: []
|
|
||||||
};
|
|
||||||
|
|
||||||
export const rootReducer = combineReducers({
|
|
||||||
api: apiReducer,
|
|
||||||
users: usersReducer,
|
|
||||||
settings: settingsReducer
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
|
||||||
import { rootReducer, initialState } from './reducers/root'
|
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
|
|
||||||
const store = createStore(rootReducer, initialState, applyMiddleware(thunk));
|
|
||||||
|
|
||||||
!window.Common && (window.Common = {});
|
|
||||||
Common.Store = { get: () => store };
|
|
||||||
|
|
||||||
export { store };
|
|
132
apps/documenteditor/mobile/src/store/textSettings.js
Normal file
132
apps/documenteditor/mobile/src/store/textSettings.js
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
import {action, observable, computed} from 'mobx';
|
||||||
|
|
||||||
|
export class storeTextSettings {
|
||||||
|
@observable fontsArray = [];
|
||||||
|
@observable fontName = '';
|
||||||
|
@observable fontSize = undefined;
|
||||||
|
@observable isBold = false;
|
||||||
|
@observable isItalic = false;
|
||||||
|
@observable isUnderline = false;
|
||||||
|
@observable isStrikethrough = false;
|
||||||
|
@observable typeBaseline = undefined;
|
||||||
|
@observable listType = undefined;
|
||||||
|
@observable typeBullets = undefined;
|
||||||
|
@observable typeNumbers = undefined;
|
||||||
|
@observable paragraphAlign = undefined;
|
||||||
|
@observable textColor = undefined;
|
||||||
|
@observable lineSpacing = undefined;
|
||||||
|
@observable backgroundColor = undefined;
|
||||||
|
|
||||||
|
|
||||||
|
@action initEditorFonts (fonts, select) {
|
||||||
|
let array = [];
|
||||||
|
for (let font of fonts) {
|
||||||
|
let fontId = font.asc_getFontId();
|
||||||
|
array.push({
|
||||||
|
id : fontId,
|
||||||
|
name : font.asc_getFontName(),
|
||||||
|
//displayValue: font.asc_getFontName(),
|
||||||
|
imgidx : font.asc_getFontThumbnail(),
|
||||||
|
type : font.asc_getFontType()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.fontsArray = array;
|
||||||
|
}
|
||||||
|
@action resetFontName (font) {
|
||||||
|
let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName();
|
||||||
|
this.fontName = name;
|
||||||
|
}
|
||||||
|
@action resetFontSize (size) {
|
||||||
|
this.fontSize = size;
|
||||||
|
}
|
||||||
|
@action resetIsBold (isBold) {
|
||||||
|
this.isBold = isBold;
|
||||||
|
}
|
||||||
|
@action resetIsItalic (isItalic) {
|
||||||
|
this.isItalic = isItalic;
|
||||||
|
}
|
||||||
|
@action resetIsUnderline (isUnderline) {
|
||||||
|
this.isUnderline = isUnderline;
|
||||||
|
}
|
||||||
|
@action resetIsStrikeout (isStrikethrough) {
|
||||||
|
this.isStrikethrough = isStrikethrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertical align
|
||||||
|
@action resetTypeBaseline (typeBaseline) {
|
||||||
|
this.typeBaseline = typeBaseline;
|
||||||
|
}
|
||||||
|
@computed get isSuperscript() {
|
||||||
|
return (this.typeBaseline === 1);
|
||||||
|
}
|
||||||
|
@computed get isSubscript() {
|
||||||
|
return (this.typeBaseline === 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bullets
|
||||||
|
@action resetListType (type) {
|
||||||
|
this.listType = type;
|
||||||
|
}
|
||||||
|
@action resetBullets (type) {
|
||||||
|
this.typeBullets = type;
|
||||||
|
}
|
||||||
|
@action resetNumbers (type) {
|
||||||
|
this.typeNumbers = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action resetParagraphAlign (align) {
|
||||||
|
let value;
|
||||||
|
switch (align) {
|
||||||
|
case 0:
|
||||||
|
value = 'right';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = 'left';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = 'center';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = 'just';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.paragraphAlign = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action resetTextColor (color) {
|
||||||
|
let value;
|
||||||
|
if (color) {
|
||||||
|
if (color.get_auto()) {
|
||||||
|
value = '000000';
|
||||||
|
} else {
|
||||||
|
if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
|
||||||
|
value = {
|
||||||
|
color: Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()),
|
||||||
|
effectValue: color.get_value()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.textColor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action resetLineSpacing (vc) {
|
||||||
|
let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line();
|
||||||
|
this.lineSpacing = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action resetBackgroundColor (color) {
|
||||||
|
let value;
|
||||||
|
if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
|
||||||
|
value = {
|
||||||
|
color: Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()),
|
||||||
|
effectValue: color.get_value()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
|
||||||
|
}
|
||||||
|
this.backgroundColor = value;
|
||||||
|
}
|
||||||
|
}
|
2
vendor/framework7-react/babel.config.js
vendored
2
vendor/framework7-react/babel.config.js
vendored
|
@ -8,5 +8,7 @@ module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
'@babel/plugin-transform-runtime',
|
'@babel/plugin-transform-runtime',
|
||||||
'@babel/plugin-syntax-dynamic-import',
|
'@babel/plugin-syntax-dynamic-import',
|
||||||
|
['@babel/plugin-proposal-decorators', {'legacy': true }],
|
||||||
|
['@babel/plugin-proposal-class-properties',{'loose':true}],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
4
vendor/framework7-react/package.json
vendored
4
vendor/framework7-react/package.json
vendored
|
@ -35,6 +35,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.11.0",
|
"@babel/core": "^7.11.0",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||||
|
"@babel/plugin-proposal-decorators": "^7.10.5",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-transform-runtime": "^7.11.0",
|
"@babel/plugin-transform-runtime": "^7.11.0",
|
||||||
"@babel/preset-env": "^7.11.0",
|
"@babel/preset-env": "^7.11.0",
|
||||||
|
@ -52,6 +54,8 @@
|
||||||
"less": "^3.12.2",
|
"less": "^3.12.2",
|
||||||
"less-loader": "^6.2.0",
|
"less-loader": "^6.2.0",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
"mobx": "^5.15.7",
|
||||||
|
"mobx-react": "^6.3.0",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
"ora": "^4.0.5",
|
"ora": "^4.0.5",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
|
|
Loading…
Reference in a new issue