From 10927e6f63c7d3af58c45b293544f117b1554223 Mon Sep 17 00:00:00 2001 From: ShimaginAndrey Date: Sun, 23 May 2021 18:27:21 +0300 Subject: [PATCH 1/2] Filter Options --- .../mobile/lib/controller/ContextMenu.jsx | 2 +- apps/spreadsheeteditor/mobile/locale/en.json | 8 +- .../mobile/src/controller/FilterOptions.jsx | 134 ++++++++++++++++++ .../mobile/src/less/app-material.less | 30 ++++ .../mobile/src/less/icons-ios.less | 10 ++ .../mobile/src/page/main.jsx | 6 + .../mobile/src/view/FilterOptions.jsx | 93 ++++++++++++ 7 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 apps/spreadsheeteditor/mobile/src/controller/FilterOptions.jsx create mode 100644 apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx diff --git a/apps/common/mobile/lib/controller/ContextMenu.jsx b/apps/common/mobile/lib/controller/ContextMenu.jsx index 9b05db8a8..ef6f5f897 100644 --- a/apps/common/mobile/lib/controller/ContextMenu.jsx +++ b/apps/common/mobile/lib/controller/ContextMenu.jsx @@ -103,7 +103,7 @@ class ContextMenuController extends Component { } onApiOpenContextMenu(x, y) { - if ( !this.state.opened && $$('.dialog.modal-in').length < 1) { + if ( !this.state.opened && $$('.dialog.modal-in').length < 1 && !$$('.popover.modal-in, .sheet-modal.modal-in').length) { this.setState({ items: this.initMenuItems(), extraItems: this.initExtraItems() diff --git a/apps/spreadsheeteditor/mobile/locale/en.json b/apps/spreadsheeteditor/mobile/locale/en.json index 55d00ec13..036965d76 100644 --- a/apps/spreadsheeteditor/mobile/locale/en.json +++ b/apps/spreadsheeteditor/mobile/locale/en.json @@ -406,7 +406,13 @@ "textExternalLink": "External Link", "textDefault": "Selected range", "textInvalidRange": "Invalid cells range", - "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\"", + "textFilterOptions": "Filter Options", + "textClearFilter": "Clear Filter", + "textDeleteFilter": "Delete Filter", + "textEmptyItem": "{Blanks}", + "textErrorTitle": "Warning", + "textErrorMsg": "You must choose at least one value" }, "Settings": { "textFindAndReplace": "Find and Replace", diff --git a/apps/spreadsheeteditor/mobile/src/controller/FilterOptions.jsx b/apps/spreadsheeteditor/mobile/src/controller/FilterOptions.jsx new file mode 100644 index 000000000..e13be4046 --- /dev/null +++ b/apps/spreadsheeteditor/mobile/src/controller/FilterOptions.jsx @@ -0,0 +1,134 @@ +import React, { useEffect,useState } from 'react'; +import FilterView from '../../src/view/FilterOptions'; +import { f7,Sheet,Popover } from 'framework7-react'; +import { Device } from '../../../../common/mobile/utils/device'; +import { useTranslation } from 'react-i18next'; + +const FilterOptionsController = () => { + const { t } = useTranslation(); + const _t = t('View.Edit', {returnObjects: true}); + + const [configFilter, setConfig] = useState(null); + const [listVal, setListValue] = useState([]); + const [isValid, setIsValid] = useState(null) + + useEffect(() => { + function onDocumentReady() { + const api = Common.EditorApi.get(); + api.asc_registerCallback('asc_onSetAFDialog',onApiFilterOptions); + } + + if ( !Common.EditorApi ) { + Common.Notifications.on('document:ready',onDocumentReady); + } else { + onDocumentReady(); + } + + return () => { + Common.Notifications.off('document:ready', onDocumentReady); + const api = Common.EditorApi.get(); + api.asc_unregisterCallback('asc_onSetAFDialog',onApiFilterOptions); + } + }, []); + + const onApiFilterOptions= (config) => { + setDataFilterCells(config); + setConfig(config); + setClearDisable(config); + + if (Device.phone) { + f7.sheet.open('.picker__sheet'); + } else { + let rect = config.asc_getCellCoord(), + posX = rect.asc_getX() + rect.asc_getWidth() - 9, + posY = rect.asc_getY() + rect.asc_getHeight() - 9; + + let $target = $$('#idx-context-menu-target') + .css({left: `${posX}px`, top: `${posY}px`}); + f7.popover.open('#picker-popover',$target); + } + } + + const onSort = (type) => { + const api = Common.EditorApi.get(); + api.asc_sortColFilter(type == 'sortdown' ? Asc.c_oAscSortOptions.Ascending : Asc.c_oAscSortOptions.Descending, configFilter.asc_getCellId(), configFilter.asc_getDisplayName(), undefined, true); + }; + + const onClearFilter = () => { + const api = Common.EditorApi.get(); + if(api) api.asc_clearFilter(); + }; + + const onDeleteFilter = () => { + const api = Common.EditorApi.get(); + let formatTableInfo = api.asc_getCellInfo().asc_getFormatTableInfo(); + let tablename = (formatTableInfo) ? formatTableInfo.asc_getTableName() : undefined; + if(api) { + api.asc_changeAutoFilter(tablename, Asc.c_oAscChangeFilterOptions.filter, false); + f7.sheet.close('.picker__sheet'); + f7.popover.close('#picker-popover'); + } + }; + + const setClearDisable = (config) => { + let arr = config.asc_getValues(); + let lenCheck = arr.filter((item) => item.visible == true).length; + lenCheck == arr.length ? setIsValid(true) : setIsValid(false) + }; + + const setDataFilterCells = (config) => { + function isNumeric(value) { + return !isNaN(parseFloat(value)) && isFinite(value); + } + + let value = null, + isnumber = null, + arrCells = []; + + config.asc_getValues().forEach((item, index) => { + value = item.asc_getText(); + isnumber = isNumeric(value); + + arrCells.push({ + id : index, + selected : false, + cellvalue : value ? value : _t.textEmptyItem, + value : isnumber ? value : (value.length > 0 ? value: _t.textEmptyItem), + groupid : '1', + check : item.asc_getVisible() + }); + }); + + setListValue(arrCells); + }; + + const onUpdateCell = (id, state) => { + const api = Common.EditorApi.get(); + + if ( id == 'all' ) { + listVal.forEach(item => item.check = state); + } else { + listVal[id].check = state; + } + + setListValue([...listVal]); + + if ( listVal.some(item => item.check) ) { + configFilter.asc_getValues().forEach( + (item, index) => item.asc_setVisible(listVal[index].check) + ); + + configFilter.asc_getFilterObj().asc_setType(Asc.c_oAscAutoFilterTypes.Filters); + api.asc_applyAutoFilter(configFilter); + } + + setClearDisable(configFilter); + }; + + return ( + + ) +}; + +export default FilterOptionsController; \ No newline at end of file diff --git a/apps/spreadsheeteditor/mobile/src/less/app-material.less b/apps/spreadsheeteditor/mobile/src/less/app-material.less index 879f3a67c..b23fb8edf 100644 --- a/apps/spreadsheeteditor/mobile/src/less/app-material.less +++ b/apps/spreadsheeteditor/mobile/src/less/app-material.less @@ -21,4 +21,34 @@ align-items: center; width: auto; } +} + +.icon.icon-checkbox { + width: 20px; + height: 20px; + border-radius: 20px; + border: 2px solid #6d6d6d; +} +label.item-checkbox input[type='checkbox']:checked ~ +.icon-checkbox, label.item-checkbox input[type='checkbox']:checked ~ +* .icon-checkbox, .checkbox input[type='checkbox']:checked ~ +i, label.item-checkbox input[type='checkbox']:indeterminate ~ +.icon-checkbox, label.item-checkbox input[type='checkbox']:indeterminate ~ * .icon-checkbox, .checkbox input[type='checkbox']:indeterminate ~ i{ + border-color: #40865c; + background-color: transparent; +} +label.item-content i.icon.icon-checkbox:after { + content: ' '; + position: absolute; + width: 10px; + height: 10px; + left: 50%; + top: 50%; + margin-left: -5px; + margin-top: -5px; + background-color: #40865c; + border-radius: 100%; +} +.device-android .button-raised{ + box-shadow: none; } \ No newline at end of file diff --git a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less index 26229adbb..1dd26a597 100644 --- a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less +++ b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less @@ -474,4 +474,14 @@ } } } + label.item-content input[type=checkbox]:checked~.item-inner, + label.item-content input[type=radio]:checked~.item-inner { + background: no-repeat center; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2013%2010'%3E%3Cpolygon%20fill%3D'%2340865c'%20points%3D'11.6%2C0%204.4%2C7.2%201.4%2C4.2%200%2C5.6%204.4%2C10%204.4%2C10%204.4%2C10%2013%2C1.4%20'%2F%3E%3C%2Fsvg%3E"); + background-position: 90% center; + background-size: 13px 10px; + } + .icon.icon-checkbox{ + display:none; + } } diff --git a/apps/spreadsheeteditor/mobile/src/page/main.jsx b/apps/spreadsheeteditor/mobile/src/page/main.jsx index 7c2a80c34..28d7a265b 100644 --- a/apps/spreadsheeteditor/mobile/src/page/main.jsx +++ b/apps/spreadsheeteditor/mobile/src/page/main.jsx @@ -9,6 +9,7 @@ import CellEditor from '../controller/CellEditor'; import Statusbar from '../controller/Statusbar'; import AddOptions from "../view/add/Add"; import EditOptions from "../view/edit/Edit"; +import FilterOptionsController from "../controller/FilterOptions"; import { Search, SearchSettings } from '../controller/Search'; import { f7 } from 'framework7-react'; @@ -110,6 +111,11 @@ class MainPage extends Component { !this.state.collaborationVisible ? null : } + + { + + } + {/* hidden component*/} diff --git a/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx b/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx new file mode 100644 index 000000000..200cc01bd --- /dev/null +++ b/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx @@ -0,0 +1,93 @@ +import React, {useEffect, useState} from 'react'; +import {f7, List, Popover, Sheet, ListItem, Icon, Row, Button, ListButton, Page, Navbar, Segmented, BlockTitle, NavRight, Link, Toggle,View} from 'framework7-react'; +import { useTranslation } from 'react-i18next'; +import { Device } from '../../../../common/mobile/utils/device'; + +const FilterOptions = (props) => { + const { t } = useTranslation(); + const _t = t('View.Edit', {returnObjects: true}); + + useEffect(() => { + const $clearFilter = $$("#button-clear-filter"); + props.isValid ? $clearFilter.addClass('disabled') : $clearFilter.removeClass('disabled'); + const is_all_checked = props.listVal.every(item => item.check); + setAll(is_all_checked); + }); + + const [all, setAll] = useState(false); + + const HandleClearFilter = () => { + props.onClearFilter(); + setAll(true); + props.onUpdateCell('all', true); + }; + + return ( + + + + {Device.phone && + + + + + + } + + + + + props.onSort('sortdown')}> + + + props.onSort('sortup')}> + + + + + + + {_t.textClearFilter} + props.onDeleteFilter()} id="btn-delete-filter">{_t.textDeleteFilter} + + + props.onUpdateCell('all', e.target.checked)} name='filter-cellAll' checkbox checked={all}>Select All + {props.listVal.map((value) => + props.onUpdateCell(value.id, e.target.checked)} key={value.value} name='filter-cell' value={value.value} title={value.cellvalue} checkbox checked={value.check} /> + )} + + + + ) +}; + +const FilterView = (props) => { + const { t } = useTranslation(); + const _t = t('View.Edit', {returnObjects: true}); + + const onClosed = () => { + if ( props.listVal.every(item => !item.check) ) { + f7.dialog.create({ + title: _t.textErrorTitle, + text: _t.textErrorMsg, + buttons: [ + { + text: 'OK', + } + ] + }).open(); + } + }; + + return ( + !Device.phone ? + + + : + + + + ) +} + +export default FilterView; \ No newline at end of file From e3be43c3ee2a935ee892cafbbd176ad9ea62267a Mon Sep 17 00:00:00 2001 From: JuliaSvinareva Date: Mon, 24 May 2021 13:32:35 +0300 Subject: [PATCH 2/2] [SSE mobile] Refactoring filter options --- apps/spreadsheeteditor/mobile/locale/en.json | 1 + .../mobile/src/less/app-ios.less | 12 ++++ .../mobile/src/less/app-material.less | 56 +++++++++---------- .../mobile/src/less/icons-ios.less | 10 ---- .../mobile/src/page/main.jsx | 4 +- .../mobile/src/view/FilterOptions.jsx | 8 +-- 6 files changed, 44 insertions(+), 47 deletions(-) diff --git a/apps/spreadsheeteditor/mobile/locale/en.json b/apps/spreadsheeteditor/mobile/locale/en.json index 036965d76..4c3b8581c 100644 --- a/apps/spreadsheeteditor/mobile/locale/en.json +++ b/apps/spreadsheeteditor/mobile/locale/en.json @@ -410,6 +410,7 @@ "textFilterOptions": "Filter Options", "textClearFilter": "Clear Filter", "textDeleteFilter": "Delete Filter", + "textSelectAll": "Select All", "textEmptyItem": "{Blanks}", "textErrorTitle": "Warning", "textErrorMsg": "You must choose at least one value" diff --git a/apps/spreadsheeteditor/mobile/src/less/app-ios.less b/apps/spreadsheeteditor/mobile/src/less/app-ios.less index e058a2241..7dd7f4917 100644 --- a/apps/spreadsheeteditor/mobile/src/less/app-ios.less +++ b/apps/spreadsheeteditor/mobile/src/less/app-ios.less @@ -20,4 +20,16 @@ appearance: none; } + // For filter options + .radio-checkbox-item { + label.item-content input[type=checkbox]:checked ~ .item-inner { + background: no-repeat center; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2013%2010'%3E%3Cpolygon%20fill%3D'%2340865c'%20points%3D'11.6%2C0%204.4%2C7.2%201.4%2C4.2%200%2C5.6%204.4%2C10%204.4%2C10%204.4%2C10%2013%2C1.4%20'%2F%3E%3C%2Fsvg%3E"); + background-position: calc(100% - 15px) center; + background-size: 13px 10px; + } + .icon.icon-checkbox { + display: none; + } + } } diff --git a/apps/spreadsheeteditor/mobile/src/less/app-material.less b/apps/spreadsheeteditor/mobile/src/less/app-material.less index b23fb8edf..cbb0da4ce 100644 --- a/apps/spreadsheeteditor/mobile/src/less/app-material.less +++ b/apps/spreadsheeteditor/mobile/src/less/app-material.less @@ -2,12 +2,14 @@ // Colors @themeColorLight: #a2bdde; @navBarIconColor: #fff; +@listButtonBorderColor: rgba(0,0,0,0.15); .device-android { --f7-navbar-bg-color: @themeColor; --f7-navbar-link-color: @navBarIconColor; --f7-navbar-text-color: @navBarIconColor; + --f7-list-button-border-color: @listButtonBorderColor; // Main Toolbar #editor-navbar.navbar .right { @@ -21,34 +23,30 @@ align-items: center; width: auto; } -} -.icon.icon-checkbox { - width: 20px; - height: 20px; - border-radius: 20px; - border: 2px solid #6d6d6d; -} -label.item-checkbox input[type='checkbox']:checked ~ -.icon-checkbox, label.item-checkbox input[type='checkbox']:checked ~ -* .icon-checkbox, .checkbox input[type='checkbox']:checked ~ -i, label.item-checkbox input[type='checkbox']:indeterminate ~ -.icon-checkbox, label.item-checkbox input[type='checkbox']:indeterminate ~ * .icon-checkbox, .checkbox input[type='checkbox']:indeterminate ~ i{ - border-color: #40865c; - background-color: transparent; -} -label.item-content i.icon.icon-checkbox:after { - content: ' '; - position: absolute; - width: 10px; - height: 10px; - left: 50%; - top: 50%; - margin-left: -5px; - margin-top: -5px; - background-color: #40865c; - border-radius: 100%; -} -.device-android .button-raised{ - box-shadow: none; + // For filter options + .radio-checkbox-item { + .icon.icon-checkbox { + width: 20px; + height: 20px; + border-radius: 20px; + border: 2px solid var(--f7-checkbox-inactive-color); + } + label.item-checkbox input[type='checkbox']:checked ~ .icon-checkbox { + border-color: @themeColor; + background-color: transparent; + } + label.item-content i.icon.icon-checkbox:after { + content: ' '; + position: absolute; + width: 10px; + height: 10px; + left: 50%; + top: 50%; + margin-left: -5px; + margin-top: -5px; + background-color: @themeColor; + border-radius: 100%; + } + } } \ No newline at end of file diff --git a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less index 1dd26a597..26229adbb 100644 --- a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less +++ b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less @@ -474,14 +474,4 @@ } } } - label.item-content input[type=checkbox]:checked~.item-inner, - label.item-content input[type=radio]:checked~.item-inner { - background: no-repeat center; - background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2013%2010'%3E%3Cpolygon%20fill%3D'%2340865c'%20points%3D'11.6%2C0%204.4%2C7.2%201.4%2C4.2%200%2C5.6%204.4%2C10%204.4%2C10%204.4%2C10%2013%2C1.4%20'%2F%3E%3C%2Fsvg%3E"); - background-position: 90% center; - background-size: 13px 10px; - } - .icon.icon-checkbox{ - display:none; - } } diff --git a/apps/spreadsheeteditor/mobile/src/page/main.jsx b/apps/spreadsheeteditor/mobile/src/page/main.jsx index 28d7a265b..a305b2e84 100644 --- a/apps/spreadsheeteditor/mobile/src/page/main.jsx +++ b/apps/spreadsheeteditor/mobile/src/page/main.jsx @@ -112,9 +112,7 @@ class MainPage extends Component { } - { - - } + diff --git a/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx b/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx index 200cc01bd..e5d307379 100644 --- a/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx +++ b/apps/spreadsheeteditor/mobile/src/view/FilterOptions.jsx @@ -8,8 +8,6 @@ const FilterOptions = (props) => { const _t = t('View.Edit', {returnObjects: true}); useEffect(() => { - const $clearFilter = $$("#button-clear-filter"); - props.isValid ? $clearFilter.addClass('disabled') : $clearFilter.removeClass('disabled'); const is_all_checked = props.listVal.every(item => item.check); setAll(is_all_checked); }); @@ -47,13 +45,13 @@ const FilterOptions = (props) => { - {_t.textClearFilter} + {_t.textClearFilter} props.onDeleteFilter()} id="btn-delete-filter">{_t.textDeleteFilter} - props.onUpdateCell('all', e.target.checked)} name='filter-cellAll' checkbox checked={all}>Select All + props.onUpdateCell('all', e.target.checked)} name='filter-cellAll' checkbox checked={all}>{_t.textSelectAll} {props.listVal.map((value) => - props.onUpdateCell(value.id, e.target.checked)} key={value.value} name='filter-cell' value={value.value} title={value.cellvalue} checkbox checked={value.check} /> + props.onUpdateCell(value.id, e.target.checked)} key={value.value} name='filter-cell' value={value.value} title={value.cellvalue} checkbox checked={value.check} /> )}