diff --git a/apps/common/main/lib/util/LanguageInfo.js b/apps/common/main/lib/util/LanguageInfo.js index 618868ead..25c078385 100644 --- a/apps/common/main/lib/util/LanguageInfo.js +++ b/apps/common/main/lib/util/LanguageInfo.js @@ -100,6 +100,7 @@ Common.util.LanguageInfo = new(function() { 0x0402 : ["bg-BG", "Български (България)"], 0x0003 : ["ca", "Català"], 0x0403 : ["ca-ES", "Català (Català)"], + 0x0803 : ["ca-ES-valencia", "Català (Valencià)"], 0x7804 : ["zh", "中文"], 0x0004 : ["zh-Hans", "中文(简体)"], 0x0804 : ["zh-CN", "中文(中华人民共和国)"], @@ -315,7 +316,7 @@ Common.util.LanguageInfo = new(function() { 0x181A : ["sr-Latn-BA", "Srpski (Bosna i Hercegovina)"], 0x2C1A : ["sr-Latn-ME", "Srpski (Crna Gora)"], 0x081A : ["sr-Latn-CS", "Srpski (Srbija i Crna Gora (Prethodno))"], - 0x241A : ["sr-Latn-RS", "Srpski (Srbija)"], + 0x241A : ["sr-Latn-RS", "Srpski (Srbija, Latinica)"], 0x006C : ["nso", "Sesotho sa Leboa"], 0x046C : ["nso-ZA", "Sesotho sa Leboa (Afrika Borwa)"], 0x0032 : ["tn", "Setswana"], diff --git a/apps/documenteditor/mobile/app/controller/DocumentHolder.js b/apps/documenteditor/mobile/app/controller/DocumentHolder.js index 0c171546b..2e0c9d42a 100644 --- a/apps/documenteditor/mobile/app/controller/DocumentHolder.js +++ b/apps/documenteditor/mobile/app/controller/DocumentHolder.js @@ -86,6 +86,7 @@ define([ me.api.asc_registerCallback('asc_onHideForeignCursorLabel', _.bind(me.onApiHideForeignCursorLabel, me)); me.api.asc_registerCallback('asc_onAuthParticipantsChanged',_.bind(me.onApiUsersChanged, me)); me.api.asc_registerCallback('asc_onConnectionStateChanged', _.bind(me.onApiUserConnection, me)); + me.api.asc_registerCallback('asc_onDocumentContentReady', _.bind(me.onApiDocumentContentReady, me)); me.api.asc_coAuthoringGetUsers(); }, @@ -259,6 +260,10 @@ define([ } }, + onApiDocumentContentReady: function () { + _view = this.createView('DocumentHolder').render(); + }, + // Internal _openLink: function(url) { diff --git a/apps/documenteditor/mobile/app/view/DocumentHolder.js b/apps/documenteditor/mobile/app/view/DocumentHolder.js index b4310296a..c9b3625f4 100644 --- a/apps/documenteditor/mobile/app/view/DocumentHolder.js +++ b/apps/documenteditor/mobile/app/view/DocumentHolder.js @@ -68,7 +68,10 @@ define([ // Render layout render: function() { var el = $(this.el); - el.append(this.template({})); + + if (el.length > 0 && el.find('#' + _anchorId).length < 1) { + el.append(this.template()); + } return this; }, diff --git a/apps/presentationeditor/mobile/app/controller/DocumentHolder.js b/apps/presentationeditor/mobile/app/controller/DocumentHolder.js index 4e4535f0e..34da8550d 100644 --- a/apps/presentationeditor/mobile/app/controller/DocumentHolder.js +++ b/apps/presentationeditor/mobile/app/controller/DocumentHolder.js @@ -77,8 +77,9 @@ define([ me.api = api; - me.api.asc_registerCallback('asc_onShowPopMenu', _.bind(me.onApiShowPopMenu, me)); - me.api.asc_registerCallback('asc_onHidePopMenu', _.bind(me.onApiHidePopMenu, me)); + me.api.asc_registerCallback('asc_onShowPopMenu', _.bind(me.onApiShowPopMenu, me)); + me.api.asc_registerCallback('asc_onHidePopMenu', _.bind(me.onApiHidePopMenu, me)); + me.api.asc_registerCallback('asc_onDocumentContentReady', _.bind(me.onApiDocumentContentReady, me)); }, setMode: function (mode) { @@ -161,6 +162,10 @@ define([ _view && _view.hideMenu(); }, + onApiDocumentContentReady: function () { + _view = this.createView('DocumentHolder').render(); + }, + // Internal _openLink: function(url) { diff --git a/apps/presentationeditor/mobile/app/view/DocumentHolder.js b/apps/presentationeditor/mobile/app/view/DocumentHolder.js index de46fad96..db0377eb8 100644 --- a/apps/presentationeditor/mobile/app/view/DocumentHolder.js +++ b/apps/presentationeditor/mobile/app/view/DocumentHolder.js @@ -68,7 +68,9 @@ define([ // Render layout render: function() { var el = $(this.el); - el.append(this.template({})); + if (el.length > 0 && el.find('#' + _anchorId).length < 1) { + el.append(this.template()); + } return this; }, diff --git a/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js b/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js index cd7528c4b..c6b114db6 100644 --- a/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js +++ b/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js @@ -338,10 +338,31 @@ define([ onSortCells: function(menu, item) { if (this.api) { - this.api.asc_sortColFilter(item.value, '', undefined, (item.value==Asc.c_oAscSortOptions.ByColorFill) ? this.documentHolder.ssMenu.cellColor : this.documentHolder.ssMenu.fontColor); + var res = this.api.asc_sortCellsRangeExpand(); + if (res) { + var config = { + width: 500, + title: this.txtSorting, + msg: this.txtExpandSort, + iconCls: 'warn', + buttons: [ {caption: this.txtExpand, primary: true, value: 'expand'}, + {caption: this.txtSortSelected, primary: true, value: 'sort'}, + 'cancel'], + callback: _.bind(function(btn){ + if (btn == 'expand' || btn == 'sort') { + this.api.asc_sortColFilter(item.value, '', undefined, (item.value==Asc.c_oAscSortOptions.ByColorFill) ? this.documentHolder.ssMenu.cellColor : this.documentHolder.ssMenu.fontColor, btn == 'expand'); + } + Common.NotificationCenter.trigger('edit:complete', this.documentHolder); + Common.component.Analytics.trackEvent('DocumentHolder', 'Sort Cells'); + }, this) + }; + Common.UI.alert(config); + } else { + this.api.asc_sortColFilter(item.value, '', undefined, (item.value==Asc.c_oAscSortOptions.ByColorFill) ? this.documentHolder.ssMenu.cellColor : this.documentHolder.ssMenu.fontColor, res !== null); - Common.NotificationCenter.trigger('edit:complete', this.documentHolder); - Common.component.Analytics.trackEvent('DocumentHolder', 'Sort Cells'); + Common.NotificationCenter.trigger('edit:complete', this.documentHolder); + Common.component.Analytics.trackEvent('DocumentHolder', 'Sort Cells'); + } } }, @@ -2299,7 +2320,11 @@ define([ deleteText : 'Delete', deleteRowText : 'Delete Row', deleteColumnText : 'Delete Column', - txtNoChoices: 'There are no choices for filling the cell.
Only text values from the column can be selected for replacement.' + txtNoChoices: 'There are no choices for filling the cell.
Only text values from the column can be selected for replacement.', + txtExpandSort: 'The data next to the selection will not be sorted. Do you want to expand the selection to include the adjacent data or continue with sorting the currently selected cells only?', + txtExpand: 'Expand and sort', + txtSorting: 'Sorting', + txtSortSelected: 'Sort selected' }, SSE.Controllers.DocumentHolder || {})); }); \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/controller/Statusbar.js b/apps/spreadsheeteditor/main/app/controller/Statusbar.js index 777ad7f0e..61dea8682 100644 --- a/apps/spreadsheeteditor/main/app/controller/Statusbar.js +++ b/apps/spreadsheeteditor/main/app/controller/Statusbar.js @@ -104,6 +104,7 @@ define([ this.api.asc_registerCallback('asc_onWorksheetLocked', _.bind(this.onWorksheetLocked, this)); /** coauthoring end **/ this.api.asc_registerCallback('asc_onError', _.bind(this.onError, this)); + this.api.asc_registerCallback('asc_onFilterInfo', _.bind(this.onApiFilterInfo , this)); this.statusbar.setApi(api); }, @@ -185,6 +186,11 @@ define([ this.statusbar.updateTabbarBorders(); }, + onApiFilterInfo: function(countFilter, countRecords) { + this.statusbar.setFilteredInfo(countFilter, countRecords); + this.statusbar.updateTabbarBorders(); + }, + onApiEditCell: function(state) { var disableAdd = (state == Asc.c_oAscCellEditorState.editFormula), disable = (state != Asc.c_oAscCellEditorState.editEnd), diff --git a/apps/spreadsheeteditor/main/app/controller/Toolbar.js b/apps/spreadsheeteditor/main/app/controller/Toolbar.js index f9460c963..38d001d64 100644 --- a/apps/spreadsheeteditor/main/app/controller/Toolbar.js +++ b/apps/spreadsheeteditor/main/app/controller/Toolbar.js @@ -839,8 +839,27 @@ define([ }, onSortType: function(type, btn) { - if (this.api) - this.api.asc_sortColFilter(type, ''); + if (this.api) { + var res = this.api.asc_sortCellsRangeExpand(); + if (res) { + var config = { + width: 500, + title: this.txtSorting, + msg: this.txtExpandSort, + iconCls: 'warn', + buttons: [ {caption: this.txtExpand, primary: true, value: 'expand'}, + {caption: this.txtSortSelected, primary: true, value: 'sort'}, + 'cancel'], + callback: _.bind(function(btn){ + if (btn == 'expand' || btn == 'sort') { + this.api.asc_sortColFilter(type, '', undefined, undefined, btn == 'expand'); + } + }, this) + }; + Common.UI.alert(config); + } else + this.api.asc_sortColFilter(type, '', undefined, undefined, res !== null); + } }, onSearch: function(type, btn) { @@ -1936,6 +1955,7 @@ define([ need_disable = this._state.controlsdisabled.filters || !filterInfo || (filterInfo.asc_getIsApplyAutoFilter()!==true); toolbar.lockToolbar(SSE.enumLock.ruleDelFilter, need_disable, {array:[toolbar.btnClearAutofilter,toolbar.mnuitemClearFilter]}); + this.getApplication().getController('Statusbar').onApiFilterInfo(!need_disable); this._state.multiselect = info.asc_getFlags().asc_getMultiselect(); toolbar.lockToolbar(SSE.enumLock.multiselect, this._state.multiselect, { array: [toolbar.btnTableTemplate, toolbar.btnInsertHyperlink]}); @@ -2965,6 +2985,11 @@ define([ txtMatrix_2_2_LineBracket : 'Empty Matrix with Brackets', txtMatrix_2_2_DLineBracket : 'Empty Matrix with Brackets', txtMatrix_Flat_Round : 'Sparse Matrix', - txtMatrix_Flat_Square : 'Sparse Matrix' + txtMatrix_Flat_Square : 'Sparse Matrix', + txtExpandSort: 'The data next to the selection will not be sorted. Do you want to expand the selection to include the adjacent data or continue with sorting the currently selected cells only?', + txtExpand: 'Expand and sort', + txtSorting: 'Sorting', + txtSortSelected: 'Sort selected' + }, SSE.Controllers.Toolbar || {})); }); \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/template/StatusBar.template b/apps/spreadsheeteditor/main/app/template/StatusBar.template index edf69d514..adb030fc1 100644 --- a/apps/spreadsheeteditor/main/app/template/StatusBar.template +++ b/apps/spreadsheeteditor/main/app/template/StatusBar.template @@ -39,6 +39,10 @@ +
+
+ +
diff --git a/apps/spreadsheeteditor/main/app/template/TableSettings.template b/apps/spreadsheeteditor/main/app/template/TableSettings.template index 0e5a32083..76d313084 100644 --- a/apps/spreadsheeteditor/main/app/template/TableSettings.template +++ b/apps/spreadsheeteditor/main/app/template/TableSettings.template @@ -73,12 +73,12 @@
- +
- + diff --git a/apps/spreadsheeteditor/main/app/view/Statusbar.js b/apps/spreadsheeteditor/main/app/view/Statusbar.js index d3c237237..2d2bc1859 100644 --- a/apps/spreadsheeteditor/main/app/view/Statusbar.js +++ b/apps/spreadsheeteditor/main/app/view/Statusbar.js @@ -323,6 +323,10 @@ define([ this.labelAverage = $('#status-math-average', this.boxMath); this.boxMath.hide(); + this.boxFiltered = $('#status-filtered-box', this.el); + this.labelFiltered = $('#status-filtered-records', this.boxFiltered); + this.boxFiltered.hide(); + this.boxZoom = $('#status-zoom-box', this.el); this.boxZoom.find('.separator').css('border-left-color','transparent'); @@ -426,6 +430,23 @@ define([ },30); }, + setFilteredInfo: function(countFilter, countRecords) { + if (countFilter>0 && countRecords>0) {//filter is applied + if (!this.boxFiltered.is(':visible')) this.boxFiltered.show(); + this.labelFiltered.text(Common.Utils.String.format(this.filteredRecordsText, countFilter, countRecords)); + } else if (countFilter) {// filter mode + if (!this.boxFiltered.is(':visible')) this.boxFiltered.show(); + this.labelFiltered.text(this.filteredText); + } else { + if (this.boxFiltered.is(':visible')) this.boxFiltered.hide(); + } + + var me = this; + _.delay(function(){ + me.onTabInvisible(undefined, me.tabbar.checkInvisible(true)); + },30); + }, + /** coauthoring begin **/ onUsersClick: function() { this.panelUsers.removeClass('open'); @@ -600,6 +621,11 @@ define([ visible = true; } + if (this.boxFiltered.is(':visible')) { + right += parseInt(this.boxFiltered.css('width')); + visible = true; + } + if (this.panelUsers.is(':visible')) { right += parseInt(this.panelUsers.css('width')); visible = true; @@ -645,7 +671,9 @@ define([ tipUsers : 'Document is currently being edited by several users.', tipAccessRights : 'Manage document access rights', tipViewUsers : 'View users and manage document access rights', - txAccessRights : 'Change access rights' + txAccessRights : 'Change access rights', + filteredRecordsText : '{0} of {1} records filtered', + filteredText : 'Filter mode' }, SSE.Views.Statusbar || {})); diff --git a/apps/spreadsheeteditor/main/app/view/TableSettings.js b/apps/spreadsheeteditor/main/app/view/TableSettings.js index f9430b7e9..8bfa6b075 100644 --- a/apps/spreadsheeteditor/main/app/view/TableSettings.js +++ b/apps/spreadsheeteditor/main/app/view/TableSettings.js @@ -304,7 +304,10 @@ define([ handler: function(result, value) { if (result == 'ok') { if (me.api) { - // me.api.asc_setGraphicObjectProps(value.tableProps); + if (value.tableProps.altTitle) + me.api.asc_changeFormatTableInfo(me._state.TableName, Asc.c_oAscChangeTableStyleInfo.title, value.tableProps.altTitle); + if (value.tableProps.altDescription) + me.api.asc_changeFormatTableInfo(me._state.TableName, Asc.c_oAscChangeTableStyleInfo.description , value.tableProps.altDescription); } } diff --git a/apps/spreadsheeteditor/main/app/view/TableSettingsAdvanced.js b/apps/spreadsheeteditor/main/app/view/TableSettingsAdvanced.js index b49a875ee..1a7f58346 100644 --- a/apps/spreadsheeteditor/main/app/view/TableSettingsAdvanced.js +++ b/apps/spreadsheeteditor/main/app/view/TableSettingsAdvanced.js @@ -106,11 +106,11 @@ define([ 'text!spreadsheeteditor/main/app/template/TableSettingsAdvanced.temp _setDefaults: function(props) { if (props ){ - // var value = props.asc_getTitle(); - // this.inputAltTitle.setValue(value ? value : ''); - // - // value = props.asc_getDescription(); - // this.textareaAltDescription.val(value ? value : ''); + var value = props.asc_getTitle(); + this.inputAltTitle.setValue(value ? value : ''); + + value = props.asc_getDescription(); + this.textareaAltDescription.val(value ? value : ''); } }, diff --git a/apps/spreadsheeteditor/main/locale/en.json b/apps/spreadsheeteditor/main/locale/en.json index dc25078cd..ee60dbe08 100644 --- a/apps/spreadsheeteditor/main/locale/en.json +++ b/apps/spreadsheeteditor/main/locale/en.json @@ -194,6 +194,10 @@ "SSE.Controllers.DocumentHolder.txtTop": "Top", "SSE.Controllers.DocumentHolder.txtUnderbar": "Bar under text", "SSE.Controllers.DocumentHolder.txtWidth": "Width", + "SSE.Controllers.DocumentHolder.txtExpandSort": "The data next to the selection will not be sorted. Do you want to expand the selection to include the adjacent data or continue with sorting the currently selected cells only?", + "SSE.Controllers.DocumentHolder.txtExpand": "Expand and sort", + "SSE.Controllers.DocumentHolder.txtSorting": "Sorting", + "SSE.Controllers.DocumentHolder.txtSortSelected": "Sort selected", "SSE.Controllers.LeftMenu.newDocumentTitle": "Unnamed spreadsheet", "SSE.Controllers.LeftMenu.textByColumns": "By columns", "SSE.Controllers.LeftMenu.textByRows": "By rows", @@ -675,6 +679,10 @@ "SSE.Controllers.Toolbar.txtSymbol_xsi": "Xi", "SSE.Controllers.Toolbar.txtSymbol_zeta": "Zeta", "SSE.Controllers.Toolbar.warnMergeLostData": "Only the data from the upper-left cell will remain in the merged cell.
Are you sure you want to continue?", + "SSE.Controllers.Toolbar.txtExpandSort": "The data next to the selection will not be sorted. Do you want to expand the selection to include the adjacent data or continue with sorting the currently selected cells only?", + "SSE.Controllers.Toolbar.txtExpand": "Expand and sort", + "SSE.Controllers.Toolbar.txtSorting": "Sorting", + "SSE.Controllers.Toolbar.txtSortSelected": "Sort selected", "SSE.Views.AutoFilterDialog.btnCustomFilter": "Custom Filter", "SSE.Views.AutoFilterDialog.cancelButtonText": "Cancel", "SSE.Views.AutoFilterDialog.okButtonText": "OK", @@ -1406,6 +1414,8 @@ "SSE.Views.Statusbar.tipZoomOut": "Zoom Out", "SSE.Views.Statusbar.txAccessRights": "Change access rights", "SSE.Views.Statusbar.zoomText": "Zoom {0}%", + "SSE.Views.Statusbar.filteredRecordsText": "{0} of {1} records filtered", + "SSE.Views.Statusbar.filteredText": "Filter mode", "SSE.Views.TableOptionsDialog.errorAutoFilterDataRange": "The operation could not be done for the selected range of cells.
Select a uniform data range different from the existing one and try again.", "SSE.Views.TableOptionsDialog.errorFTChangeTableRangeError": "Operation could not be completed for the selected cell range.
Select a range so that the first table row was on the same row
and the resulting table overlapped the current one.", "SSE.Views.TableOptionsDialog.errorFTRangeIncludedOtherTables": "Operation could not be completed for the selected cell range.
Select a range which does not include other tables.", diff --git a/apps/spreadsheeteditor/main/resources/less/statusbar.less b/apps/spreadsheeteditor/main/resources/less/statusbar.less index e2b56f51d..bbee52d60 100644 --- a/apps/spreadsheeteditor/main/resources/less/statusbar.less +++ b/apps/spreadsheeteditor/main/resources/less/statusbar.less @@ -119,7 +119,8 @@ height: 25px; } - #status-math-box { + #status-math-box, + #status-filtered-box { float: right; padding-top: 6px; padding-right: 14px; diff --git a/apps/spreadsheeteditor/mobile/app/controller/Settings.js b/apps/spreadsheeteditor/mobile/app/controller/Settings.js index 9f54f5e1c..f93220509 100644 --- a/apps/spreadsheeteditor/mobile/app/controller/Settings.js +++ b/apps/spreadsheeteditor/mobile/app/controller/Settings.js @@ -74,10 +74,10 @@ define([ }); }, - // setApi: function (api) { - // var me = this; - // me.api = api; - // }, + setApi: function (api) { + var me = this; + me.api = api; + }, onLaunch: function () { this.createView('Settings').render(); diff --git a/build/Gruntfile.js b/build/Gruntfile.js index 73885594d..a5dd7e8a8 100644 --- a/build/Gruntfile.js +++ b/build/Gruntfile.js @@ -247,7 +247,8 @@ module.exports = function(grunt) { }, cssmin: { - styles: { + // options: {level: { 1: { roundingPrecision: 'all=3' }}}, // to round fw7 numbers in styles. need clean-css 4.0 + target: { files: { "<%= pkg.mobile.css.ios.dist %>" : packageFile['mobile']['css']['ios']['src'], "<%= pkg.mobile.css.material.dist %>" : packageFile['mobile']['css']['material']['src'] @@ -293,6 +294,19 @@ module.exports = function(grunt) { return packageFile.version; } }] + }, + fixResourceUrl: { + src: ['<%= pkg.mobile.js.requirejs.options.out %>', + '<%= pkg.mobile.css.ios.dist %>', + '<%= pkg.mobile.css.material.dist %>'], + overwrite: true, + replacements: [{ + from: /(?:\.{2}\/){4}common\/mobile\/resources\/img/g, + to: '../img' + },{ + from: /(?:\.{2}\/){2}common\/mobile/g, + to: '../mobile' + }] } } }); @@ -367,9 +381,16 @@ module.exports = function(grunt) { grunt.registerTask('deploy-jsrsasign', ['jsrsasign-init', 'clean', 'copy']); grunt.registerTask('deploy-requirejs', ['requirejs-init', 'clean', 'uglify']); - grunt.registerTask('deploy-app-main', ['main-app-init', 'clean', 'imagemin', 'less', 'requirejs', 'concat', 'copy', 'replace:writeVersion']); - grunt.registerTask('deploy-app-mobile', ['mobile-app-init', 'clean:deploy', 'cssmin:styles', 'copy:template-backup', 'htmlmin', 'requirejs', 'concat', 'copy:template-restore', 'clean:template-backup', 'copy:localization', 'copy:index-page', 'copy:images-app', 'replace:writeVersion']); - grunt.registerTask('deploy-app-embed', ['embed-app-init', 'clean:prebuild', 'uglify', 'less', 'copy', 'clean:postbuild']); + grunt.registerTask('deploy-app-main', ['main-app-init', 'clean', 'imagemin', 'less', 'requirejs', 'concat', + 'copy', 'replace:writeVersion']); + + grunt.registerTask('deploy-app-mobile', ['mobile-app-init', 'clean:deploy', 'cssmin', 'copy:template-backup', + 'htmlmin', 'requirejs', 'concat', 'copy:template-restore', + 'clean:template-backup', 'copy:localization', 'copy:index-page', + 'copy:images-app', 'replace:writeVersion', 'replace:fixResourceUrl']); + + grunt.registerTask('deploy-app-embed', ['embed-app-init', 'clean:prebuild', 'uglify', 'less', 'copy', + 'clean:postbuild']); doRegisterInitializeAppTask('documenteditor', 'DocumentEditor', 'documenteditor.json'); diff --git a/build/package.json b/build/package.json index e11d90655..e30af30dc 100644 --- a/build/package.json +++ b/build/package.json @@ -20,7 +20,7 @@ "grunt-contrib-uglify": "^0.8.1", "grunt-contrib-concat": "^0.5.1", "grunt-contrib-imagemin": "^1.0.0", - "grunt-contrib-cssmin": "^0.12.2", + "grunt-contrib-cssmin": "^1.0.0", "grunt-contrib-htmlmin": "^2.0.0", "vinyl-fs": "2.2.1", "less-plugin-clean-css": "1.5.0" diff --git a/build/spreadsheeteditor.json b/build/spreadsheeteditor.json index cf310b5b3..29b178747 100644 --- a/build/spreadsheeteditor.json +++ b/build/spreadsheeteditor.json @@ -396,6 +396,12 @@ { "expand": true, "cwd": "../apps/spreadsheeteditor/mobile/resources/img/", + "src": "**/*.png", + "dest": "../deploy/web-apps/apps/spreadsheeteditor/mobile/resources/img/" + }, + { + "expand": true, + "cwd": "../apps/common/mobile/resources/img/", "src": "**", "dest": "../deploy/web-apps/apps/spreadsheeteditor/mobile/resources/img/" }