[SSE mobile] Added the ability insert links
This commit is contained in:
parent
368c773d16
commit
683a9722e5
|
@ -242,6 +242,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.list-input-right input {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-buttons {
|
.tab-buttons {
|
||||||
|
|
|
@ -32,7 +32,19 @@
|
||||||
"textPictureFromURL": "Picture from URL",
|
"textPictureFromURL": "Picture from URL",
|
||||||
"txtNotUrl": "This field should be a URL in the format \"http://www.example.com\"",
|
"txtNotUrl": "This field should be a URL in the format \"http://www.example.com\"",
|
||||||
"textEmptyImgUrl": "You need to specify image URL.",
|
"textEmptyImgUrl": "You need to specify image URL.",
|
||||||
"notcriticalErrorTitle": "Warning"
|
"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"
|
||||||
},
|
},
|
||||||
"Edit" : {
|
"Edit" : {
|
||||||
"textSelectObjectToEdit": "Select object to edit",
|
"textSelectObjectToEdit": "Select object to edit",
|
||||||
|
|
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};
|
|
@ -12,6 +12,8 @@ import AddShapeController from "../../controller/add/AddShape";
|
||||||
import {AddOtherController} from "../../controller/add/AddOther";
|
import {AddOtherController} from "../../controller/add/AddOther";
|
||||||
import {AddImageController} from "../../controller/add/AddImage";
|
import {AddImageController} from "../../controller/add/AddImage";
|
||||||
import {PageImageLinkSettings} from "./AddImage";
|
import {PageImageLinkSettings} from "./AddImage";
|
||||||
|
import {AddLinkController} from "../../controller/add/AddLink";
|
||||||
|
import {PageTypeLink, PageSheet} from "./AddLink";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// Functions
|
// Functions
|
||||||
|
@ -31,6 +33,19 @@ const routes = [
|
||||||
{
|
{
|
||||||
path: '/add-image-from-url/',
|
path: '/add-image-from-url/',
|
||||||
component: PageImageLinkSettings
|
component: PageImageLinkSettings
|
||||||
|
},
|
||||||
|
// Link
|
||||||
|
{
|
||||||
|
path: '/add-link/',
|
||||||
|
component: AddLinkController
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/add-link-type/',
|
||||||
|
component: PageTypeLink
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/add-link-sheet/',
|
||||||
|
component: PageSheet
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -110,6 +125,13 @@ const AddTabs = props => {
|
||||||
component: <AddOtherController/>
|
component: <AddOtherController/>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (showPanels && showPanels === 'hyperlink') {
|
||||||
|
tabs.push({
|
||||||
|
caption: _t.textAddLink,
|
||||||
|
id: 'add-link',
|
||||||
|
component: <AddLinkController/>
|
||||||
|
});
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<View style={props.style} stackPages={true} routes={routes}>
|
<View style={props.style} stackPages={true} routes={routes}>
|
||||||
<Page pageContent={false}>
|
<Page pageContent={false}>
|
||||||
|
|
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};
|
|
@ -10,6 +10,9 @@ const AddOther = props => {
|
||||||
<ListItem title={_t.textImage} link={'/add-image/'}>
|
<ListItem title={_t.textImage} link={'/add-image/'}>
|
||||||
<Icon slot="media" icon="icon-insimage"></Icon>
|
<Icon slot="media" icon="icon-insimage"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem title={_t.textLink} link={'/add-link/'}>
|
||||||
|
<Icon slot="media" icon="icon-link"></Icon>
|
||||||
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue