Merge branch 'feature/mobile-apps-on-reactjs' into feature/mobile-apps-on-reactjs-se-edit-settings
This commit is contained in:
commit
ef0449b49b
|
@ -1,3 +1,5 @@
|
|||
@import "./ios/_contextmenu";
|
||||
@import "icons-ios";
|
||||
|
||||
.device-ios {
|
||||
@blockTitleColor: #6d6d72;
|
||||
|
@ -198,8 +200,11 @@
|
|||
}
|
||||
li.no-indicator {
|
||||
.item-link {
|
||||
.item-inner:before {
|
||||
content: none;
|
||||
.item-inner {
|
||||
padding-right: 15px;
|
||||
&:before {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +242,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.list-input-right input {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-buttons {
|
||||
|
|
|
@ -152,8 +152,11 @@
|
|||
.list {
|
||||
li.no-indicator {
|
||||
.item-link {
|
||||
.item-inner:before {
|
||||
content: none;
|
||||
.item-inner{
|
||||
padding-right: 15px;
|
||||
&:before {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
apps/common/mobile/resources/less/icons-ios.less
Normal file
9
apps/common/mobile/resources/less/icons-ios.less
Normal file
|
@ -0,0 +1,9 @@
|
|||
.device-ios {
|
||||
i.icon {
|
||||
&.icon-paste {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
.encoded-svg-background('<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" fill="white"/><path d="M5 0H14V5H5V0Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" fill="white"/></svg>');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,15 @@ export default class Notifications {
|
|||
}
|
||||
|
||||
on(event, callback) {
|
||||
!this._events[event] && (this._events[event] = []);
|
||||
this._events[event].push(callback);
|
||||
const addevent = (e, c) => {
|
||||
!this._events[e] && (this._events[e] = []);
|
||||
this._events[e].push(c);
|
||||
};
|
||||
|
||||
if ( typeof(event) == 'object' )
|
||||
for (const i in event)
|
||||
addevent(i, event[i])
|
||||
else addevent(event, callback);
|
||||
}
|
||||
|
||||
off(event, callback) {
|
||||
|
|
74
apps/documenteditor/mobile/src/controller/ContextMenu.jsx
Normal file
74
apps/documenteditor/mobile/src/controller/ContextMenu.jsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
import React, { Component } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
|
||||
import ContextMenuView from '../view/ContextMenu';
|
||||
|
||||
class ContextMenuController extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
pos: [-10000,-10000],
|
||||
show: false
|
||||
};
|
||||
|
||||
this.onMenuClosed = this.onMenuClosed.bind(this);
|
||||
|
||||
Common.Notifications.on({
|
||||
'engineCreated': api => {
|
||||
api.asc_registerCallback('asc_onShowPopMenu', this.onApiShowPopMenu.bind(this));
|
||||
api.asc_registerCallback('asc_onHidePopMenu', this.onApiHidePopMenu.bind(this));
|
||||
},
|
||||
'document:ready': () => {
|
||||
this.$targetEl = $$('<div id="idx-context-menu-target" style="position:absolute;width:15px;height:15px;background-color:green;z-index:1;"></div>');
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
|
||||
$$('#editor_sdk').append(this.$targetEl);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('context menu controller created');
|
||||
}
|
||||
|
||||
onApiShowPopMenu(x, y) {
|
||||
console.log('show context menu ' + [x,y]);
|
||||
|
||||
this.$targetEl.css({left: `${x}px`, top: `${y}px`});
|
||||
this.setState({
|
||||
pos: [x,y],
|
||||
show: true });
|
||||
}
|
||||
|
||||
onApiHidePopMenu() {
|
||||
// console.log('hide context menu');
|
||||
|
||||
if ( this.state.show ) {
|
||||
f7.popover.close('#idx-context-menu-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onMenuClosed() {
|
||||
(async () => {
|
||||
await 1 && this.setState(state => {
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
return ({pos: [-10000, -10000], show: false});
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log('context menu controller will be unmounted');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log('context menu controller did mount');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
!this.state.show ? null :
|
||||
<ContextMenuView onMenuClosed={this.onMenuClosed} />)
|
||||
}
|
||||
}
|
||||
|
||||
export { ContextMenuController as ContextMenu };
|
|
@ -134,6 +134,8 @@ class MainController extends Component {
|
|||
const onDocumentContentReady = () => {
|
||||
Common.Gateway.documentReady();
|
||||
f7.emit('resize');
|
||||
|
||||
Common.Notifications.trigger('document:ready');
|
||||
};
|
||||
|
||||
const _process_array = (array, fn) => {
|
||||
|
|
|
@ -7,6 +7,7 @@ import Settings from '../view/settings/Settings';
|
|||
import CollaborationView from '../../../../common/mobile/lib/view/Collaboration.jsx'
|
||||
import { Device } from '../../../../common/mobile/utils/device'
|
||||
import { Search, SearchSettings } from '../controller/Search';
|
||||
import { ContextMenu } from '../controller/ContextMenu';
|
||||
|
||||
export default class MainPage extends Component {
|
||||
constructor(props) {
|
||||
|
@ -89,6 +90,7 @@ export default class MainPage extends Component {
|
|||
!this.state.collaborationVisible ? null :
|
||||
<CollaborationView onclosed={this.handleOptionsViewClosed.bind(this, 'coauth')} />
|
||||
}
|
||||
{/*<ContextMenu />*/}
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
|
50
apps/documenteditor/mobile/src/view/ContextMenu.jsx
Normal file
50
apps/documenteditor/mobile/src/view/ContextMenu.jsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Popover, List, ListItem, ListButton, Link, Icon } from 'framework7-react';
|
||||
import { f7 } from 'framework7-react';
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
text: 'Edit',
|
||||
action: 'edit'
|
||||
}, {
|
||||
text: 'View',
|
||||
action: 'view'
|
||||
}, {
|
||||
icon: 'icon-paste',
|
||||
action: 'review'
|
||||
}
|
||||
];
|
||||
|
||||
class ContextMenuView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Popover id="idx-context-menu-popover"
|
||||
className="document-menu"
|
||||
backdrop={false}
|
||||
closeByBackdropClick={false}
|
||||
closeByOutsideClick={false}
|
||||
onPopoverClosed={e => this.props.onMenuClosed()}
|
||||
>
|
||||
<List className="list-block">
|
||||
{buttons.map((b, index) =>
|
||||
!!b.text ?
|
||||
<ListButton className="asd" title={b.text} key={index} /> :
|
||||
<ListButton className="asd" title={b.text} key={index}>
|
||||
<Icon slot="media" icon={b.icon} />
|
||||
</ListButton>
|
||||
)}
|
||||
</List>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ContextMenuView;
|
|
@ -229,7 +229,22 @@
|
|||
"textRemoveTable": "Remove Table",
|
||||
"textCellMargins": "Cell Margins",
|
||||
"textRemoveChart": "Remove Chart",
|
||||
"textNoStyles": "No styles for this type of charts."
|
||||
"textNoStyles": "No styles for this type of charts.",
|
||||
"textLinkType": "Link Type",
|
||||
"textExternalLink": "External Link",
|
||||
"textSlideInThisPresentation": "Slide in this Presentation",
|
||||
"textLink": "Link",
|
||||
"textLinkTo": "Link to",
|
||||
"textNextSlide": "Next Slide",
|
||||
"textPreviousSlide": "Previous Slide",
|
||||
"textFirstSlide": "First Slide",
|
||||
"textLastSlide": "Last Slide",
|
||||
"textSlideNumber": "Slide Number",
|
||||
"textEditLink": "Edit Link",
|
||||
"textRemoveLink": "Remove Link",
|
||||
"textDisplay": "Display",
|
||||
"textScreenTip": "Screen Tip",
|
||||
"textDefault": "Selected text"
|
||||
}
|
||||
},
|
||||
"Common": {
|
||||
|
|
|
@ -322,6 +322,14 @@ class MainController extends Component {
|
|||
storeChartSettings.updateChartStyles(this.api.asc_getChartPreviews(storeFocusObjects.chartObject.getType()));
|
||||
}
|
||||
});
|
||||
|
||||
// Link settings
|
||||
|
||||
const storeLinkSettings = this.props.storeLinkSettings;
|
||||
|
||||
this.api.asc_registerCallback('asc_onCanAddHyperlink', (value) => {
|
||||
storeLinkSettings.canAddHyperlink(value);
|
||||
});
|
||||
}
|
||||
|
||||
_onDocumentContentReady() {
|
||||
|
|
114
apps/presentationeditor/mobile/src/controller/edit/EditLink.jsx
Normal file
114
apps/presentationeditor/mobile/src/controller/edit/EditLink.jsx
Normal file
|
@ -0,0 +1,114 @@
|
|||
import React, { Component } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { Device } from '../../../../../common/mobile/utils/device';
|
||||
import {observer, inject} from "mobx-react";
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
import { EditLink } from '../../view/edit/EditLink';
|
||||
|
||||
class EditLinkController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onEditLink = this.onEditLink.bind(this);
|
||||
this.onRemoveLink = this.onRemoveLink.bind(this);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('#edit-sheet', true);
|
||||
} else {
|
||||
f7.popover.close('#edit-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onEditLink(type, linkInfo) {
|
||||
const api = Common.EditorApi.get();
|
||||
const { t } = this.props;
|
||||
const _t = t("View.Edit", { returnObjects: true });
|
||||
|
||||
const c_oHyperlinkType = {
|
||||
InternalLink: 0,
|
||||
WebLink: 1
|
||||
};
|
||||
|
||||
const display = linkInfo.display;
|
||||
const tip = linkInfo.tip;
|
||||
const props = new Asc.CHyperlinkProperty();
|
||||
let def_display = '';
|
||||
|
||||
if (type == c_oHyperlinkType.WebLink) {
|
||||
let url = linkInfo.url;
|
||||
const urltype = api.asc_getUrlType(url.trim());
|
||||
const isEmail = (urltype == 2);
|
||||
if (urltype < 1) {
|
||||
f7.dialog.alert(_t.textNotUrl, _t.notcriticalErrorTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
url = url.replace(/^\s+|\s+$/g, '');
|
||||
if (!/(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(url))
|
||||
url = (isEmail ? 'mailto:' : 'http://' ) + url;
|
||||
url = url.replace(new RegExp("%20", 'g'), " ");
|
||||
|
||||
props.put_Value(url);
|
||||
props.put_ToolTip(tip);
|
||||
def_display = url;
|
||||
} else {
|
||||
let url = "ppaction://hlink";
|
||||
let slidetip = '';
|
||||
switch (linkInfo.linkTo) {
|
||||
case 0:
|
||||
url = url + "showjump?jump=nextslide";
|
||||
slidetip = _t.textNextSlide;
|
||||
break;
|
||||
case 1:
|
||||
url = url + "showjump?jump=previousslide";
|
||||
slidetip = _t.textPrevSlide;
|
||||
break;
|
||||
case 2:
|
||||
url = url + "showjump?jump=firstslide";
|
||||
slidetip = _t.textFirstSlide;
|
||||
break;
|
||||
case 3:
|
||||
url = url + "showjump?jump=lastslide";
|
||||
slidetip = _t.textLastSlide;
|
||||
break;
|
||||
case 4:
|
||||
url = url + "sldjumpslide" + linkInfo.numberTo;
|
||||
slidetip = _t.textSlide + ' ' + (linkInfo.numberTo + 1);
|
||||
break;
|
||||
}
|
||||
props.put_Value(url);
|
||||
props.put_ToolTip(!tip ? slidetip : tip);
|
||||
def_display = slidetip;
|
||||
}
|
||||
|
||||
if (!linkInfo.displayDisabled) {
|
||||
props.put_Text(!display ? def_display : display);
|
||||
} else
|
||||
props.put_Text(null);
|
||||
|
||||
api.change_Hyperlink(props);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
onRemoveLink() {
|
||||
const api = Common.EditorApi.get();
|
||||
api.remove_Hyperlink();
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<EditLink
|
||||
onEditLink={this.onEditLink}
|
||||
onRemoveLink={this.onRemoveLink}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const EditLinkWithTranslation = withTranslation()(EditLinkController);
|
||||
|
||||
export {EditLinkWithTranslation as EditLinkController};
|
|
@ -163,4 +163,19 @@ export class storeFocusObjects {
|
|||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@computed get linkObject() {
|
||||
const links = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
links.push(object);
|
||||
}
|
||||
}
|
||||
if (links.length > 0) {
|
||||
const object = links[links.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,4 +5,68 @@ export class storeLinkSettings {
|
|||
@action canAddHyperlink (value) {
|
||||
this.canAddLink = value;
|
||||
}
|
||||
}
|
||||
|
||||
@observable typeLink;
|
||||
@action changeLinkType(value) {
|
||||
this.typeLink = value;
|
||||
}
|
||||
|
||||
@observable slideLink;
|
||||
@action changeSlideLink(value) {
|
||||
this.slideLink = value;
|
||||
}
|
||||
|
||||
@observable slideNum;
|
||||
@action changeSlideNum(value) {
|
||||
this.slideNum = value;
|
||||
}
|
||||
|
||||
@observable slideName;
|
||||
@action changeSlideName(value) {
|
||||
this.slideName = value;
|
||||
}
|
||||
|
||||
initCategory(linkObject) {
|
||||
const url = linkObject.get_Value();
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
let indAction;
|
||||
let slidesCount;
|
||||
let slideNum;
|
||||
|
||||
if(url === null || url === undefined || url === '') {
|
||||
this.changeLinkType(1);
|
||||
}
|
||||
else {
|
||||
indAction = url.indexOf("ppaction://hlink");
|
||||
if(0 == indAction) {
|
||||
if (url == "ppaction://hlinkshowjump?jump=firstslide") {
|
||||
this.changeSlideLink(2);
|
||||
} else if (url == "ppaction://hlinkshowjump?jump=lastslide") {
|
||||
this.changeSlideLink(3);
|
||||
}
|
||||
else if (url == "ppaction://hlinkshowjump?jump=nextslide") {
|
||||
this.changeSlideLink(0);
|
||||
}
|
||||
else if (url == "ppaction://hlinkshowjump?jump=previousslide") {
|
||||
this.changeSlideLink(1);
|
||||
}
|
||||
else {
|
||||
this.changeSlideLink(4);
|
||||
slidesCount = api.getCountPages();
|
||||
let mask = "ppaction://hlinksldjumpslide",
|
||||
indSlide = url.indexOf(mask);
|
||||
if (0 == indSlide) {
|
||||
slideNum = parseInt(url.substring(mask.length));
|
||||
if (slideNum < 0) this.changeSlideNum(0);
|
||||
if (slideNum >= slidesCount) this.changeSlideNum(slidesCount - 1);
|
||||
} else this.changeSlideNum(0);
|
||||
}
|
||||
this.changeLinkType(0);
|
||||
} else {
|
||||
this.changeLinkType(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import EditShapeController from "../../controller/edit/EditShape";
|
|||
import EditImageController from "../../controller/edit/EditImage";
|
||||
import EditTableController from "../../controller/edit/EditTable";
|
||||
import EditChartController from "../../controller/edit/EditChart";
|
||||
import { EditLinkController } from "../../controller/edit/EditLink";
|
||||
|
||||
import { Theme, Layout, Transition, Type, Effect, StyleFillColor, CustomFillColor } from './EditSlide';
|
||||
import { PageTextFonts, PageTextFontColor, PageTextCustomFontColor, PageTextAddFormatting, PageTextBullets, PageTextNumbers, PageTextLineSpacing } from './EditText';
|
||||
|
@ -18,7 +19,7 @@ import { PageShapeStyle, PageShapeStyleNoFill, PageReplaceContainer, PageReorder
|
|||
import { PageImageReplace, PageImageReorder, PageImageAlign, PageLinkSettings } from './EditImage';
|
||||
import { PageTableStyle, PageTableStyleOptions, PageTableCustomFillColor, PageTableBorderColor, PageTableCustomBorderColor, PageTableReorder, PageTableAlign } from './EditTable';
|
||||
import { PageChartStyle, PageChartCustomFillColor, PageChartBorderColor, PageChartCustomBorderColor, PageChartReorder, PageChartAlign } from './EditChart'
|
||||
//import EditLinkController from "../../controller/edit/EditLink";
|
||||
import { PageLinkTo, PageTypeLink } from './EditLink'
|
||||
|
||||
const routes = [
|
||||
|
||||
|
@ -194,6 +195,17 @@ const routes = [
|
|||
{
|
||||
path: '/edit-chart-custom-fill-color/',
|
||||
component: PageChartCustomFillColor
|
||||
},
|
||||
|
||||
// Link
|
||||
|
||||
{
|
||||
path: '/edit-link-type/',
|
||||
component: PageTypeLink
|
||||
},
|
||||
{
|
||||
path: '/edit-link-to/',
|
||||
component: PageLinkTo
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -303,14 +315,13 @@ const EditTabs = props => {
|
|||
component: <EditChartController />
|
||||
})
|
||||
}
|
||||
/*
|
||||
if (settings.indexOf('hyperlink') > -1) {
|
||||
editors.push({
|
||||
caption: _t.textHyperlink,
|
||||
id: 'edit-link',
|
||||
component: <EditLinkController />
|
||||
})
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
187
apps/presentationeditor/mobile/src/view/edit/EditLink.jsx
Normal file
187
apps/presentationeditor/mobile/src/view/edit/EditLink.jsx
Normal file
|
@ -0,0 +1,187 @@
|
|||
import React, {useState, useEffect} from 'react';
|
||||
import {observer, inject} from "mobx-react";
|
||||
import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, Segmented, Button} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {Device} from "../../../../../common/mobile/utils/device";
|
||||
|
||||
const PageTypeLink = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Edit', {returnObjects: true});
|
||||
const storeLinkSettings = props.storeLinkSettings;
|
||||
const typeLink = storeLinkSettings.typeLink;
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLinkType} backLink={_t.textBack}/>
|
||||
<List>
|
||||
<ListItem title={_t.textExternalLink} radio checked={typeLink === 1} onClick={() => {storeLinkSettings.changeLinkType(1);}}></ListItem>
|
||||
<ListItem title={_t.textSlideInThisPresentation} radio checked={typeLink === 0} onClick={() => {storeLinkSettings.changeLinkType(0);}}></ListItem>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const PageLinkTo = props => {
|
||||
const isAndroid = Device.android;
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Edit', {returnObjects: true});
|
||||
const api = Common.EditorApi.get();
|
||||
const slidesCount = api.getCountPages();
|
||||
const storeLinkSettings = props.storeLinkSettings;
|
||||
const slideLink = storeLinkSettings.slideLink;
|
||||
// console.log(slideLink);
|
||||
// const slideNum = storeLinkSettings.slideNum;
|
||||
// const [stateTypeTo, setTypeTo] = useState(props.curTo);
|
||||
|
||||
const changeTypeTo = (type) => {
|
||||
storeLinkSettings.changeSlideLink(type);
|
||||
props.changeTo(type);
|
||||
};
|
||||
|
||||
const [stateNumberTo, setNumberTo] = useState(0);
|
||||
|
||||
const changeNumber = (curNumber, isDecrement) => {
|
||||
storeLinkSettings.changeSlideLink(4);
|
||||
let value;
|
||||
|
||||
if (isDecrement) {
|
||||
value = Math.max(0, --curNumber);
|
||||
} else {
|
||||
value = Math.min(slidesCount - 1, ++curNumber);
|
||||
}
|
||||
|
||||
setNumberTo(value);
|
||||
storeLinkSettings.changeSlideNum(value);
|
||||
props.changeTo(4, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLinkTo} backLink={_t.textBack}/>
|
||||
<List>
|
||||
<ListItem title={_t.textNextSlide} radio checked={slideLink === 0} onClick={() => {changeTypeTo(0)}}></ListItem>
|
||||
<ListItem title={_t.textPreviousSlide} radio checked={slideLink === 1} onClick={() => {changeTypeTo(1)}}></ListItem>
|
||||
<ListItem title={_t.textFirstSlide} radio checked={slideLink === 2} onClick={() => {changeTypeTo(2)}}></ListItem>
|
||||
<ListItem title={_t.textLastSlide} radio checked={slideLink === 3} onClick={() => {changeTypeTo(3)}}></ListItem>
|
||||
<ListItem title={_t.textSlideNumber}>
|
||||
{!isAndroid && <div slot='after-start'>{stateNumberTo + 1}</div>}
|
||||
<div slot='after'>
|
||||
<Segmented>
|
||||
<Button outline className='decrement item-link' onClick={() => {changeNumber(stateNumberTo, true);}}>
|
||||
{isAndroid ? <Icon icon="icon-expand-down"></Icon> : ' - '}
|
||||
</Button>
|
||||
{isAndroid && <label>{stateNumberTo + 1}</label>}
|
||||
<Button outline className='increment item-link' onClick={() => {changeNumber(stateNumberTo, false);}}>
|
||||
{isAndroid ? <Icon icon="icon-expand-up"></Icon> : ' + '}
|
||||
</Button>
|
||||
</Segmented>
|
||||
</div>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const PageLink = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Edit', {returnObjects: true});
|
||||
const storeFocusObjects = props.storeFocusObjects;
|
||||
const storeLinkSettings = props.storeLinkSettings;
|
||||
const linkObject = storeFocusObjects.linkObject;
|
||||
|
||||
useEffect(() => {
|
||||
storeLinkSettings.initCategory(linkObject);
|
||||
}, [linkObject]);
|
||||
|
||||
const url = linkObject.get_Value();
|
||||
const tooltip = linkObject.get_ToolTip();
|
||||
const display = linkObject.get_Text();
|
||||
const slideNum = storeLinkSettings.slideNum;
|
||||
const slideLink = storeLinkSettings.slideLink;
|
||||
const typeLink = storeLinkSettings.typeLink;
|
||||
|
||||
if(typeLink === 1) {
|
||||
storeLinkSettings.changeSlideName(_t.textNextSlide);
|
||||
storeLinkSettings.changeSlideLink(0);
|
||||
}
|
||||
|
||||
const textType = typeLink === 1 ? _t.textExternalLink : _t.textSlideInThisPresentation;
|
||||
const [link, setLink] = useState(typeLink !== 0 ? url : '');
|
||||
|
||||
const changeTo = (slideLink, number) => {
|
||||
switch (slideLink) {
|
||||
case 0 : storeLinkSettings.changeSlideName(_t.textNextSlide); break;
|
||||
case 1 : storeLinkSettings.changeSlideName(_t.textPreviousSlide); break;
|
||||
case 2 : storeLinkSettings.changeSlideName(_t.textFirstSlide); break;
|
||||
case 3 : storeLinkSettings.changeSlideName(_t.textLastSlide); break;
|
||||
case 4 : storeLinkSettings.changeSlideName(`${_t.textSlide} ${number + 1}`); storeLinkSettings.changeSlideNum(number);
|
||||
}
|
||||
}
|
||||
|
||||
changeTo(slideLink, slideNum);
|
||||
|
||||
const slideName = storeLinkSettings.slideName;
|
||||
const [screenTip, setScreenTip] = useState(tooltip);
|
||||
const displayDisabled = display !== false && display === null;
|
||||
const [stateDisplay, setDisplay] = useState(display !== false ? ((display !== null) ? display : _t.textDefault) : "");
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLink} backLink={_t.textBack}/>
|
||||
<List inlineLabels className='inputs-list'>
|
||||
<ListItem link={'/edit-link-type/'} title={_t.textLinkType} after={textType} routeProps={{
|
||||
curType: typeLink
|
||||
}} />
|
||||
{typeLink !== 0 ?
|
||||
<ListInput label={_t.textLink}
|
||||
type="text"
|
||||
placeholder={_t.textLink}
|
||||
value={link}
|
||||
onChange={(event) => {setLink(event.target.value)}}
|
||||
/> :
|
||||
<ListItem link={'/edit-link-to/'} title={_t.textLinkTo} after={slideName} routeProps={{
|
||||
changeTo: changeTo,
|
||||
curTo: slideLink
|
||||
}}/>
|
||||
}
|
||||
<ListInput label={_t.textDisplay}
|
||||
type="text"
|
||||
placeholder={_t.textDisplay}
|
||||
value={stateDisplay}
|
||||
disabled={displayDisabled}
|
||||
onChange={(event) => {setDisplay(event.target.value)}}
|
||||
/>
|
||||
<ListInput label={_t.textScreenTip}
|
||||
type="text"
|
||||
placeholder={_t.textScreenTip}
|
||||
value={screenTip}
|
||||
onChange={(event) => {setScreenTip(event.target.value)}}
|
||||
/>
|
||||
</List>
|
||||
<List>
|
||||
<ListButton title={_t.textEditLink}
|
||||
className={`button-fill button-raised${typeLink === 1 && link.length < 1 && ' disabled'}`}
|
||||
onClick={() => {
|
||||
props.onEditLink(typeLink, (typeLink === 1 ?
|
||||
{url: link, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled } :
|
||||
{linkTo: slideLink, numberTo: slideNum, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled}));
|
||||
}}
|
||||
/>
|
||||
<ListButton title={_t.textRemoveLink}
|
||||
className={`button-fill button-red`}
|
||||
onClick={() => {
|
||||
props.onRemoveLink()
|
||||
}}
|
||||
/>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const EditLink = inject("storeFocusObjects", "storeLinkSettings")(observer(PageLink));
|
||||
const LinkTo = inject("storeFocusObjects", "storeLinkSettings")(observer(PageLinkTo));
|
||||
const TypeLink = inject("storeFocusObjects", "storeLinkSettings")(observer(PageTypeLink));
|
||||
|
||||
export {EditLink,
|
||||
LinkTo as PageLinkTo,
|
||||
TypeLink as PageTypeLink}
|
|
@ -11,7 +11,42 @@
|
|||
"textChart": "Chart",
|
||||
"textFunction": "Function",
|
||||
"textShape": "Shape",
|
||||
"textOther": "Other"
|
||||
"textOther": "Other",
|
||||
"textGroups": "CATEGORIES",
|
||||
"textBack": "Back",
|
||||
"sCatLogical": "Logical",
|
||||
"sCatDateAndTime": "Date and time",
|
||||
"sCatEngineering": "Engineering",
|
||||
"sCatFinancial": "Financial",
|
||||
"sCatInformation": "Information",
|
||||
"sCatLookupAndReference": "Lookup and Reference",
|
||||
"sCatMathematic": "Math and trigonometry",
|
||||
"sCatStatistical": "Statistical",
|
||||
"sCatTextAndData": "Text and data",
|
||||
"textImage": "Image",
|
||||
"textInsertImage": "Insert Image",
|
||||
"textLinkSettings": "Link Settings",
|
||||
"textAddress": "Address",
|
||||
"textImageURL": "Image URL",
|
||||
"textPictureFromLibrary": "Picture from library",
|
||||
"textPictureFromURL": "Picture from URL",
|
||||
"txtNotUrl": "This field should be a URL in the format \"http://www.example.com\"",
|
||||
"textEmptyImgUrl": "You need to specify image URL.",
|
||||
"notcriticalErrorTitle": "Warning",
|
||||
"textLink": "Link",
|
||||
"textAddLink": "Add Link",
|
||||
"textLinkType": "Link Type",
|
||||
"textExternalLink": "External Link",
|
||||
"textInternalDataRange": "Internal Data Range",
|
||||
"textSheet": "Sheet",
|
||||
"textRange": "Range",
|
||||
"textRequired": "Required",
|
||||
"textDisplay": "Display",
|
||||
"textScreenTip": "Screen Tip",
|
||||
"textInsert": "Insert",
|
||||
"textInvalidRange": "ERROR! Invalid cells range",
|
||||
"textSortAndFilter": "Sort and Filter",
|
||||
"textFilter": "Filter"
|
||||
},
|
||||
"Edit" : {
|
||||
"textSelectObjectToEdit": "Select object to edit",
|
||||
|
|
|
@ -159,7 +159,7 @@ class MainController extends Component {
|
|||
const {t} = this.props;
|
||||
this.api = new Asc.spreadsheet_api({
|
||||
'id-view': 'editor_sdk',
|
||||
'id-input' : 'ce-cell-content',
|
||||
'id-input': 'idx-cell-content',
|
||||
'mobile': true
|
||||
// 'translate': translate
|
||||
});
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import React, {Component} from 'react';
|
||||
|
||||
import AddSortAndFilter from '../../view/add/AddFilter';
|
||||
|
||||
class AddFilterController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertFilter = this.onInsertFilter.bind(this);
|
||||
this.uncheckedFilter = this.uncheckedFilter.bind(this);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
|
||||
const filterInfo = api.asc_getCellInfo().asc_getAutoFilterInfo();
|
||||
const isFilter = (filterInfo ? filterInfo.asc_getIsAutoFilter() : false);
|
||||
|
||||
this.state = {
|
||||
isFilter: isFilter
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_registerCallback('asc_onError', this.uncheckedFilter);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_unregisterCallback('asc_onError', this.uncheckedFilter);
|
||||
}
|
||||
|
||||
uncheckedFilter (id, level, errData) {
|
||||
setTimeout(() => {
|
||||
if (id === Asc.c_oAscError.ID.AutoFilterDataRangeError) {
|
||||
this.setState({isFilter: false});
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
onInsertSort (type) {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_sortColFilter(type == 'down' ? Asc.c_oAscSortOptions.Ascending : Asc.c_oAscSortOptions.Descending, '', undefined, undefined, true);
|
||||
}
|
||||
|
||||
onInsertFilter (checked) {
|
||||
this.setState({isFilter: checked});
|
||||
const api = Common.EditorApi.get();
|
||||
const formatTableInfo = api.asc_getCellInfo().asc_getFormatTableInfo();
|
||||
const tablename = (formatTableInfo) ? formatTableInfo.asc_getTableName() : undefined;
|
||||
if (checked) {
|
||||
api.asc_addAutoFilter();
|
||||
} else {
|
||||
api.asc_changeAutoFilter(tablename, Asc.c_oAscChangeFilterOptions.filter, checked);
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddSortAndFilter getIsAutoFilter={this.getIsAutoFilter}
|
||||
onInsertSort={this.onInsertSort}
|
||||
onInsertFilter={this.onInsertFilter}
|
||||
isFilter={this.state.isFilter}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AddFilterController;
|
|
@ -1,12 +1,65 @@
|
|||
import React, {Component} from 'react';
|
||||
import {observer, inject} from "mobx-react";
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
|
||||
import AddFunction from '../../view/add/AddFunction';
|
||||
import {LocalStorage} from '../../../../../common/mobile/utils/LocalStorage';
|
||||
|
||||
import {AddFunction} from '../../view/add/AddFunction';
|
||||
|
||||
class _FunctionGroups extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
}
|
||||
componentDidMount() {
|
||||
Common.Notifications.on('engineCreated', api => {
|
||||
this.api = api;
|
||||
this.init();
|
||||
});
|
||||
}
|
||||
init () {
|
||||
const editorLang = LocalStorage.getItem('sse-settings-func-lang');
|
||||
this._editorLang = (editorLang ? editorLang : 'en').split(/[\-\_]/)[0].toLowerCase();
|
||||
const localizationFunctions = (data) => {
|
||||
this.api.asc_setLocalization(data);
|
||||
this.fill(data);
|
||||
};
|
||||
|
||||
fetch(`locale/l10n/functions/${this._editorLang}.json`)
|
||||
.then(response => response.json())
|
||||
.then((data) => {
|
||||
localizationFunctions(data);
|
||||
});
|
||||
}
|
||||
fill () {
|
||||
this._functions = {};
|
||||
const localizationFunctionsDesc = (data) => {
|
||||
let jsonDesc = {};
|
||||
try {
|
||||
jsonDesc = JSON.parse(data);
|
||||
} catch (e) {
|
||||
jsonDesc = data;
|
||||
}
|
||||
const grouparr = this.api.asc_getFormulasInfo();
|
||||
this.props.storeFunctions.initFunctions(grouparr, jsonDesc);
|
||||
};
|
||||
|
||||
fetch(`locale/l10n/functions/${this._editorLang}_desc.json`)
|
||||
.then(response => response.json())
|
||||
.then((data) => {
|
||||
localizationFunctionsDesc(data);
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const FunctionGroups = inject("storeFunctions")(observer(_FunctionGroups));
|
||||
|
||||
class AddFunctionController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertFunction = this.onInsertFunction.bind(this);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
|
@ -17,12 +70,19 @@ class AddFunctionController extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
onInsertFunction (type) {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_insertInCell(api.asc_getFormulaLocaleName(type), Asc.c_oAscPopUpSelectorType.Func, true);
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddFunction
|
||||
<AddFunction onInsertFunction={this.onInsertFunction}
|
||||
onOptionClick={this.props.onOptionClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AddFunctionController;
|
||||
export {FunctionGroups, AddFunctionController};
|
|
@ -0,0 +1,60 @@
|
|||
import React, {Component} from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
import {withTranslation} from 'react-i18next';
|
||||
|
||||
import {AddImage} from '../../view/add/AddImage';
|
||||
|
||||
class AddImageController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertByFile = this.onInsertByFile.bind(this);
|
||||
this.onInsertByUrl = this.onInsertByUrl.bind(this);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('.add-popup', true);
|
||||
} else {
|
||||
f7.popover.close('#add-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onInsertByFile () {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_addImage();
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
onInsertByUrl (value) {
|
||||
const { t } = this.props;
|
||||
const _t = t("View.Add", { returnObjects: true });
|
||||
|
||||
const _value = value.replace(/ /g, '');
|
||||
|
||||
if (_value) {
|
||||
if ((/((^https?)|(^ftp)):\/\/.+/i.test(_value))) {
|
||||
this.closeModal();
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_addImageDrawingObject(_value);
|
||||
} else {
|
||||
f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
|
||||
}
|
||||
} else {
|
||||
f7.dialog.alert(_t.textEmptyImgUrl, _t.notcriticalErrorTitle);
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddImage inTabs={this.props.inTabs}
|
||||
onInsertByFile={this.onInsertByFile}
|
||||
onInsertByUrl={this.onInsertByUrl}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const AddImageWithTranslation = withTranslation()(AddImageController);
|
||||
|
||||
export {AddImageWithTranslation as AddImageController};
|
121
apps/spreadsheeteditor/mobile/src/controller/add/AddLink.jsx
Normal file
121
apps/spreadsheeteditor/mobile/src/controller/add/AddLink.jsx
Normal file
|
@ -0,0 +1,121 @@
|
|||
import React, {Component} from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
import {withTranslation} from 'react-i18next';
|
||||
|
||||
import {AddLink} from '../../view/add/AddLink';
|
||||
|
||||
class AddLinkController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onInsertLink = this.onInsertLink.bind(this);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const cell = api.asc_getCellInfo();
|
||||
const celltype = cell.asc_getSelectionType();
|
||||
|
||||
this.allowInternal = (celltype !== Asc.c_oAscSelectionType.RangeImage && celltype !== Asc.c_oAscSelectionType.RangeShape &&
|
||||
celltype !== Asc.c_oAscSelectionType.RangeShapeText && celltype !== Asc.c_oAscSelectionType.RangeChart &&
|
||||
celltype !== Asc.c_oAscSelectionType.RangeChartText);
|
||||
|
||||
this.displayText = cell.asc_getLockText() ? 'locked' : cell.asc_getText();
|
||||
|
||||
// sheets
|
||||
let items = [];
|
||||
let wsc = api.asc_getWorksheetsCount();
|
||||
const aws = api.asc_getActiveWorksheetIndex();
|
||||
if (wsc > 0) {
|
||||
items = [];
|
||||
while ( !(--wsc < 0) ) {
|
||||
if ( !api.asc_isWorksheetHidden(wsc) ) {
|
||||
items.unshift({
|
||||
value: wsc,
|
||||
caption: api.asc_getWorksheetName(wsc)
|
||||
});
|
||||
if (wsc === aws) {
|
||||
this.activeSheet = {
|
||||
value: wsc,
|
||||
caption: api.asc_getWorksheetName(wsc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.sheets = items;
|
||||
}
|
||||
}
|
||||
|
||||
onInsertLink (args) {
|
||||
const api = Common.EditorApi.get();
|
||||
const { t } = this.props;
|
||||
const _t = t("View.Add", { returnObjects: true });
|
||||
|
||||
const link = new Asc.asc_CHyperlink();
|
||||
let display = '';
|
||||
|
||||
if (args.type == 'ext') {
|
||||
let url = args.url;
|
||||
const urltype = api.asc_getUrlType(url.trim());
|
||||
const isEmail = (urltype == 2);
|
||||
|
||||
if (urltype < 1) {
|
||||
f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
url = url.replace(/^\s+|\s+$/g, '');
|
||||
|
||||
if (!/(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(url))
|
||||
url = (isEmail ? 'mailto:' : 'http://' ) + url;
|
||||
|
||||
url = url.replace(new RegExp("%20", 'g'), " ");
|
||||
|
||||
link.asc_setType(Asc.c_oAscHyperlinkType.WebLink);
|
||||
link.asc_setHyperlinkUrl(url);
|
||||
display = url;
|
||||
} else {
|
||||
const isValid = api.asc_checkDataRange(Asc.c_oAscSelectionDialogType.FormatTable, args.url, false);
|
||||
|
||||
if (isValid !== Asc.c_oAscError.ID.No) {
|
||||
f7.dialog.alert(_t.textInvalidRange, _t.notcriticalErrorTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
link.asc_setType(Asc.c_oAscHyperlinkType.RangeLink);
|
||||
link.asc_setSheet(args.sheet);
|
||||
link.asc_setRange(args.url);
|
||||
|
||||
display = args.sheet + '!' + args.url;
|
||||
}
|
||||
|
||||
link.asc_setText(args.text == null ? null : !!args.text ? args.text : display);
|
||||
link.asc_setTooltip(args.tooltip);
|
||||
|
||||
api.asc_insertHyperlink(link);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('.add-popup', true);
|
||||
} else {
|
||||
f7.popover.close('#add-popover');
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddLink inTabs={this.props.inTabs}
|
||||
allowInternal={this.allowInternal}
|
||||
displayText={this.displayText}
|
||||
sheets={this.sheets}
|
||||
activeSheet={this.activeSheet}
|
||||
onInsertLink={this.onInsertLink}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const AddLinkWithTranslation = withTranslation()(AddLinkController);
|
||||
|
||||
export {AddLinkWithTranslation as AddLinkController};
|
|
@ -0,0 +1,31 @@
|
|||
import React, {Component} from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
import { withTranslation} from 'react-i18next';
|
||||
|
||||
import {AddOther} from '../../view/add/AddOther';
|
||||
|
||||
class AddOtherController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('.add-popup', true);
|
||||
} else {
|
||||
f7.popover.close('#add-popover');
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddOther
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const AddOtherWithTranslation = withTranslation()(AddOtherController);
|
||||
|
||||
export {AddOtherWithTranslation as AddOtherController};
|
|
@ -0,0 +1,35 @@
|
|||
import React, {Component} from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
|
||||
import AddShape from '../../view/add/AddShape';
|
||||
|
||||
class AddShapeController extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.onShapeClick = this.onShapeClick.bind(this);
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
if ( Device.phone ) {
|
||||
f7.sheet.close('.add-popup', true);
|
||||
} else {
|
||||
f7.popover.close('#add-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onShapeClick (type) {
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_addShapeOnSheet(type);
|
||||
this.closeModal();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<AddShape onShapeClick={this.onShapeClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AddShapeController;
|
|
@ -30,3 +30,12 @@
|
|||
--f7-popover-width: 360px;
|
||||
//--f7-page-content-extra-padding-top: 37px;
|
||||
}
|
||||
|
||||
.function-info {
|
||||
padding: 0 15px;
|
||||
}
|
||||
.page-function-info {
|
||||
&.page-content, .page-content {
|
||||
background-color: @white;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import '../../../../common/Gateway.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {App,Views,View,Navbar,NavLeft,NavRight,Link} from 'framework7-react';
|
||||
|
@ -5,7 +7,6 @@ import { f7ready } from 'framework7-react';
|
|||
|
||||
import routes from '../router/routes.js';
|
||||
|
||||
import '../../../../common/Gateway.js';
|
||||
import '../../../../common/main/lib/util/utils.js';
|
||||
import Notifications from '../../../../common/mobile/utils/notifications.js'
|
||||
import {MainController} from '../controller/Main';
|
||||
|
|
|
@ -9,6 +9,8 @@ import Statusbar from '../controller/StatusBar'
|
|||
import AddOptions from "../view/add/Add";
|
||||
import EditOptions from "../view/edit/Edit";
|
||||
|
||||
import {FunctionGroups} from "../controller/add/AddFunction";
|
||||
|
||||
export default class MainPage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -89,6 +91,8 @@ export default class MainPage extends Component {
|
|||
<CollaborationView onclosed={this.handleOptionsViewClosed.bind(this, 'coauth')} />
|
||||
}
|
||||
<Statusbar />
|
||||
|
||||
<FunctionGroups /> {/* hidden component*/}
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -136,11 +136,9 @@ export class storeFocusObjects {
|
|||
|
||||
@computed get shapeObject() {
|
||||
const shapes = [];
|
||||
console.log(this._focusObjects);
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Image) {
|
||||
if (object.get_ObjectValue() && object.get_ObjectValue().get_ShapeProperties()) {
|
||||
console.log(object);
|
||||
shapes.push(object);
|
||||
}
|
||||
}
|
||||
|
@ -155,10 +153,8 @@ export class storeFocusObjects {
|
|||
|
||||
@computed get imageObject() {
|
||||
const images = [];
|
||||
console.log(this._focusObjects);
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Image) {
|
||||
console.log(object);
|
||||
images.push(object);
|
||||
}
|
||||
}
|
||||
|
|
31
apps/spreadsheeteditor/mobile/src/store/functions.js
Normal file
31
apps/spreadsheeteditor/mobile/src/store/functions.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import {action, computed} from 'mobx';
|
||||
|
||||
export class storeFunctions {
|
||||
@action initFunctions (groups, data) {
|
||||
this.groups = groups;
|
||||
this.data = data;
|
||||
}
|
||||
@computed get functions () {
|
||||
const groups = this.groups;
|
||||
const data = this.data;
|
||||
const functions = {};
|
||||
for (let g in groups) {
|
||||
const group = groups[g];
|
||||
const groupname = group.asc_getGroupName();
|
||||
const funcarr = group.asc_getFormulasArray();
|
||||
|
||||
for (let f in funcarr) {
|
||||
const func = funcarr[f];
|
||||
const _name = func.asc_getName();
|
||||
functions[_name] = {
|
||||
type: _name,
|
||||
group: groupname,
|
||||
caption: func.asc_getLocaleName(),
|
||||
args: (data && data[_name]) ? data[_name].a : '',
|
||||
descr: (data && data[_name]) ? data[_name].d : ''
|
||||
};
|
||||
}
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
import {storeFocusObjects} from "./focusObjects";
|
||||
import {storeUsers} from '../../../../common/mobile/lib/store/users';
|
||||
import {storeWorksheets} from './sheets';
|
||||
import {storeFunctions} from './functions';
|
||||
import {storePalette} from "./palette";
|
||||
// import {storeTextSettings} from "./textSettings";
|
||||
// import {storeParagraphSettings} from "./paragraphSettings";
|
||||
|
@ -17,6 +18,7 @@ export const stores = {
|
|||
// storeDocumentSettings: new storeDocumentSettings(),
|
||||
users: new storeUsers(),
|
||||
sheets: new storeWorksheets(),
|
||||
storeFunctions: new storeFunctions(),
|
||||
// storeTextSettings: new storeTextSettings(),
|
||||
// storeParagraphSettings: new storeParagraphSettings(),
|
||||
storeShapeSettings: new storeShapeSettings(),
|
||||
|
|
|
@ -6,11 +6,53 @@ import { observer, inject } from "mobx-react";
|
|||
import {Device} from '../../../../../common/mobile/utils/device';
|
||||
|
||||
import AddChartController from "../../controller/add/AddChart";
|
||||
import AddFunctionController from "../../controller/add/AddFunction";
|
||||
//import AddShapeController from "../../controller/add/AddShape";
|
||||
//import {AddOtherController} from "../../controller/add/AddOther";
|
||||
import {AddFunctionController} from "../../controller/add/AddFunction";
|
||||
import {PageFunctionGroup, PageFunctionInfo} from "./AddFunction";
|
||||
import AddShapeController from "../../controller/add/AddShape";
|
||||
import {AddOtherController} from "../../controller/add/AddOther";
|
||||
import {AddImageController} from "../../controller/add/AddImage";
|
||||
import {PageImageLinkSettings} from "./AddImage";
|
||||
import {AddLinkController} from "../../controller/add/AddLink";
|
||||
import {PageTypeLink, PageSheet} from "./AddLink";
|
||||
import AddFilterController from "../../controller/add/AddFilter";
|
||||
|
||||
const routes = [
|
||||
// Functions
|
||||
{
|
||||
path: '/add-function-group/',
|
||||
component: PageFunctionGroup
|
||||
},
|
||||
{
|
||||
path: '/add-function-info/',
|
||||
component: PageFunctionInfo
|
||||
},
|
||||
// Image
|
||||
{
|
||||
path: '/add-image/',
|
||||
component: AddImageController
|
||||
},
|
||||
{
|
||||
path: '/add-image-from-url/',
|
||||
component: PageImageLinkSettings
|
||||
},
|
||||
// Link
|
||||
{
|
||||
path: '/add-link/',
|
||||
component: AddLinkController
|
||||
},
|
||||
{
|
||||
path: '/add-link-type/',
|
||||
component: PageTypeLink
|
||||
},
|
||||
{
|
||||
path: '/add-link-sheet/',
|
||||
component: PageSheet
|
||||
},
|
||||
// Other
|
||||
{
|
||||
path: '/add-sort-and-filter/',
|
||||
component: AddFilterController
|
||||
}
|
||||
];
|
||||
|
||||
const AddLayoutNavbar = ({ tabs, inPopover }) => {
|
||||
|
@ -62,21 +104,40 @@ const AddTabs = props => {
|
|||
caption: _t.textFunction,
|
||||
id: 'add-function',
|
||||
icon: 'icon-add-formula',
|
||||
component: <AddFunctionController/>
|
||||
component: <AddFunctionController onOptionClick={props.onOptionClick}/>
|
||||
});
|
||||
}
|
||||
if (!showPanels || showPanels.indexOf('shape') > 0) {
|
||||
tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController/>
|
||||
});
|
||||
}
|
||||
if (showPanels && showPanels.indexOf('image') !== -1) {
|
||||
tabs.push({
|
||||
caption: _t.textImage,
|
||||
id: 'add-image',
|
||||
icon: 'icon-add-image',
|
||||
component: <AddImageController inTabs={true}/>
|
||||
});
|
||||
}
|
||||
if (!showPanels) {
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController/>
|
||||
});
|
||||
}
|
||||
if (showPanels && showPanels === 'hyperlink') {
|
||||
tabs.push({
|
||||
caption: _t.textAddLink,
|
||||
id: 'add-link',
|
||||
component: <AddLinkController/>
|
||||
});
|
||||
}
|
||||
/*tabs.push({
|
||||
caption: _t.textShape,
|
||||
id: 'add-shape',
|
||||
icon: 'icon-add-shape',
|
||||
component: <AddShapeController />
|
||||
});
|
||||
tabs.push({
|
||||
caption: _t.textOther,
|
||||
id: 'add-other',
|
||||
icon: 'icon-add-other',
|
||||
component: <AddOtherController />
|
||||
});*/
|
||||
return (
|
||||
<View style={props.style} stackPages={true} routes={routes}>
|
||||
<Page pageContent={false}>
|
||||
|
@ -93,8 +154,8 @@ class AddView extends Component {
|
|||
|
||||
this.onoptionclick = this.onoptionclick.bind(this);
|
||||
}
|
||||
onoptionclick(page){
|
||||
f7.views.current.router.navigate(page);
|
||||
onoptionclick(page, props){
|
||||
f7.views.current.router.navigate(page, props);
|
||||
}
|
||||
render() {
|
||||
const show_popover = this.props.usePopover;
|
||||
|
|
36
apps/spreadsheeteditor/mobile/src/view/add/AddFilter.jsx
Normal file
36
apps/spreadsheeteditor/mobile/src/view/add/AddFilter.jsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
import React, {useState} from 'react';
|
||||
import {Page, Navbar, List, ListItem, Icon, Row, Toggle} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AddSortAndFilter = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const isFilter = props.isFilter;
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textSortAndFilter} backLink={_t.textBack}/>
|
||||
<List>
|
||||
<ListItem className='buttons'>
|
||||
<Row>
|
||||
<a className='button' onClick={() => {props.onInsertSort('down')}}>
|
||||
<Icon slot="media" icon="sortdown"></Icon>
|
||||
</a>
|
||||
<a className='button' onClick={() => {props.onInsertSort('up')}}>
|
||||
<Icon slot="media" icon="sortup"></Icon>
|
||||
</a>
|
||||
</Row>
|
||||
</ListItem>
|
||||
</List>
|
||||
<List>
|
||||
<ListItem title={_t.textFilter}>
|
||||
<Toggle checked={isFilter}
|
||||
onToggleChange={(prev) => {
|
||||
props.onInsertFilter(!prev);
|
||||
}}/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
export default AddSortAndFilter;
|
|
@ -1,12 +1,143 @@
|
|||
import React, {Fragment, useState} from 'react';
|
||||
import {observer, inject} from "mobx-react";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {List, ListItem, Page, Navbar, Icon, BlockTitle} from 'framework7-react';
|
||||
|
||||
const PageInfo = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const f = props.functionInfo;
|
||||
return(
|
||||
<Page className='page-function-info'>
|
||||
<Navbar title={f.caption} backLink={_t.textBack}/>
|
||||
<div className='function-info'>
|
||||
<h3>{`${f.caption} ${f.args}`}</h3>
|
||||
<p>{f.descr}</p>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const PageGroup = ({name, type, functions, onInsertFunction, f7router}) => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const items = [];
|
||||
for (let k in functions) {
|
||||
if (functions[k].group == type)
|
||||
items.push(functions[k]);
|
||||
}
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={name} backLink={_t.textBack}/>
|
||||
<List>
|
||||
{items.map((f, index) => {
|
||||
return(
|
||||
<ListItem key={`f-${index}`}
|
||||
link={'#'}
|
||||
title={f.caption}
|
||||
className='no-indicator'
|
||||
onClick={() => {onInsertFunction(f.type);}}
|
||||
>
|
||||
<div slot='after'
|
||||
onClick={(event) => {
|
||||
f7router.navigate('/add-function-info/', {
|
||||
props: {
|
||||
functionInfo: f
|
||||
}
|
||||
});
|
||||
event.stopPropagation();
|
||||
}}>
|
||||
<Icon icon='icon-info'/>
|
||||
</div>
|
||||
</ListItem>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const AddFunction = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const store = props.storeFunctions;
|
||||
const functions = store.functions;
|
||||
const quickFunctions = [
|
||||
{caption: 'SUM', type: 'SUM'},
|
||||
{caption: 'MIN', type: 'MIN'},
|
||||
{caption: 'MAX', type: 'MAX'},
|
||||
{caption: 'COUNT', type: 'COUNT'}
|
||||
];
|
||||
if (functions) {
|
||||
quickFunctions.forEach((quickFunction) => {
|
||||
const f = functions[quickFunction.type];
|
||||
quickFunction.caption = f.caption;
|
||||
quickFunction.args = f.args;
|
||||
quickFunction.descr = f.descr;
|
||||
});
|
||||
}
|
||||
let name = '';
|
||||
const descriptions = ['DateAndTime', 'Engineering', 'Financial', 'Information', 'Logical', 'LookupAndReference', 'Mathematic', 'Statistical', 'TextAndData' ];
|
||||
const groups = [];
|
||||
for (let i = 0; i < descriptions.length; i++) {
|
||||
name = descriptions[i];
|
||||
name = _t['sCat' + name] || name;
|
||||
groups.push({
|
||||
type: descriptions[i],
|
||||
name: name
|
||||
})
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
|
||||
<List>
|
||||
{quickFunctions.map((f, index) => {
|
||||
return (
|
||||
<ListItem key={`f-${index}`}
|
||||
title={f.caption}
|
||||
className='no-indicator'
|
||||
link='#'
|
||||
onClick={() => {props.onInsertFunction(f.type);}}
|
||||
>
|
||||
<div slot='after'
|
||||
onClick={(event) => {
|
||||
props.onOptionClick('/add-function-info/', {
|
||||
props: {
|
||||
functionInfo: f
|
||||
}
|
||||
});
|
||||
event.stopPropagation();
|
||||
}}>
|
||||
<Icon icon='icon-info'/>
|
||||
</div>
|
||||
</ListItem>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
<BlockTitle>{_t.textGroups}</BlockTitle>
|
||||
<List>
|
||||
{groups.map((group, index) => {
|
||||
return(
|
||||
<ListItem key={`gr-${index}`}
|
||||
link={'/add-function-group/'}
|
||||
title={group.name}
|
||||
routeProps={{
|
||||
name: group.name,
|
||||
type: group.type,
|
||||
functions: functions,
|
||||
onInsertFunction: props.onInsertFunction
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</Fragment>
|
||||
)
|
||||
};
|
||||
|
||||
export default AddFunction;
|
||||
const AddFunctionContainer = inject("storeFunctions")(observer(AddFunction));
|
||||
|
||||
export {
|
||||
AddFunctionContainer as AddFunction,
|
||||
PageGroup as PageFunctionGroup,
|
||||
PageInfo as PageFunctionInfo
|
||||
};
|
61
apps/spreadsheeteditor/mobile/src/view/add/AddImage.jsx
Normal file
61
apps/spreadsheeteditor/mobile/src/view/add/AddImage.jsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import React, {Fragment, useState} from 'react';
|
||||
import {Page, Navbar, BlockTitle, List, ListItem, ListInput, ListButton, Icon} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AddImageList = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
return (
|
||||
<List>
|
||||
<ListItem title={_t.textPictureFromLibrary} onClick={() => {props.onInsertByFile()}}>
|
||||
<Icon slot="media" icon="icon-image-library"></Icon>
|
||||
</ListItem>
|
||||
<ListItem title={_t.textPictureFromURL} link={'/add-image-from-url/'} routeProps={{
|
||||
onInsertByUrl: props.onInsertByUrl
|
||||
}}>
|
||||
<Icon slot="media" icon="icon-link"></Icon>
|
||||
</ListItem>
|
||||
</List>
|
||||
)
|
||||
};
|
||||
|
||||
const PageLinkSettings = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const [stateValue, setValue] = useState('');
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLinkSettings} backLink={_t.textBack}></Navbar>
|
||||
<BlockTitle>{_t.textAddress}</BlockTitle>
|
||||
<List>
|
||||
<ListInput
|
||||
type='text'
|
||||
placeholder={_t.textImageURL}
|
||||
value={stateValue}
|
||||
onChange={(event) => {setValue(event.target.value)}}
|
||||
>
|
||||
</ListInput>
|
||||
</List>
|
||||
<List>
|
||||
<ListButton className={'button-fill button-raised' + (stateValue.length < 1 ? ' disabled' : '')}
|
||||
title={_t.textInsertImage}
|
||||
onClick={() => {props.onInsertByUrl(stateValue)}}></ListButton>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const AddImage = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
return (
|
||||
props.inTabs ?
|
||||
<AddImageList onInsertByFile={props.onInsertByFile} onInsertByUrl={ props.onInsertByUrl} /> :
|
||||
<Page>
|
||||
<Navbar title={_t.textImage} backLink={_t.textBack}/>
|
||||
<AddImageList onInsertByFile={props.onInsertByFile} onInsertByUrl={ props.onInsertByUrl} />
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
export {AddImage, PageLinkSettings as PageImageLinkSettings};
|
151
apps/spreadsheeteditor/mobile/src/view/add/AddLink.jsx
Normal file
151
apps/spreadsheeteditor/mobile/src/view/add/AddLink.jsx
Normal file
|
@ -0,0 +1,151 @@
|
|||
import React, {Fragment, useState} from 'react';
|
||||
import {Page, Navbar, BlockTitle, List, ListItem, ListInput, ListButton, Icon} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {Device} from "../../../../../common/mobile/utils/device";
|
||||
|
||||
const PageTypeLink = ({curType, changeType}) => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const [typeLink, setTypeLink] = useState(curType);
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textLinkType} backLink={_t.textBack}/>
|
||||
<List>
|
||||
<ListItem title={_t.textExternalLink} radio checked={typeLink === 'ext'} onClick={() => {setTypeLink('ext'); changeType('ext');}}></ListItem>
|
||||
<ListItem title={_t.textInternalDataRange} radio checked={typeLink === 'int'} onClick={() => {setTypeLink('int'); changeType('int');}}></ListItem>
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const PageSheet = ({curSheet, sheets, changeSheet}) => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
const [stateSheet, setSheet] = useState(curSheet.value);
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={_t.textSheet} backLink={_t.textBack}/>
|
||||
<List>
|
||||
{sheets.map((sheet) => {
|
||||
return(
|
||||
<ListItem key={`sheet-${sheet.value}`}
|
||||
title={sheet.caption}
|
||||
radio
|
||||
checked={stateSheet === sheet.value}
|
||||
onClick={() => {
|
||||
setSheet(sheet.value);
|
||||
changeSheet(sheet);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
</List>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
const AddLinkView = props => {
|
||||
const isIos = Device.ios;
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
|
||||
const [typeLink, setTypeLink] = useState('ext');
|
||||
const textType = typeLink === 'ext' ? _t.textExternalLink : _t.textInternalDataRange;
|
||||
const changeType = (newType) => {
|
||||
setTypeLink(newType);
|
||||
};
|
||||
|
||||
const [link, setLink] = useState('');
|
||||
|
||||
let displayText = props.displayText;
|
||||
const displayDisabled = displayText === 'locked';
|
||||
displayText = displayDisabled ? _t.textSelectedRange : displayText;
|
||||
const [stateDisplayText, setDisplayText] = useState(displayText);
|
||||
|
||||
const [screenTip, setScreenTip] = useState('');
|
||||
|
||||
const activeSheet = props.activeSheet;
|
||||
const [curSheet, setSheet] = useState(activeSheet);
|
||||
const changeSheet = (sheet) => {
|
||||
setSheet(sheet);
|
||||
};
|
||||
|
||||
const [range, setRange] = useState('');
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<List inlineLabels className='inputs-list'>
|
||||
{props.allowInternal &&
|
||||
<ListItem link={'/add-link-type/'} title={_t.textLinkType} after={textType} routeProps={{
|
||||
changeType: changeType,
|
||||
curType: typeLink
|
||||
}}/>
|
||||
}
|
||||
{typeLink === 'ext' &&
|
||||
<ListInput label={_t.textLink}
|
||||
type="text"
|
||||
placeholder={_t.textLink}
|
||||
value={link}
|
||||
onChange={(event) => {setLink(event.target.value)}}
|
||||
className={isIos ? 'list-input-right' : ''}
|
||||
/>
|
||||
}
|
||||
{typeLink === 'int' &&
|
||||
<ListItem link={'/add-link-sheet/'} title={_t.textSheet} after={curSheet.caption} routeProps={{
|
||||
changeSheet: changeSheet,
|
||||
sheets: props.sheets,
|
||||
curSheet: curSheet
|
||||
}}/>
|
||||
}
|
||||
{typeLink === 'int' &&
|
||||
<ListInput label={_t.textRange}
|
||||
type="text"
|
||||
placeholder={_t.textRequired}
|
||||
value={range}
|
||||
onChange={(event) => {setRange(event.target.value)}}
|
||||
className={isIos ? 'list-input-right' : ''}
|
||||
/>
|
||||
}
|
||||
<ListInput label={_t.textDisplay}
|
||||
type="text"
|
||||
placeholder={_t.textDisplay}
|
||||
value={stateDisplayText}
|
||||
disabled={displayDisabled}
|
||||
onChange={(event) => {setDisplayText(event.target.value)}}
|
||||
className={isIos ? 'list-input-right' : ''}
|
||||
/>
|
||||
<ListInput label={_t.textScreenTip}
|
||||
type="text"
|
||||
placeholder={_t.textScreenTip}
|
||||
value={screenTip}
|
||||
onChange={(event) => {setScreenTip(event.target.value)}}
|
||||
className={isIos ? 'list-input-right' : ''}
|
||||
/>
|
||||
</List>
|
||||
<List>
|
||||
<ListButton title={_t.textInsert}
|
||||
className={`button-fill button-raised${(typeLink === 'ext' && link.length < 1 || typeLink === 'int' && range.length < 1) && ' disabled'}`}
|
||||
onClick={() => {props.onInsertLink(typeLink === 'ext' ?
|
||||
{type: 'ext', url: link, text: stateDisplayText, tooltip: screenTip} :
|
||||
{type: 'int', url: range, sheet: curSheet.caption, text: stateDisplayText, tooltip: screenTip})}}
|
||||
/>
|
||||
</List>
|
||||
</Fragment>
|
||||
)
|
||||
};
|
||||
|
||||
const AddLink = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
return (
|
||||
props.inTabs ?
|
||||
<AddLinkView allowInternal={props.allowInternal} displayText={props.displayText} sheets={props.sheets} activeSheet={props.activeSheet} onInsertLink={props.onInsertLink}/> :
|
||||
<Page>
|
||||
<Navbar title={_t.textAddLink} backLink={_t.textBack}/>
|
||||
<AddLinkView allowInternal={props.allowInternal} displayText={props.displayText} sheets={props.sheets} activeSheet={props.activeSheet} onInsertLink={props.onInsertLink}/>
|
||||
</Page>
|
||||
)
|
||||
};
|
||||
|
||||
export {AddLink, PageTypeLink, PageSheet};
|
23
apps/spreadsheeteditor/mobile/src/view/add/AddOther.jsx
Normal file
23
apps/spreadsheeteditor/mobile/src/view/add/AddOther.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import {List, ListItem, Icon} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AddOther = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('View.Add', {returnObjects: true});
|
||||
return (
|
||||
<List>
|
||||
<ListItem title={_t.textImage} link={'/add-image/'}>
|
||||
<Icon slot="media" icon="icon-insimage"></Icon>
|
||||
</ListItem>
|
||||
<ListItem title={_t.textLink} link={'/add-link/'}>
|
||||
<Icon slot="media" icon="icon-link"></Icon>
|
||||
</ListItem>
|
||||
<ListItem title={_t.textSortAndFilter} link={'/add-sort-and-filter/'}>
|
||||
<Icon slot="media" icon="icon-sort"></Icon>
|
||||
</ListItem>
|
||||
</List>
|
||||
)
|
||||
};
|
||||
|
||||
export {AddOther};
|
27
apps/spreadsheeteditor/mobile/src/view/add/AddShape.jsx
Normal file
27
apps/spreadsheeteditor/mobile/src/view/add/AddShape.jsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import React, {Fragment, useState} from 'react';
|
||||
import {observer, inject} from "mobx-react";
|
||||
|
||||
const AddShape = props => {
|
||||
const shapes = props.storeShapeSettings.getStyleGroups();
|
||||
return (
|
||||
<div className={'dataview shapes'}>
|
||||
{shapes.map((row, indexRow) => {
|
||||
return (
|
||||
<ul className="row" key={'shape-row-' + indexRow}>
|
||||
{row.map((shape, index) => {
|
||||
return (
|
||||
<li key={'shape-' + indexRow + '-' + index} onClick={() => {props.onShapeClick(shape.type)}}>
|
||||
<div className="thumb"
|
||||
style={{WebkitMaskImage: `url('resources/img/shapes/${shape.thumb}')`}}>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
export default inject("storeShapeSettings")(observer(AddShape));
|
|
@ -12,7 +12,6 @@ const EditShape = props => {
|
|||
// const selections = storeFocusObjects.selections;
|
||||
// console.log(selections);
|
||||
const shapeObject = storeFocusObjects.shapeObject;
|
||||
console.log(shapeObject);
|
||||
const canFill = shapeObject.get_ShapeProperties().asc_getCanFill();
|
||||
|
||||
return (
|
||||
|
|
Loading…
Reference in a new issue