diff --git a/apps/common/mobile/resources/less/common-ios.less b/apps/common/mobile/resources/less/common-ios.less index 0441d6b292..ee582bc7be 100644 --- a/apps/common/mobile/resources/less/common-ios.less +++ b/apps/common/mobile/resources/less/common-ios.less @@ -52,6 +52,12 @@ ul { border-radius: 0; } + + li:first-child, li:last-child { + > label { + border-radius: 0; + } + } } } @@ -359,4 +365,10 @@ margin-top: 20px; } } + + .dataview, #add-table, #add-shape { + &.page-content { + background-color: @white; + } + } } diff --git a/apps/common/mobile/resources/less/common.less b/apps/common/mobile/resources/less/common.less index 9a8f835e68..02bcddc4e1 100644 --- a/apps/common/mobile/resources/less/common.less +++ b/apps/common/mobile/resources/less/common.less @@ -50,6 +50,37 @@ } } +.chart-types { + width: 100%; + .row { + padding: 0 10px; + } + li { + width: 60px; + height: 60px; + margin: 6px; + + .thumb { + width: 100%; + height: 100%; + background-size: contain; + } + } +} + +.chart-styles { + .row { + li { + margin: 0; + padding: 1px; + } + img { + width: 50px; + height: 50px; + } + } +} + .segmented { .decrement, .increment { text-overflow: clip; @@ -377,7 +408,6 @@ .table-styles { width: 100%; .row { - padding: 0; &, li { margin-bottom: 12px; } diff --git a/apps/common/mobile/resources/less/search.less b/apps/common/mobile/resources/less/search.less new file mode 100644 index 0000000000..ab694cea8d --- /dev/null +++ b/apps/common/mobile/resources/less/search.less @@ -0,0 +1,16 @@ +@statusBarBorderColor: #cbcbcb; + +.navbar { + .searchbar { + background-color: var(--f7-navbar-bg-color); + + .buttons-row { + align-self: center; + display: flex; + } + + .searchbar-bg { + .hairline(bottom, @statusBarBorderColor); + } + } +} diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 1de8002b92..b6004ece59 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -1,4 +1,32 @@ { + "Main" : { + "SDK": { + "Series": "Series", + "Diagram Title": "Chart Title", + "X Axis": "X Axis XAS", + "Y Axis": "Y Axis", + "Your text here": "Your text here", + "Footer": "Footer", + "Header": "Header", + "Normal": "Normal", + "No Spacing": "No Spacing", + "Heading 1": "Heading 1", + "Heading 2": "Heading 2", + "Heading 3": "Heading 3", + "Heading 4": "Heading 4", + "Heading 5": "Heading 5", + "Heading 6": "Heading 6", + "Heading 7": "Heading 7", + "Heading 8": "Heading 8", + "Heading 9": "Heading 9", + "Title": "Title", + "Subtitle": "Subtitle", + "Quote": "Quote", + "Intense Quote": "Intense Quote", + "List Paragraph": "List Paragraph", + "footnote text": "Footnote Text" + } + }, "Common": { "ThemeColorPalette": { "textThemeColors": "Theme Colors", @@ -188,12 +216,57 @@ "textBandedRow": "Banded Row", "textFirstColumn": "First Column", "textLastColumn": "Last Column", - "textBandedColumn": "Banded Column" + "textBandedColumn": "Banded Column", + "textType": "Type" }, "Add": { "textTable": "Table", "textShape": "Shape", "textImage": "Image", - "textOther": "Other" + "textOther": "Other", + "textTableSize": "Table Size", + "textColumns": "Columns", + "textRows": "Rows", + "textCancel": "Cancel", + "textPictureFromLibrary": "Picture from Library", + "textPictureFromURL": "Picture from URL", + "textLinkSettings": "LinkSettings", + "textBack": "Back", + "textEmptyImgUrl": "You need to specify image URL.", + "txtNotUrl": "This field should be a URL in the format \"http://www.example.com\"", + "notcriticalErrorTitle": "Warning", + "textAddress": "Address", + "textImageURL": "Image URL", + "textInsertImage": "Insert Image", + "textComment": "Comment", + "textLink": "Link", + "textPageNumber": "Page Number", + "textBreak": "Break", + "textFootnote": "Footnote", + "textAddLink": "Add Link", + "textDisplay": "Display", + "textScreenTip": "Screen Tip", + "textInsert": "Insert", + "textPosition": "Position", + "textLeftTop": "Left Top", + "textCenterTop": "Center Top", + "textRightTop": "Right Top", + "textLeftBottom": "Left Bottom", + "textCenterBottom": "Center Bottom", + "textRightBottom": "Right Bottom", + "textCurrentPosition": "Current Position", + "textPageBreak": "Page Break", + "textColumnBreak": "Column Break", + "textSectionBreak": "Section Break", + "textNextPage": "Next Page", + "textContinuousPage": "Continuous Page", + "textEvenPage": "Even Page", + "textOddPage": "Odd Page", + "textInsertFootnote": "Insert Footnote", + "textBottomOfPage": "Bottom Of Page", + "textBelowText": "Below Text", + "textStartAt": "Start At", + "textLocation": "Location", + "textFormat": "Format" } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/controller/Main.jsx b/apps/documenteditor/mobile/src/controller/Main.jsx index 69e5de2a14..ad66e92e65 100644 --- a/apps/documenteditor/mobile/src/controller/Main.jsx +++ b/apps/documenteditor/mobile/src/controller/Main.jsx @@ -6,7 +6,7 @@ import { withTranslation } from 'react-i18next'; import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'; import { onAdvancedOptions } from './settings/Download.jsx'; -@inject("storeAppOptions", "storeDocumentSettings", "storeFocusObjects", "storeTextSettings", "storeParagraphSettings", "storeTableSettings", "storeDocumentInfo") +@inject("storeAppOptions", "storeDocumentSettings", "storeFocusObjects", "storeTextSettings", "storeParagraphSettings", "storeTableSettings", "storeDocumentInfo", "storeChartSettings") class MainController extends Component { constructor(props) { super(props) @@ -150,10 +150,12 @@ class MainController extends Component { _process_array(dep_scripts, promise_get_script) .then ( result => { + window["flat_desine"] = true; + const {t} = this.props; this.api = new Asc.asc_docs_api({ 'id-view' : 'editor_sdk', 'mobile' : true, - // 'translate': translate + 'translate': t('Main.SDK', {returnObjects:true}) }); this.appOptions = {}; @@ -249,6 +251,7 @@ class MainController extends Component { }); //paragraph settings + this.api.asc_setParagraphStylesSizes(330, 38); const storeParagraphSettings = this.props.storeParagraphSettings; this.api.asc_registerCallback('asc_onInitEditorStyles', (styles) => { storeParagraphSettings.initEditorStyles(styles); @@ -263,6 +266,14 @@ class MainController extends Component { storeTableSettings.initTableTemplates(templates); }); + //chart settings + const storeChartSettings = this.props.storeChartSettings; + this.api.asc_registerCallback('asc_onUpdateChartStyles', () => { + if (storeFocusObjects.chartObject && storeFocusObjects.chartObject.get_ChartProperties()) { + storeChartSettings.updateChartStyles(this.api.asc_getChartPreviews(storeFocusObjects.chartObject.get_ChartProperties().getType())); + } + }); + // Document Info const storeDocumentInfo = this.props.storeDocumentInfo; diff --git a/apps/documenteditor/mobile/src/controller/Search.jsx b/apps/documenteditor/mobile/src/controller/Search.jsx new file mode 100644 index 0000000000..6c662c5f3c --- /dev/null +++ b/apps/documenteditor/mobile/src/controller/Search.jsx @@ -0,0 +1,8 @@ +import React from 'react'; +import SearchView, {SearchSettingsView} from '../view/Search' + +const SearchController = props => { + return +}; + +export {SearchController as Search, SearchSettingsView as SearchSettings}; diff --git a/apps/documenteditor/mobile/src/controller/add/AddImage.jsx b/apps/documenteditor/mobile/src/controller/add/AddImage.jsx new file mode 100644 index 0000000000..c3a10eaff3 --- /dev/null +++ b/apps/documenteditor/mobile/src/controller/add/AddImage.jsx @@ -0,0 +1,59 @@ +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("Add", { returnObjects: true }); + + const _value = value.replace(/ /g, ''); + + if (_value) { + if ((/((^https?)|(^ftp)):\/\/.+/i.test(_value))) { + this.closeModal(); + const api = Common.EditorApi.get(); + api.AddImageUrl(_value); + } else { + f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle); + } + } else { + f7.dialog.alert(_t.textEmptyImgUrl, _t.notcriticalErrorTitle); + } + } + + render () { + return ( + + ) + } +} + +const AddImageWithTranslation = withTranslation()(AddImageController); + +export {AddImageWithTranslation as AddImageController}; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/controller/add/AddOther.jsx b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx new file mode 100644 index 0000000000..9793ebfb35 --- /dev/null +++ b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx @@ -0,0 +1,300 @@ +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'; + +// footnote converting metods +const _10toS = (value) => { + value = parseInt(value); + let n = Math.ceil(value / 26), + code = String.fromCharCode((value-1) % 26 + "A".charCodeAt(0)) , + result = ''; + for (var i=0; i { + if ( str.length<1 || (new RegExp('[^' + str.charAt(0) + ']')).test(str) || !/[A-Z]/.test(str)) return 1; + let n = str.length-1, + result = str.charCodeAt(0) - "A".charCodeAt(0) + 1; + result += 26*n; + return result; +}; +const _10toRome = (value) => { + value = parseInt(value); + let result = '', + digits = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]]; + let val = digits[0][1], + div = Math.floor(value / val), + n = 0; + for (var i=0; i0) { + val = digits[n][1]; + div = value - val; + if (div>=0) { + result += digits[n][0]; + value = div; + } else + n++; + } + return result; +}; +const _Rometo10 = (str) => { + if ( !/[IVXLCDM]/.test(str) || str.length<1 ) return 1; + let digits = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}; + var n = str.length-1, + result = digits[str.charAt(n)], + prev = result; + for (var i=n-1; i>=0; i-- ) { + var val = digits[str.charAt(i)]; + if (val10) return 1; + val *= -1; + } + result += val; + prev = Math.abs(val); + } + return result; +}; + +class AddOtherController extends Component { + constructor (props) { + super(props); + this.onInsertLink = this.onInsertLink.bind(this); + this.onInsertPageNumber = this.onInsertPageNumber.bind(this); + this.onPageBreak = this.onPageBreak.bind(this); + this.onColumnBreak = this.onColumnBreak.bind(this); + this.onInsertSectionBreak = this.onInsertSectionBreak.bind(this); + this.getFootnoteStartAt = this.getFootnoteStartAt.bind(this); + this.onFootnoteStartAt = this.onFootnoteStartAt.bind(this); + this.onInsertFootnote = this.onInsertFootnote.bind(this); + this.initFootnoteStartAt = this.initFootnoteStartAt.bind(this); + this.getFootnoteProps = this.getFootnoteProps.bind(this); + } + + closeModal () { + if ( Device.phone ) { + f7.sheet.close('.add-popup', true); + } else { + f7.popover.close('#add-popover'); + } + } + + getDisplayLinkText () { + const api = Common.EditorApi.get(); + return api.can_AddHyperlink(); + } + + onInsertLink (url, display, tip) { + const api = Common.EditorApi.get(); + + const { t } = this.props; + const _t = t("Add", { returnObjects: true }); + + const urltype = api.asc_getUrlType(url.trim()); + const isEmail = (urltype == 2); + + if (urltype < 1) { + f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle); + return; + } + + let _url = url.replace(/^\s+|\s+$/g,''); + + if (! /(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(_url) ) + _url = (isEmail ? 'mailto:' : 'http://' ) + _url; + + _url = _url.replace(new RegExp("%20",'g')," "); + + const props = new Asc.CHyperlinkProperty(); + props.put_Value(_url); + props.put_Text(!display ? _url : display); + props.put_ToolTip(tip); + + api.add_Hyperlink(props); + + this.closeModal(); + } + + onInsertPageNumber (type) { + const api = Common.EditorApi.get(); + + let value = -1; + + if (2 == type.length) { + const c_pageNumPosition = { + PAGE_NUM_POSITION_TOP: 0x01, + PAGE_NUM_POSITION_BOTTOM: 0x02, + PAGE_NUM_POSITION_RIGHT: 0, + PAGE_NUM_POSITION_LEFT: 1, + PAGE_NUM_POSITION_CENTER: 2 + }; + value = {}; + + if (type[0] == 'l') { + value.subtype = c_pageNumPosition.PAGE_NUM_POSITION_LEFT; + } else if (type[0] == 'c') { + value.subtype = c_pageNumPosition.PAGE_NUM_POSITION_CENTER; + } else if (type[0] == 'r') { + value.subtype = c_pageNumPosition.PAGE_NUM_POSITION_RIGHT; + } + + if (type[1] == 't') { + value.type = c_pageNumPosition.PAGE_NUM_POSITION_TOP; + } else if (type[1] == 'b') { + value.type = c_pageNumPosition.PAGE_NUM_POSITION_BOTTOM; + } + + api.put_PageNum(value.type, value.subtype); + } else { + api.put_PageNum(value); + } + + this.closeModal(); + } + + onPageBreak () { + const api = Common.EditorApi.get(); + api.put_AddPageBreak(); + this.closeModal(); + } + + onColumnBreak () { + const api = Common.EditorApi.get(); + api.put_AddColumnBreak(); + this.closeModal(); + } + + onInsertSectionBreak (type) { + const api = Common.EditorApi.get(); + let value; + if ('next' == type) { + value = Asc.c_oAscSectionBreakType.NextPage; + } else if ('continuous' == type) { + value = Asc.c_oAscSectionBreakType.Continuous; + } else if ('even' == type) { + value = Asc.c_oAscSectionBreakType.EvenPage; + } else if ('odd' == type) { + value = Asc.c_oAscSectionBreakType.OddPage; + } + api.add_SectionBreak(value); + this.closeModal(); + } + + // Footnote + + getFootnoteProps () { + if (!this.footnoteProps) { + const api = Common.EditorApi.get(); + const props = api.asc_GetFootnoteProps(); + this.footnoteProps = {propsFormat: props.get_NumFormat(), propsPos: props.get_Pos()}; + } + return this.footnoteProps; + } + + initFootnoteStartAt () { + if (!this.footnoteCurStart) { + const api = Common.EditorApi.get(); + const currValue = api.asc_GetFootnoteProps().get_NumStart(); + this.toCustomFormat = value => { + return value; + }; + this.fromCustomFormat = value => { + return value; + }; + this.footnoteCurStart = this.toCustomFormat(currValue); + } + return this.footnoteCurStart; + } + + getFootnoteStartAt (value, start) { + const currValue = this.fromCustomFormat(start); + + switch (value) { + case Asc.c_oAscNumberingFormat.UpperRoman: // I, II, III, ... + this.toCustomFormat = _10toRome; + this.fromCustomFormat = _Rometo10; + break; + case Asc.c_oAscNumberingFormat.LowerRoman: // i, ii, iii, ... + this.toCustomFormat = value => { return _10toRome(value).toLocaleLowerCase(); }; + this.fromCustomFormat = value => { return _Rometo10(value.toLocaleUpperCase()); }; + break; + case Asc.c_oAscNumberingFormat.UpperLetter: // A, B, C, ... + this.toCustomFormat = _10toS; + this.fromCustomFormat = _Sto10; + break; + case Asc.c_oAscNumberingFormat.LowerLetter: // a, b, c, ... + this.toCustomFormat = value => { return _10toS(value).toLocaleLowerCase(); }; + this.fromCustomFormat = value => { return _Sto10(value.toLocaleUpperCase()); }; + break; + default: // 1, 2, 3, ... + this.toCustomFormat = value => { return value; }; + this.fromCustomFormat = value => { return value; }; + break; + } + return this.toCustomFormat(currValue); + } + + onFootnoteStartAt (value, isDecrement) { + let intValue; + const step = 1; + const maxValue = 16383; + if(this.fromCustomFormat) { + intValue = parseInt(this.fromCustomFormat(value)); + } else { + const api = Common.EditorApi.get(); + intValue = api.asc_GetFootnoteProps().get_NumStart(); + } + if (isDecrement) { + intValue = Math.max(1, intValue - step); + } else { + intValue = Math.min(maxValue, intValue + step); + } + return this.toCustomFormat(intValue); + } + + onInsertFootnote (format, start, location) { + const api = Common.EditorApi.get(); + const props = new Asc.CAscFootnotePr(); + let startTo10; + if (this.fromCustomFormat) { + startTo10 = parseInt(this.fromCustomFormat(start)); + } else { + startTo10 = api.asc_GetFootnoteProps().get_NumStart(); + } + props.put_Pos(location); + props.put_NumFormat(format); + props.put_NumStart(startTo10); + props.put_NumRestart(Asc.c_oAscFootnoteRestart.Continuous); + api.asc_SetFootnoteProps(props, false); + api.asc_AddFootnote(); + this.closeModal(); + } + + render () { + return ( + + ) + } +} + +const AddOtherWithTranslation = withTranslation()(AddOtherController); + +export {AddOtherWithTranslation as AddOtherController}; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/controller/add/AddShape.jsx b/apps/documenteditor/mobile/src/controller/add/AddShape.jsx index bf649dc1d4..2b51e1e18c 100644 --- a/apps/documenteditor/mobile/src/controller/add/AddShape.jsx +++ b/apps/documenteditor/mobile/src/controller/add/AddShape.jsx @@ -1,17 +1,32 @@ import React, {Component} from 'react'; import { f7 } from 'framework7-react'; import {Device} from '../../../../../common/mobile/utils/device'; -import {observer, inject} from "mobx-react"; -import { AddShape } from '../../view/add/AddShape'; +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.AddShapeOnCurrentPage(type); + this.closeModal(); + } + render () { return ( - ) } diff --git a/apps/documenteditor/mobile/src/controller/add/AddTable.jsx b/apps/documenteditor/mobile/src/controller/add/AddTable.jsx index 93149252e6..4a0a4bfd54 100644 --- a/apps/documenteditor/mobile/src/controller/add/AddTable.jsx +++ b/apps/documenteditor/mobile/src/controller/add/AddTable.jsx @@ -1,20 +1,93 @@ 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 { AddTable } from '../../view/add/AddTable'; +import AddTable from '../../view/add/AddTable'; class AddTableController extends Component { constructor (props) { super(props); + this.onStyleClick = this.onStyleClick.bind(this); + + const api = Common.EditorApi.get(); + api.asc_GetDefaultTableStyles(); } + + closeModal () { + if ( Device.phone ) { + f7.sheet.close('.add-popup', true); + } else { + f7.popover.close('#add-popover'); + } + } + + onStyleClick (type) { + const api = Common.EditorApi.get(); + + this.closeModal(); + + const { t } = this.props; + const _t = t("Add", { returnObjects: true }); + + let picker; + + const dialog = f7.dialog.create({ + title: _t.textTableSize, + text: '', + content: + '
' + + '
' + + '
' + _t.textColumns + '
' + + '
' + _t.textRows + '
' + + '
' + + '
' + + '
', + buttons: [ + { + text: _t.textCancel + }, + { + text: 'OK', + bold: true, + onClick: function () { + const size = picker.value; + + api.put_Table(parseInt(size[0]), parseInt(size[1]), type.toString()); + } + } + ] + }).open(); + dialog.on('opened', () => { + picker = f7.picker.create({ + containerEl: document.getElementById('picker-table-size'), + cols: [ + { + textAlign: 'center', + width: '100%', + values: [1,2,3,4,5,6,7,8,9,10] + }, + { + textAlign: 'center', + width: '100%', + values: [1,2,3,4,5,6,7,8,9,10] + } + ], + toolbar: false, + rotateEffect: true, + value: [3, 3] + }); + }); + } + render () { return ( - ) } } -export default AddTableController; \ No newline at end of file +const AddTableWithTranslation = withTranslation()(AddTableController); + +export {AddTableWithTranslation as AddTableController}; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/controller/edit/EditChart.jsx b/apps/documenteditor/mobile/src/controller/edit/EditChart.jsx index 3068365c22..b33b1b29e6 100644 --- a/apps/documenteditor/mobile/src/controller/edit/EditChart.jsx +++ b/apps/documenteditor/mobile/src/controller/edit/EditChart.jsx @@ -9,6 +9,13 @@ class EditChartController extends Component { constructor (props) { super(props); this.onWrapType = this.onWrapType.bind(this); + this.onType = this.onType.bind(this); + this.onStyle = this.onStyle.bind(this); + this.onBorderColor = this.onBorderColor.bind(this); + this.onBorderSize = this.onBorderSize.bind(this); + + const api = Common.EditorApi.get(); + props.storeChartSettings.updateChartStyles(api.asc_getChartPreviews(props.storeFocusObjects.chartObject.get_ChartProperties().getType())); } onRemoveChart () { @@ -97,6 +104,90 @@ class EditChartController extends Component { } } + onStyle (style) { + const api = Common.EditorApi.get(); + const image = new Asc.asc_CImgProperty(); + const chart = this.props.storeFocusObjects.chartObject.get_ChartProperties(); + chart.putStyle(style); + image.put_ChartProperties(chart); + api.ImgApply(image); + } + + onType (type) { + const api = Common.EditorApi.get(); + const image = new Asc.asc_CImgProperty(); + const chart = this.props.storeFocusObjects.chartObject.get_ChartProperties(); + chart.changeType(type); + image.put_ChartProperties(chart); + api.ImgApply(image); + // Force update styles + this.props.storeChartSettings.updateChartStyles(api.asc_getChartPreviews(chart.getType())); + } + + onFillColor (color) { + const api = Common.EditorApi.get(); + const image = new Asc.asc_CImgProperty(); + const shape = new Asc.asc_CShapeProperty(); + const fill = new Asc.asc_CShapeFill(); + if (color == 'transparent') { + fill.put_type(Asc.c_oAscFill.FILL_TYPE_NOFILL); + fill.put_fill(null); + } else { + fill.put_type(Asc.c_oAscFill.FILL_TYPE_SOLID); + fill.put_fill(new Asc.asc_CFillSolid()); + fill.get_fill().put_color(Common.Utils.ThemeColor.getRgbColor(color)); + } + shape.put_fill(fill); + image.put_ShapeProperties(shape); + api.ImgApply(image); + } + + onBorderColor (color) { + const api = Common.EditorApi.get(); + const currentShape = this.props.storeFocusObjects.shapeObject.get_ShapeProperties(); + const image = new Asc.asc_CImgProperty(); + const shape = new Asc.asc_CShapeProperty(); + const stroke = new Asc.asc_CStroke(); + if (currentShape.get_stroke().get_width() < 0.01) { + stroke.put_type(Asc.c_oAscStrokeType.STROKE_NONE); + } else { + stroke.put_type(Asc.c_oAscStrokeType.STROKE_COLOR); + stroke.put_color(Common.Utils.ThemeColor.getRgbColor(color)); + stroke.put_width(currentShape.get_stroke().get_width()); + stroke.asc_putPrstDash(currentShape.get_stroke().asc_getPrstDash()); + } + shape.put_stroke(stroke); + image.put_ShapeProperties(shape); + api.ImgApply(image); + } + + onBorderSize (value) { + const api = Common.EditorApi.get(); + + const image = new Asc.asc_CImgProperty(); + const shape = new Asc.asc_CShapeProperty(); + const stroke = new Asc.asc_CStroke(); + + const _borderColor = this.props.storeChartSettings.borderColor; + + if (value < 0.01) { + stroke.put_type(Asc.c_oAscStrokeType.STROKE_NONE); + } else { + stroke.put_type(Asc.c_oAscStrokeType.STROKE_COLOR); + if (_borderColor == 'transparent') + stroke.put_color(Common.Utils.ThemeColor.getRgbColor({color: '000000', effectId: 29})); + else + stroke.put_color(Common.Utils.ThemeColor.getRgbColor(Common.Utils.ThemeColor.colorValue2EffectId(_borderColor))); + stroke.put_width(value * 25.4 / 72.0); + } + + shape.put_stroke(stroke); + image.put_ShapeProperties(shape); + + api.ImgApply(image); + this.props.storeChartSettings.initBorderColor(this.props.storeFocusObjects.shapeObject.get_ShapeProperties().get_stroke()); // when select STROKE_NONE or change from STROKE_NONE to STROKE_COLOR + } + render () { return ( ) } } -export default inject("storeChartSettings")(observer(EditChartController)); \ No newline at end of file +export default inject("storeChartSettings", "storeFocusObjects")(observer(EditChartController)); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/css/app.less b/apps/documenteditor/mobile/src/css/app.less index ee8ffa6fe1..3caaf81f1b 100644 --- a/apps/documenteditor/mobile/src/css/app.less +++ b/apps/documenteditor/mobile/src/css/app.less @@ -1,11 +1,14 @@ @themeColor: #446995; +@import '../../../../../vendor/framework7-react/node_modules/framework7/less/mixins.less'; + @import '../../../../common/mobile/resources/less/_mixins.less'; @import '../../../../common/mobile/resources/less/collaboration.less'; @import '../../../../common/mobile/resources/less/common.less'; @import '../../../../common/mobile/resources/less/common-ios.less'; @import '../../../../common/mobile/resources/less/common-material.less'; @import '../../../../common/mobile/resources/less/dataview.less'; +@import '../../../../common/mobile/resources/less/search.less'; @import './app-material.less'; @import './app-ios.less'; @import './icons-ios.less'; diff --git a/apps/documenteditor/mobile/src/css/icons-ios.less b/apps/documenteditor/mobile/src/css/icons-ios.less index 29846ab0e9..a2aca5059a 100644 --- a/apps/documenteditor/mobile/src/css/icons-ios.less +++ b/apps/documenteditor/mobile/src/css/icons-ios.less @@ -398,6 +398,37 @@ height: 24px; .encoded-svg-background(''); } + + &.icon-insert-comment { + width: 24px; + height: 24px; + .encoded-svg-background(''); + } + &.icon-pagenumber { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-sectionbreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-footnote { + width: 24px; + height: 24px; + .encoded-svg-background(''); + } + &.icon-pagebreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-stringbreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } } .tab-link-active { i.icon { diff --git a/apps/documenteditor/mobile/src/css/icons-material.less b/apps/documenteditor/mobile/src/css/icons-material.less index f73f259f2f..d309b0bf9e 100644 --- a/apps/documenteditor/mobile/src/css/icons-material.less +++ b/apps/documenteditor/mobile/src/css/icons-material.less @@ -79,7 +79,7 @@ &.icon-search { width: 22px; height: 22px; - .encoded-svg-background(''); + .encoded-svg-background(''); } &.icon-reader { width: 22px; @@ -341,5 +341,36 @@ height: 24px; .encoded-svg-background(''); } + + &.icon-insert-comment { + width: 24px; + height: 24px; + .encoded-svg-background(''); + } + &.icon-pagenumber { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-sectionbreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-footnote { + width: 24px; + height: 24px; + .encoded-svg-background(''); + } + &.icon-pagebreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } + &.icon-stringbreak { + width: 22px; + height: 22px; + .encoded-svg-background(''); + } } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/js/app.js b/apps/documenteditor/mobile/src/js/app.js index d2dfca6c8a..09146b1f30 100644 --- a/apps/documenteditor/mobile/src/js/app.js +++ b/apps/documenteditor/mobile/src/js/app.js @@ -4,6 +4,8 @@ import ReactDOM from 'react-dom'; // Import Framework7 import Framework7 from 'framework7/framework7-lite.esm.bundle.js'; +import { Dom7 } from 'framework7'; +window.$$ = Dom7; // Import Framework7-React Plugin import Framework7React from 'framework7-react'; diff --git a/apps/documenteditor/mobile/src/pages/home.jsx b/apps/documenteditor/mobile/src/pages/home.jsx index 9fd4a44d5c..0398500961 100644 --- a/apps/documenteditor/mobile/src/pages/home.jsx +++ b/apps/documenteditor/mobile/src/pages/home.jsx @@ -5,6 +5,8 @@ import EditOptions from '../view/edit/Edit'; import AddOptions from '../view/add/Add'; 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'; export default class Home extends Component { constructor(props) { @@ -58,14 +60,19 @@ export default class Home extends Component { this.handleClickToOpenOptions('edit')}> this.handleClickToOpenOptions('add')}> + { Device.phone ? null : } this.handleClickToOpenOptions('coauth')}> this.handleClickToOpenOptions('settings')}> + { Device.phone ? null : } {/* Page content */} + { + Device.phone ? null : + } { !this.state.editOptionsVisible ? null : diff --git a/apps/documenteditor/mobile/src/store/chartSettings.js b/apps/documenteditor/mobile/src/store/chartSettings.js index 51efc5af03..8efe745468 100644 --- a/apps/documenteditor/mobile/src/store/chartSettings.js +++ b/apps/documenteditor/mobile/src/store/chartSettings.js @@ -54,4 +54,135 @@ export class storeChartSettings { getWrapDistance (chartObject) { return chartObject.get_Paddings().get_Top(); } + + // style + @observable chartStyles; + @action updateChartStyles (styles) { + this.chartStyles = styles; + } + @computed get styles () { + const widthContainer = document.querySelector(".page-content").clientWidth; + const columns = parseInt(widthContainer / 70); // magic + let row = -1; + const styles = []; + this.chartStyles.forEach((style, index) => { + if (0 == index % columns) { + styles.push([]); + row++ + } + styles[row].push(style); + }); + return styles; + } + @computed get types () { + const types = [ + { type: Asc.c_oAscChartTypeSettings.barNormal, thumb: 'chart-03.png'}, + { type: Asc.c_oAscChartTypeSettings.barStacked, thumb: 'chart-02.png'}, + { type: Asc.c_oAscChartTypeSettings.barStackedPer, thumb: 'chart-01.png'}, + { type: Asc.c_oAscChartTypeSettings.lineNormal, thumb: 'chart-06.png'}, + { type: Asc.c_oAscChartTypeSettings.lineStacked, thumb: 'chart-05.png'}, + { type: Asc.c_oAscChartTypeSettings.lineStackedPer, thumb: 'chart-04.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarNormal, thumb: 'chart-09.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarStacked, thumb: 'chart-08.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarStackedPer, thumb: 'chart-07.png'}, + { type: Asc.c_oAscChartTypeSettings.areaNormal, thumb: 'chart-12.png'}, + { type: Asc.c_oAscChartTypeSettings.areaStacked, thumb: 'chart-11.png'}, + { type: Asc.c_oAscChartTypeSettings.areaStackedPer, thumb: 'chart-10.png'}, + { type: Asc.c_oAscChartTypeSettings.pie, thumb: 'chart-13.png'}, + { type: Asc.c_oAscChartTypeSettings.doughnut, thumb: 'chart-14.png'}, + { type: Asc.c_oAscChartTypeSettings.pie3d, thumb: 'chart-22.png'}, + { type: Asc.c_oAscChartTypeSettings.scatter, thumb: 'chart-15.png'}, + { type: Asc.c_oAscChartTypeSettings.stock, thumb: 'chart-16.png'}, + { type: Asc.c_oAscChartTypeSettings.line3d, thumb: 'chart-21.png'}, + { type: Asc.c_oAscChartTypeSettings.barNormal3d, thumb: 'chart-17.png'}, + { type: Asc.c_oAscChartTypeSettings.barStacked3d, thumb: 'chart-18.png'}, + { type: Asc.c_oAscChartTypeSettings.barStackedPer3d, thumb: 'chart-19.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarNormal3d, thumb: 'chart-25.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarStacked3d, thumb: 'chart-24.png'}, + { type: Asc.c_oAscChartTypeSettings.hBarStackedPer3d, thumb: 'chart-23.png'}, + { type: Asc.c_oAscChartTypeSettings.barNormal3dPerspective, thumb: 'chart-20.png'} + ]; + const columns = 3; + const arr = []; + let row = -1; + types.forEach((type, index) => { + if (0 == index % columns) { + arr.push([]); + row++ + } + arr[row].push(type); + }); + return arr; + } + + // Fill Color + @observable fillColor = undefined; + setFillColor (color) { + this.fillColor = color; + } + getFillColor (shapeProperties) { + let fill = shapeProperties.get_fill(); + const fillType = fill.get_type(); + let color = 'transparent'; + if (fillType == Asc.c_oAscFill.FILL_TYPE_SOLID) { + fill = fill.get_fill(); + const sdkColor = fill.get_color(); + if (sdkColor) { + if (sdkColor.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) { + color = {color: Common.Utils.ThemeColor.getHexColor(sdkColor.get_r(), sdkColor.get_g(), sdkColor.get_b()), effectValue: sdkColor.get_value()}; + } else { + color = Common.Utils.ThemeColor.getHexColor(sdkColor.get_r(), sdkColor.get_g(), sdkColor.get_b()); + } + } + } + this.fillColor = color; + return color; + } + + // Border size and border color + @observable borderColor; + setBorderColor (color) { + this.borderColor = color; + } + initBorderColor (stroke) { + let color = 'transparent'; + if (stroke && stroke.get_type() == Asc.c_oAscStrokeType.STROKE_COLOR) { + const sdkColor = stroke.get_color(); + if (sdkColor) { + if (sdkColor.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) { + color = {color: Common.Utils.ThemeColor.getHexColor(sdkColor.get_r(), sdkColor.get_g(), sdkColor.get_b()), effectValue: sdkColor.get_value()}; + } + else { + color = Common.Utils.ThemeColor.getHexColor(sdkColor.get_r(), sdkColor.get_g(), sdkColor.get_b()); + } + } + } + this.borderColor = color; + return color; + } + borderSizeTransform () { + const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6]; + + return { + sizeByIndex: function (index) { + if (index < 1) return _sizes[0]; + if (index > _sizes.length - 1) return _sizes[_sizes.length - 1]; + return _sizes[index]; + }, + + indexSizeByValue: function (value) { + let index = 0; + _sizes.forEach((size, idx) => { + if (Math.abs(size - value) < 0.25) { + index = idx; + } + }); + return index; + }, + + sizeByValue: function (value) { + return _sizes[this.indexSizeByValue(value)]; + } + } + } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/Search.jsx b/apps/documenteditor/mobile/src/view/Search.jsx new file mode 100644 index 0000000000..dcbcb6de21 --- /dev/null +++ b/apps/documenteditor/mobile/src/view/Search.jsx @@ -0,0 +1,116 @@ +import React, { Component } from 'react'; +import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react'; +import { f7ready, f7 } from 'framework7-react'; +import { Device } from '../../../../common/mobile/utils/device'; + +const popoverStyle = { + height: '300px' +}; + +class SearchSettingsView extends Component { + constructor(props) { + super(props); + + this.state = { + useReplace: false, + caseSensitive: false, + markResults: false + }; + } + + onFindReplaceClick(action) { + this.setState({ + useReplace: action == 'replace' + }); + } + + render() { + const show_popover = true; + const navbar = + + {!show_popover && + + Done + } + ; + const content = + + + {navbar} + + this.onFindReplaceClick('find')}> + this.onFindReplaceClick('replace')}> + + + ; + return ( + show_popover ? + {content} : + {content} + ) + } +} + +class SearchView extends Component { + constructor(props) { + super(props); + + $$(document).on('page:init', (e, page) => { + if ( page.name == 'home' ) { + this.$f7.searchbar.create({ + el: '.searchbar', + customSearch: true, + expandable: true, + backdrop: false, + on: { + search: (bar, curval, prevval) => { + console.log('on search results ' + curval); + } + } + }); + } + }); + + this.onSettingsClick = this.onSettingsClick.bind(this); + } + + componentDidMount(){ + } + + onSettingsClick(e) { + if ( Device.phone ) { + // f7.popup.open('.settings-popup'); + } else this.$f7.popover.open('#idx-search-settings', '#idx-btn-search-settings'); + } + + render() { + return ( +
+
+
+
+ + + +
+
+ + + +
+ + Cancel +
+ + ) + } +} + +export {SearchView as default, SearchSettingsView}; diff --git a/apps/documenteditor/mobile/src/view/add/Add.jsx b/apps/documenteditor/mobile/src/view/add/Add.jsx index c6ed5e6e4a..0e50889203 100644 --- a/apps/documenteditor/mobile/src/view/add/Add.jsx +++ b/apps/documenteditor/mobile/src/view/add/Add.jsx @@ -5,13 +5,41 @@ import {f7} from 'framework7-react'; import { observer, inject } from "mobx-react"; import {Device} from '../../../../../common/mobile/utils/device'; -import AddTableController from "../../controller/add/AddTable"; +import {AddTableController} from "../../controller/add/AddTable"; import AddShapeController from "../../controller/add/AddShape"; -//import AddImageController from "../../controller/add/AddImage"; -//import AddOtherController from "../../controller/add/AddOther"; +import {AddImageController} from "../../controller/add/AddImage"; +import {AddOtherController} from "../../controller/add/AddOther"; + +import {PageImageLinkSettings} from "../add/AddImage"; +import {PageAddLink, PageAddNumber, PageAddBreak, PageAddSectionBreak, PageAddFootnote} from "../add/AddOther"; const routes = [ - + // Image + { + path: '/add-image-from-url/', + component: PageImageLinkSettings, + }, + // Other + { + path: '/add-link/', + component: PageAddLink, + }, + { + path: '/add-page-number/', + component: PageAddNumber, + }, + { + path: '/add-break/', + component: PageAddBreak, + }, + { + path: '/add-section-break/', + component: PageAddSectionBreak, + }, + { + path: '/add-footnote/', + component: PageAddFootnote, + }, ]; const AddLayoutNavbar = ({ tabs, inPopover }) => { @@ -58,7 +86,7 @@ const AddTabs = props => { icon: 'icon-add-shape', component: }); - /*tabs.push({ + tabs.push({ caption: _t.textImage, id: 'add-image', icon: 'icon-add-image', @@ -69,7 +97,7 @@ const AddTabs = props => { id: 'add-other', icon: 'icon-add-other', component: - });*/ + }); return ( diff --git a/apps/documenteditor/mobile/src/view/add/AddImage.jsx b/apps/documenteditor/mobile/src/view/add/AddImage.jsx new file mode 100644 index 0000000000..066f03c8ac --- /dev/null +++ b/apps/documenteditor/mobile/src/view/add/AddImage.jsx @@ -0,0 +1,49 @@ +import React, {useState} from 'react'; +import {observer, inject} from "mobx-react"; +import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle} from 'framework7-react'; +import { useTranslation } from 'react-i18next'; + +const PageLinkSettings = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + const [stateValue, setValue] = useState(''); + return ( + + + {_t.textAddress} + + {setValue(event.target.value)}} + > + + + + {props.onInsertByUrl(stateValue)}}> + + + ) +}; + +const AddImage = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + return ( + + {props.onInsertByFile()}}> + + + + + + + ) +}; + +export {AddImage, PageLinkSettings as PageImageLinkSettings}; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/add/AddOther.jsx b/apps/documenteditor/mobile/src/view/add/AddOther.jsx new file mode 100644 index 0000000000..06ad6f3b58 --- /dev/null +++ b/apps/documenteditor/mobile/src/view/add/AddOther.jsx @@ -0,0 +1,242 @@ +import React, {useState} from 'react'; +import {observer, inject} from "mobx-react"; +import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle, Segmented, Button} from 'framework7-react'; +import { useTranslation } from 'react-i18next'; +import {Device} from "../../../../../common/mobile/utils/device"; + +const PageLink = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + + let display = props.getDisplayLinkText(); + display = typeof display === 'string' ? display : ''; + + const [stateLink, setLink] = useState(''); + const [stateDisplay, setDisplay] = useState(display); + const [stateTip, setTip] = useState(''); + return ( + + + + {setLink(event.target.value)}} + > + {setDisplay(event.target.value)}} + > + {setTip(event.target.value)}} + > + + + { + props.onInsertLink(stateLink, stateDisplay, stateTip) + }}> + + + ) +}; + +const PageNumber = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + return ( + + + + {props.onInsertPageNumber('lt')}}> + {props.onInsertPageNumber('ct')}}> + {props.onInsertPageNumber('rt')}}> + {props.onInsertPageNumber('lb')}}> + {props.onInsertPageNumber('cb')}}> + {props.onInsertPageNumber('rb')}}> + {props.onInsertPageNumber('current')}}> + + + ) +}; + +const PageBreak = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + return ( + + + + { + props.onPageBreak() + }}> + + + { + props.onColumnBreak(); + }}> + + + + + + + + ) +}; + +const PageSectionBreak = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + return ( + + + + { + props.onInsertSectionBreak('next') + }}> + { + props.onInsertSectionBreak('continuous') + }}> + { + props.onInsertSectionBreak('even') + }}> + { + props.onInsertSectionBreak('odd') + }}> + + + ) +}; + +const PageFootnote = props => { + const isAndroid = Device.android; + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + + const dataFormatFootnote = [ + { text: '1, 2, 3,...', value: Asc.c_oAscNumberingFormat.Decimal }, + { text: 'a, b, c,...', value: Asc.c_oAscNumberingFormat.LowerLetter }, + { text: 'A, B, C,...', value: Asc.c_oAscNumberingFormat.UpperLetter }, + { text: 'i, ii, iii,...', value: Asc.c_oAscNumberingFormat.LowerRoman }, + { text: 'I, II, III,...', value: Asc.c_oAscNumberingFormat.UpperRoman } + ]; + const dataPosFootnote = [ + {value: Asc.c_oAscFootnotePos.PageBottom, displayValue: _t.textBottomOfPage }, + {value: Asc.c_oAscFootnotePos.BeneathText, displayValue: _t.textBelowText } + ]; + + const [stateStartAt, setStartAt] = useState(props.initFootnoteStartAt()); + const [stateLocation, setLocation] = useState(props.getFootnoteProps().propsPos); + const [stateFormat, setFormat] = useState(props.getFootnoteProps().propsFormat); + + return ( + + + {_t.textFormat} + + {dataFormatFootnote.map((format, index)=>{ + return ( + { + setStartAt(props.getFootnoteStartAt(format.value, stateStartAt)); + setFormat(format.value) + }}> + ) + })} + + + + {!isAndroid &&
{stateStartAt}
} +
+ + + {isAndroid && } + + +
+
+
+ {_t.textLocation} + + {dataPosFootnote.map((location, index)=>{ + return ( + {setLocation(location.value)}}> + ) + })} + + + { + props.onInsertFootnote(stateFormat, stateStartAt, stateLocation); + }}> + +
+ ) +}; + +const AddOther = props => { + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + return ( + + + + + + + + + + + + + + + + + + ) +}; + +export {AddOther, + PageLink as PageAddLink, + PageNumber as PageAddNumber, + PageBreak as PageAddBreak, + PageSectionBreak as PageAddSectionBreak, + PageFootnote as PageAddFootnote}; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/add/AddShape.jsx b/apps/documenteditor/mobile/src/view/add/AddShape.jsx index bf408d896b..155ee02dcb 100644 --- a/apps/documenteditor/mobile/src/view/add/AddShape.jsx +++ b/apps/documenteditor/mobile/src/view/add/AddShape.jsx @@ -1,15 +1,28 @@ -import React, {Fragment, useState} from 'react'; +import React from 'react'; import {observer, inject} from "mobx-react"; -import {Page, Navbar, List, ListItem, ListButton, Row, BlockTitle, Range, Toggle, Icon} from 'framework7-react'; -import { useTranslation } from 'react-i18next'; -import {Device} from '../../../../../common/mobile/utils/device'; const AddShape = props => { + const storeShapeSettings = props.storeShapeSettings; + let shapes = storeShapeSettings.getStyleGroups(); return ( - - - +
+ {shapes.map((row, indexRow) => { + return ( +
    + {row.map((shape, index) => { + return ( +
  • {props.onShapeClick(shape.type)}}> +
    +
    +
  • + ) + })} +
+ ) + })} +
) }; -export {AddShape}; \ No newline at end of file +export default inject("storeShapeSettings")(observer(AddShape)); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/add/AddTable.jsx b/apps/documenteditor/mobile/src/view/add/AddTable.jsx index 0a71acac58..3e4635f435 100644 --- a/apps/documenteditor/mobile/src/view/add/AddTable.jsx +++ b/apps/documenteditor/mobile/src/view/add/AddTable.jsx @@ -5,11 +5,22 @@ import { useTranslation } from 'react-i18next'; import {Device} from '../../../../../common/mobile/utils/device'; const AddTable = props => { + const storeTableSettings = props.storeTableSettings; + const styles = storeTableSettings.styles; return ( - - - +
+
    + {styles.map((style, index) => { + return ( +
  • {props.onStyleClick(style.templateId)}}> + +
  • + ) + })} +
+
) }; -export {AddTable}; \ No newline at end of file +export default inject("storeTableSettings")(observer(AddTable)); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/edit/Edit.jsx b/apps/documenteditor/mobile/src/view/edit/Edit.jsx index 93e20b4831..bd9bb4c7a1 100644 --- a/apps/documenteditor/mobile/src/view/edit/Edit.jsx +++ b/apps/documenteditor/mobile/src/view/edit/Edit.jsx @@ -19,7 +19,7 @@ import {ParagraphAdvSettings, PageParagraphBackColor, PageParagraphCustomColor} import {PageShapeStyleNoFill, PageShapeStyle, PageShapeCustomFillColor, PageShapeBorderColor, PageShapeCustomBorderColor, PageWrap, PageReorder, PageReplace} from "./EditShape"; import {PageImageReorder, PageImageReplace, PageImageWrap, PageLinkSettings} from "./EditImage"; import {PageTableOptions, PageTableWrap, PageTableStyle, PageTableStyleOptions, PageTableCustomFillColor, PageTableBorderColor, PageTableCustomBorderColor} from "./EditTable"; -import {PageChartWrap, PageChartReorder} from "./EditChart"; +import {PageChartStyle, PageChartCustomFillColor, PageChartBorderColor, PageChartCustomBorderColor, PageChartWrap, PageChartReorder} from "./EditChart"; const routes = [ //Edit text @@ -159,6 +159,22 @@ const routes = [ { path: '/edit-chart-reorder/', component: PageChartReorder, + }, + { + path: '/edit-chart-style/', + component: PageChartStyle, + }, + { + path: '/edit-chart-custom-fill-color/', + component: PageChartCustomFillColor, + }, + { + path: '/edit-chart-border-color/', + component: PageChartBorderColor, + }, + { + path: '/edit-chart-custom-border-color/', + component: PageChartCustomBorderColor, } ]; diff --git a/apps/documenteditor/mobile/src/view/edit/EditChart.jsx b/apps/documenteditor/mobile/src/view/edit/EditChart.jsx index 87eeeb8ae9..7c62b7bdce 100644 --- a/apps/documenteditor/mobile/src/view/edit/EditChart.jsx +++ b/apps/documenteditor/mobile/src/view/edit/EditChart.jsx @@ -1,13 +1,224 @@ import React, {Fragment, useState} from 'react'; import {observer, inject} from "mobx-react"; -import {List, ListItem, ListButton, Icon, Row, Col, Button, Page, Navbar, Segmented, BlockTitle, Toggle, Range} from 'framework7-react'; +import {List, ListItem, ListButton, Icon, Row, Page, Navbar, BlockTitle, Toggle, Range, Link, Tabs, Tab} from 'framework7-react'; import { useTranslation } from 'react-i18next'; import {Device} from '../../../../../common/mobile/utils/device'; +import {CustomColorPicker, ThemeColorPalette} from "../../../../../common/mobile/lib/component/ThemeColorPalette.jsx"; + +const PageCustomFillColor = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + let fillColor = props.storeChartSettings.fillColor; + if (typeof fillColor === 'object') { + fillColor = fillColor.color; + } + const onAddNewColor = (colors, color) => { + props.storePalette.changeCustomColors(colors); + props.onFillColor(color); + props.storeChartSettings.setFillColor(color); + props.f7router.back(); + }; + return( + + + + + ) +}; + +const PaletteFill = inject("storeFocusObjects", "storeChartSettings", "storePalette")(observer(props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + const storeChartSettings = props.storeChartSettings; + const shapeProperties = props.storeFocusObjects.shapeObject.get_ShapeProperties(); + const curFillColor = storeChartSettings.fillColor ? storeChartSettings.fillColor : storeChartSettings.getFillColor(shapeProperties); + const customColors = props.storePalette.customColors; + const changeColor = (color, effectId, effectValue) => { + if (color !== 'empty') { + if (effectId !==undefined ) { + const newColor = {color: color, effectId: effectId, effectValue: effectValue}; + props.onFillColor(newColor); + storeChartSettings.setFillColor(newColor); + } else { + props.onFillColor(color); + storeChartSettings.setFillColor(color); + } + } else { + // open custom color menu + props.f7router.navigate('/edit-chart-custom-fill-color/'); + } + }; + return( + + + + + + + ) +})); + +const PageCustomBorderColor = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + let borderColor = props.storeChartSettings.borderColor; + if (typeof borderColor === 'object') { + borderColor = borderColor.color; + } + const onAddNewColor = (colors, color) => { + props.storePalette.changeCustomColors(colors); + props.onBorderColor(color); + props.storeChartSettings.setBorderColor(color); + props.f7router.back(); + }; + return( + + + + + ) +}; + +const PageBorderColor = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + const borderColor = props.storeChartSettings.borderColor; + const customColors = props.storePalette.customColors; + const changeColor = (color, effectId, effectValue) => { + if (color !== 'empty') { + if (effectId !==undefined ) { + const newColor = {color: color, effectId: effectId, effectValue: effectValue}; + props.onBorderColor(newColor); + props.storeChartSettings.setBorderColor(newColor); + } else { + props.onBorderColor(color); + props.storeChartSettings.setBorderColor(color); + } + } else { + // open custom color menu + props.f7router.navigate('/edit-chart-custom-border-color/'); + } + }; + return( + + + + + + + + ) +}; const PageStyle = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + const storeChartSettings = props.storeChartSettings; + const chartProperties = props.storeFocusObjects.chartObject.get_ChartProperties(); + + const types = storeChartSettings.types; + const curType = chartProperties.getType(); + + const styles = storeChartSettings.styles; + + const shapeObject = props.storeFocusObjects.shapeObject; + const shapeStroke = shapeObject.get_ShapeProperties().get_stroke(); + + // Init border size + const borderSizeTransform = storeChartSettings.borderSizeTransform(); + const borderSize = shapeStroke.get_width() * 72.0 / 25.4; + const borderType = shapeStroke.get_type(); + const displayBorderSize = (borderType == Asc.c_oAscStrokeType.STROKE_NONE) ? 0 : borderSizeTransform.indexSizeByValue(borderSize); + const displayTextBorderSize = (borderType == Asc.c_oAscStrokeType.STROKE_NONE) ? 0 : borderSizeTransform.sizeByValue(borderSize); + const [stateBorderSize, setBorderSize] = useState(displayBorderSize); + const [stateTextBorderSize, setTextBorderSize] = useState(displayTextBorderSize); + + // Init border color + const borderColor = !storeChartSettings.borderColor ? storeChartSettings.initBorderColor(shapeStroke) : storeChartSettings.borderColor; + const displayBorderColor = borderColor !== 'transparent' ? `#${(typeof borderColor === "object" ? borderColor.color : borderColor)}` : borderColor; + return ( - + +
+ {_t.textType} + {_t.textStyle} + {_t.textFill} + {_t.textBorder} +
+
+ + +
+ {types.map((row, rowIndex) => { + return ( +
    + {row.map((type, index)=>{ + return( +
  • {props.onType(type.type)}}> +
    +
    +
  • + ) + })} +
+ ) + })} +
+
+ +
+ {styles.map((row, rowIndex) => { + return ( +
    + {row.map((style, index)=>{ + return( +
  • {props.onStyle(style.asc_getName())}}> + +
  • + ) + })} +
+ ) + })} +
+
+ + + + + + +
{_t.textSize}
+
+ {setBorderSize(value); setTextBorderSize(borderSizeTransform.sizeByIndex(value));}} + onRangeChanged={(value) => {props.onBorderSize(borderSizeTransform.sizeByIndex(value))}} + > +
+
+ {stateTextBorderSize + ' ' + Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.pt)} +
+
+ + + +
+
+
) }; @@ -56,20 +267,26 @@ const PageWrap = props => { {_t.textAlign} - + { props.onAlign(Asc.c_oAscAlignH.Left) - }}>left + }}> + + { props.onAlign(Asc.c_oAscAlignH.Center) - }}>center + }}> + + { props.onAlign(Asc.c_oAscAlignH.Right) - }}>right + }}> + + @@ -136,7 +353,13 @@ const EditChart = props => { return ( - + { ) }; -const PageChartStyle = inject("storeFocusObjects")(observer(PageStyle)); +const PageChartStyle = inject("storeChartSettings", "storeFocusObjects")(observer(PageStyle)); const PageChartWrap = inject("storeChartSettings", "storeFocusObjects")(observer(PageWrap)); +const PageChartCustomFillColor = inject("storeChartSettings", "storePalette")(observer(PageCustomFillColor)); +const PageChartBorderColor = inject("storeChartSettings", "storePalette")(observer(PageBorderColor)); +const PageChartCustomBorderColor = inject("storeChartSettings", "storePalette")(observer(PageCustomBorderColor)); -export {EditChart, PageChartStyle, PageChartWrap, PageReorder as PageChartReorder} \ No newline at end of file +export {EditChart, + PageChartStyle, + PageChartCustomFillColor, + PageChartBorderColor, + PageChartCustomBorderColor, + PageChartWrap, + PageReorder as PageChartReorder} \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/edit/EditShape.jsx b/apps/documenteditor/mobile/src/view/edit/EditShape.jsx index 9a1d1b3a3f..56da592805 100644 --- a/apps/documenteditor/mobile/src/view/edit/EditShape.jsx +++ b/apps/documenteditor/mobile/src/view/edit/EditShape.jsx @@ -353,7 +353,7 @@ const PageReplace = props => { let shapes = storeShapeSettings.getStyleGroups(); shapes.splice(0, 1); // Remove line shapes return ( - + {shapes.map((row, indexRow) => { return ( diff --git a/apps/documenteditor/mobile/src/view/edit/EditText.jsx b/apps/documenteditor/mobile/src/view/edit/EditText.jsx index 3ad6f5aaad..93b114610f 100644 --- a/apps/documenteditor/mobile/src/view/edit/EditText.jsx +++ b/apps/documenteditor/mobile/src/view/edit/EditText.jsx @@ -132,12 +132,18 @@ const PageBullets = props => { const storeTextSettings = props.storeTextSettings; const typeBullets = storeTextSettings.typeBullets; return( - + {bulletArrays.map((bullets, index) => (
    {bullets.map((bullet) => ( -
  • {props.onBullet(bullet.type)}}> +
  • { + if (bullet.type === -1) { + storeTextSettings.resetBullets(-1); + } + props.onBullet(bullet.type) + }}> {bullet.thumb.length < 1 ?
    @@ -171,12 +177,18 @@ const PageNumbers = props => { const storeTextSettings = props.storeTextSettings; const typeNumbers = storeTextSettings.typeNumbers; return( - + {numberArrays.map((numbers, index) => (
      {numbers.map((number) => ( -
    • {props.onNumber(number.type)}}> +
    • { + if (number.type === -1) { + storeTextSettings.resetNumbers(-1); + } + props.onNumber(number.type) + }}> {number.thumb.length < 1 ?
      diff --git a/apps/documenteditor/mobile/src/view/search.jsx b/apps/documenteditor/mobile/src/view/search.jsx new file mode 100644 index 0000000000..dcbcb6de21 --- /dev/null +++ b/apps/documenteditor/mobile/src/view/search.jsx @@ -0,0 +1,116 @@ +import React, { Component } from 'react'; +import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react'; +import { f7ready, f7 } from 'framework7-react'; +import { Device } from '../../../../common/mobile/utils/device'; + +const popoverStyle = { + height: '300px' +}; + +class SearchSettingsView extends Component { + constructor(props) { + super(props); + + this.state = { + useReplace: false, + caseSensitive: false, + markResults: false + }; + } + + onFindReplaceClick(action) { + this.setState({ + useReplace: action == 'replace' + }); + } + + render() { + const show_popover = true; + const navbar = + + {!show_popover && + + Done + } + ; + const content = + + + {navbar} + + this.onFindReplaceClick('find')}> + this.onFindReplaceClick('replace')}> + + + ; + return ( + show_popover ? + {content} : + {content} + ) + } +} + +class SearchView extends Component { + constructor(props) { + super(props); + + $$(document).on('page:init', (e, page) => { + if ( page.name == 'home' ) { + this.$f7.searchbar.create({ + el: '.searchbar', + customSearch: true, + expandable: true, + backdrop: false, + on: { + search: (bar, curval, prevval) => { + console.log('on search results ' + curval); + } + } + }); + } + }); + + this.onSettingsClick = this.onSettingsClick.bind(this); + } + + componentDidMount(){ + } + + onSettingsClick(e) { + if ( Device.phone ) { + // f7.popup.open('.settings-popup'); + } else this.$f7.popover.open('#idx-search-settings', '#idx-btn-search-settings'); + } + + render() { + return ( +
      +
      +
      +
      + + + +
      +
      + + + +
      + + Cancel +
      + + ) + } +} + +export {SearchView as default, SearchSettingsView};