diff --git a/apps/common/main/lib/util/utils.js b/apps/common/main/lib/util/utils.js index e85fd867b3..ee22d7a995 100644 --- a/apps/common/main/lib/util/utils.js +++ b/apps/common/main/lib/util/utils.js @@ -101,7 +101,8 @@ Common.Utils = _.extend(new(function() { Shape : 5, Slide : 6, Chart : 7, - MailMerge : 8 + MailMerge : 8, + Pivot : 9 }, isMobile = /android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent || navigator.vendor || window.opera), me = this, diff --git a/apps/spreadsheeteditor/main/app.js b/apps/spreadsheeteditor/main/app.js index c0e25840d8..5b6e2c9276 100644 --- a/apps/spreadsheeteditor/main/app.js +++ b/apps/spreadsheeteditor/main/app.js @@ -182,6 +182,7 @@ require([ 'spreadsheeteditor/main/app/view/ChartSettings', 'spreadsheeteditor/main/app/view/ShapeSettings', 'spreadsheeteditor/main/app/view/TextArtSettings', + 'spreadsheeteditor/main/app/view/PivotSettings', 'common/main/lib/util/utils', 'common/main/lib/util/LocalStorage', 'common/main/lib/controller/Fonts', diff --git a/apps/spreadsheeteditor/main/app/controller/RightMenu.js b/apps/spreadsheeteditor/main/app/controller/RightMenu.js index 85af0e8a4a..69e1fc3052 100644 --- a/apps/spreadsheeteditor/main/app/controller/RightMenu.js +++ b/apps/spreadsheeteditor/main/app/controller/RightMenu.js @@ -85,6 +85,7 @@ define([ this._settings[Common.Utils.documentSettingsType.TextArt] = {panelId: "id-textart-settings", panel: rightMenu.textartSettings, btn: rightMenu.btnTextArt, hidden: 1, locked: false}; this._settings[Common.Utils.documentSettingsType.Chart] = {panelId: "id-chart-settings", panel: rightMenu.chartSettings, btn: rightMenu.btnChart, hidden: 1, locked: false}; this._settings[Common.Utils.documentSettingsType.Table] = {panelId: "id-table-settings", panel: rightMenu.tableSettings, btn: rightMenu.btnTable, hidden: 1, locked: false}; + this._settings[Common.Utils.documentSettingsType.Pivot] = {panelId: "id-pivot-settings", panel: rightMenu.pivotSettings, btn: rightMenu.btnPivot, hidden: 1, locked: false}; }, setApi: function(api) { @@ -114,14 +115,15 @@ define([ var SelectedObjects = [], selectType = info.asc_getFlags().asc_getSelectionType(), formatTableInfo = info.asc_getFormatTableInfo(), - sparkLineInfo = info.asc_getSparklineInfo(); + sparkLineInfo = info.asc_getSparklineInfo(), + pivotInfo = info.asc_getPivotTableInfo(); if (selectType == Asc.c_oAscSelectionType.RangeImage || selectType == Asc.c_oAscSelectionType.RangeShape || selectType == Asc.c_oAscSelectionType.RangeChart || selectType == Asc.c_oAscSelectionType.RangeChartText || selectType == Asc.c_oAscSelectionType.RangeShapeText) { SelectedObjects = this.api.asc_getGraphicObjectProps(); } - if (SelectedObjects.length<=0 && !formatTableInfo && !sparkLineInfo && !this.rightmenu.minimizedMode) { + if (SelectedObjects.length<=0 && !formatTableInfo && !sparkLineInfo && !pivotInfo && !this.rightmenu.minimizedMode) { this.rightmenu.clearSelection(); this._openRightMenu = true; } @@ -130,10 +132,10 @@ define([ need_disable_table = (info.asc_getLockedTable()===true), need_disable_spark = (info.asc_getLockedSparkline()===true); - this.onFocusObject(SelectedObjects, formatTableInfo, sparkLineInfo, need_disable, need_disable_table, need_disable_spark); + this.onFocusObject(SelectedObjects, formatTableInfo, sparkLineInfo, pivotInfo, need_disable, need_disable_table, need_disable_spark); }, - onFocusObject: function(SelectedObjects, formatTableInfo, sparkLineInfo, isCellLocked, isTableLocked, isSparkLocked) { + onFocusObject: function(SelectedObjects, formatTableInfo, sparkLineInfo, pivotInfo, isCellLocked, isTableLocked, isSparkLocked) { if (!this.editMode) return; @@ -186,6 +188,13 @@ define([ this._settings[settingsType].btn.updateHint(this.rightmenu.txtSparklineSettings); } + if (pivotInfo) { + settingsType = Common.Utils.documentSettingsType.Pivot; + this._settings[settingsType].props = pivotInfo; + this._settings[settingsType].locked = isCellLocked; + this._settings[settingsType].hidden = 0; + } + var lastactive = -1, currentactive, priorityactive = -1, activePane = this.rightmenu.GetActivePane(); for (i=0; i + + + + + + + +
+ + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + +
+ + +
+ + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/template/RightMenu.template b/apps/spreadsheeteditor/main/app/template/RightMenu.template index 1f7d9abf6b..2259f7de2e 100644 --- a/apps/spreadsheeteditor/main/app/template/RightMenu.template +++ b/apps/spreadsheeteditor/main/app/template/RightMenu.template @@ -12,6 +12,8 @@
+
+
@@ -21,5 +23,6 @@ +
\ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/view/PivotSettings.js b/apps/spreadsheeteditor/main/app/view/PivotSettings.js new file mode 100644 index 0000000000..c7844c869a --- /dev/null +++ b/apps/spreadsheeteditor/main/app/view/PivotSettings.js @@ -0,0 +1,442 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2017 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, + * EU, LV-1021. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +/** + * PivotSettings.js + * + * Created by Julia Radzhabova on 7/10/17 + * Copyright (c) 2017 Ascensio System SIA. All rights reserved. + * + */ + +define([ + 'text!spreadsheeteditor/main/app/template/PivotSettings.template', + 'jquery', + 'underscore', + 'backbone', + 'common/main/lib/component/Button', + 'common/main/lib/component/ListView' +], function (menuTemplate, $, _, Backbone, Sortable) { + 'use strict'; + + SSE.Views.PivotSettings = Backbone.View.extend(_.extend({ + el: '#id-pivot-settings', + + // Compile our stats template + template: _.template(menuTemplate), + + // Delegated events for creating new items, and clearing completed ones. + events: { + }, + + options: { + alias: 'PivotSettings' + }, + + initialize: function () { + this._initSettings = true; + + this._state = { + TableName: '', + TemplateName: '', + Range: '', + CheckHeader: false, + CheckTotal: false, + CheckBanded: false, + CheckFirst: false, + CheckLast: false, + CheckColBanded: false, + CheckFilter: false, + DisabledControls: false, + TableNameError: false + }; + this.lockedControls = []; + this._locked = false; + + this._originalProps = null; + this._noApply = false; + + this.render(); + }, + + onCheckTemplateChange: function(type, stateName, field, newValue, oldValue, eOpts) { + this._state[stateName] = undefined; + if (this.api) + this.api.asc_changeFormatTableInfo(this._state.TableName, type, newValue=='checked'); + Common.NotificationCenter.trigger('edit:complete', this); + }, + + onTableTemplateSelect: function(combo, record){ + if (this.api && !this._noApply) { + this.api.asc_changeAutoFilter(this._state.TableName, Asc.c_oAscChangeFilterOptions.style, record.get('name')); + } + Common.NotificationCenter.trigger('edit:complete', this); + }, + + onEditClick: function(menu, item, e) { + if (this.api) { + if (item.options.idx>=0 && item.options.idx<4) + this.api.asc_changeSelectionFormatTable(this._state.TableName, item.value); + else if (item.options.idx>=4 && item.options.idx<8) { + this.api.asc_insertCellsInTable(this._state.TableName, item.value); + } else { + this.api.asc_deleteCellsInTable(this._state.TableName, item.value); + } + } + Common.NotificationCenter.trigger('edit:complete', this); + }, + + onTableNameChanged: function(input, newValue, oldValue) { + var oldName = this._state.TableName; + this._state.TableName = ''; + + if (oldName.toLowerCase() == newValue.toLowerCase()) { + Common.NotificationCenter.trigger('edit:complete', this); + return; + } + + var me = this, + isvalid = this.api.asc_checkDefinedName(newValue, null); + if (isvalid.asc_getStatus() === true) isvalid = true; + else { + switch (isvalid.asc_getReason()) { + case Asc.c_oAscDefinedNameReason.IsLocked: + isvalid = this.textIsLocked; + break; + case Asc.c_oAscDefinedNameReason.Existed: + isvalid = this.textExistName; + break; + case Asc.c_oAscDefinedNameReason.NameReserved: + isvalid = this.textReservedName; + break; + default: + isvalid = this.textInvalidName; + } + } + if (isvalid === true) { + this.api.asc_changeDisplayNameTable(oldName, newValue); + Common.NotificationCenter.trigger('edit:complete', this); + } else if (!this._state.TableNameError) { + this._state.TableNameError = true; + Common.UI.alert({ + msg: isvalid, + title: this.notcriticalErrorTitle, + iconCls: 'warn', + buttons: ['ok'], + callback: function(btn){ + Common.NotificationCenter.trigger('edit:complete', this); + me._state.TableNameError = false; + } + }); + } + }, + + render: function () { + var el = $(this.el); + el.html(this.template({ + scope: this + })); + + this.linkAdvanced = $('#table-advanced-link'); + }, + + setApi: function(o) { + this.api = o; + return this; + }, + + createDelayedControls: function() { + var me = this; + this.fieldsList = new Common.UI.ListView({ + el: $('#pivot-list-fields'), + store: new Common.UI.DataViewStore(), + simpleAddMode: true, + template: _.template(['
'].join('')), + itemTemplate: _.template([ + '
', + '', + '
<%= Common.Utils.String.htmlEncode(value) %>
', + '
' + ].join('')) + }); + this.fieldsList.on('item:select', _.bind(this.onFieldsCheck, this)); + // this.fieldsList.onKeyDown = _.bind(this.onFieldsListKeyDown, this); + this.lockedControls.push(this.fieldsList); + + // Sortable.create(this.fieldsList.$el.find('.listview')[0], {}); + + this.columnsList = new Common.UI.ListView({ + el: $('#pivot-list-columns'), + store: new Common.UI.DataViewStore(), + simpleAddMode: true, + template: _.template(['
'].join('')), + itemTemplate: _.template([ + '
', + '
<%= Common.Utils.String.htmlEncode(value) %>
', + '
', + '
' + ].join('')) + }); + // this.columnsList.on('item:select', _.bind(this.onColumnsSelect, this)); + // this.columnsList.onKeyDown = _.bind(this.onColumnsListKeyDown, this); + this.lockedControls.push(this.columnsList); + + this.rowsList = new Common.UI.ListView({ + el: $('#pivot-list-rows'), + store: new Common.UI.DataViewStore(), + simpleAddMode: true, + template: _.template(['
'].join('')), + itemTemplate: _.template([ + '
', + '
<%= Common.Utils.String.htmlEncode(value) %>
', + '
', + '
' + ].join('')) + }); + // this.rowsList.on('item:select', _.bind(this.onRowSelect, this)); + // this.rowsList.onKeyDown = _.bind(this.onRowsListKeyDown, this); + this.lockedControls.push(this.rowsList); + + this.valuesList = new Common.UI.ListView({ + el: $('#pivot-list-values'), + store: new Common.UI.DataViewStore(), + simpleAddMode: true, + template: _.template(['
'].join('')), + itemTemplate: _.template([ + '
', + '
<%= Common.Utils.String.htmlEncode(value) %>
', + '
', + '
' + ].join('')) + }); + // this.valuesList.on('item:select', _.bind(this.onValuesSelect, this)); + // this.valuesList.onKeyDown = _.bind(this.onValuesListKeyDown, this); + this.lockedControls.push(this.valuesList); + + this.filtersList = new Common.UI.ListView({ + el: $('#pivot-list-filters'), + store: new Common.UI.DataViewStore(), + simpleAddMode: true, + template: _.template(['
'].join('')), + itemTemplate: _.template([ + '
', + '
<%= Common.Utils.String.htmlEncode(value) %>
', + '
', + '
' + ].join('')) + }); + // this.filtersList.on('item:select', _.bind(this.onFiltersSelect, this)); + // this.filtersList.onKeyDown = _.bind(this.onFiltersListKeyDown, this); + this.lockedControls.push(this.filtersList); + + $(this.el).on('click', '#pivot-advanced-link', _.bind(this.openAdvancedSettings, this)); + + this._initSettings = false; + }, + + openAdvancedSettings: function(e) { + if (this.linkAdvanced.hasClass('disabled')) return; + + var me = this; + var win; + if (me.api && !this._locked){ + (new SSE.Views.TableSettingsAdvanced( + { + tableProps: me._originalProps, + api: me.api, + handler: function(result, value) { + if (result == 'ok' && me.api && value) { + me.api.asc_changeFormatTableInfo(me._state.TableName, Asc.c_oAscChangeTableStyleInfo.advancedSettings, value); + } + + Common.NotificationCenter.trigger('edit:complete', me); + } + })).show(); + } + }, + + ChangeSettings: function(props) { + if (this._initSettings) + this.createDelayedControls(); + + this.disableControls(this._locked); // need to update combodataview after disabled state + + if (props )//formatTableInfo + { + this._originalProps = props; + + this._state.TableName=props.asc_getName(); + + var arr = [], isChecked = [], + value = props.asc_getColumnFields(); + value && value.forEach(function (item) { + arr.push(new Common.UI.DataViewModel({ + selected : false, + allowSelected : true, + value : item + })); + isChecked[item] = true; + }); + this.columnsList.store.reset(arr); + this.columnsList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + + arr = []; + value = props.asc_getRowFields(); + value && value.forEach(function (item) { + arr.push(new Common.UI.DataViewModel({ + selected : false, + allowSelected : true, + value : item + })); + isChecked[item] = true; + }); + this.rowsList.store.reset(arr); + this.rowsList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + + arr = []; + value = props.asc_getDataFields(); + value && value.forEach(function (item) { + arr.push(new Common.UI.DataViewModel({ + selected : false, + allowSelected : true, + value : item + })); + isChecked[item] = true; + }); + this.valuesList.store.reset(arr); + this.valuesList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + + arr = []; + value = props.asc_getPageFields(); + value && value.forEach(function (item) { + arr.push(new Common.UI.DataViewModel({ + selected : false, + allowSelected : true, + value : item + })); + isChecked[item] = true; + }); + this.filtersList.store.reset(arr); + this.filtersList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + + arr = []; + value = props.asc_getFields(); + value && value.forEach(function (item) { + arr.push(new Common.UI.DataViewModel({ + selected : false, + allowSelected : true, + value : item, + check : isChecked[item] + })); + }); + this.fieldsList.store.reset(arr); + this.fieldsList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + } + }, + + onFieldsCheck: function (listView, itemView, record) { + if (this.checkCellTrigerBlock) + return; + + var target = '', type = '', isLabel = false, bound = null; + + var event = window.event ? window.event : window._event; + if (event) { + type = event.target.type; + target = $(event.currentTarget).find('.list-item'); + + if (target.length) { + bound = target.get(0).getBoundingClientRect(); + var _clientX = event.clientX*Common.Utils.zoom(), + _clientY = event.clientY*Common.Utils.zoom(); + if (bound.left < _clientX && _clientX < bound.right && + bound.top < _clientY && _clientY < bound.bottom) { + isLabel = true; + } + } + + if (type === 'button' || isLabel) { + this.updateFieldCheck(listView, record); + + _.delay(function () { + listView.$el.find('.listview').focus(); + }, 100, this); + } + } + }, + + updateFieldCheck: function (listView, record) { + if (record && listView) { + listView.isSuspendEvents = true; + + record.set('check', !record.get('check')); + + listView.isSuspendEvents = false; + listView.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true}); + } + }, + + setLocked: function (locked) { + this._locked = locked; + }, + + disableControls: function(disable) { + if (this._initSettings) return; + + if (this._state.DisabledControls!==disable) { + this._state.DisabledControls = disable; + _.each(this.lockedControls, function(item) { + item.setDisabled(disable); + }); + this.linkAdvanced.toggleClass('disabled', disable); + } + }, + + textFields: 'Select Fields', + textOK : 'OK', + textCancel : 'Cancel', + textValues : 'Values', + textRows : 'Rows', + textColumns : 'Columns', + textFilters : 'Filters', + notcriticalErrorTitle : 'Warning', + textAdvanced: 'Show advanced settings' + + }, SSE.Views.PivotSettings || {})); +}); \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/view/RightMenu.js b/apps/spreadsheeteditor/main/app/view/RightMenu.js index c685e418a6..4dac5b41e4 100644 --- a/apps/spreadsheeteditor/main/app/view/RightMenu.js +++ b/apps/spreadsheeteditor/main/app/view/RightMenu.js @@ -55,6 +55,7 @@ define([ 'spreadsheeteditor/main/app/view/ShapeSettings', 'spreadsheeteditor/main/app/view/TextArtSettings', 'spreadsheeteditor/main/app/view/TableSettings', + 'spreadsheeteditor/main/app/view/PivotSettings', 'common/main/lib/component/Scroller' ], function (menuTemplate, $, _, Backbone) { 'use strict'; @@ -123,6 +124,15 @@ define([ allowMouseEventsOnDisabled: true }); + this.btnPivot = new Common.UI.Button({ + hint: this.txtPivotSettings, + asctype: Common.Utils.documentSettingsType.Pivot, + enableToggle: true, + disabled: true, + toggleGroup: 'tabpanelbtnsGroup', + allowMouseEventsOnDisabled: true + }); + this._settings = []; this._settings[Common.Utils.documentSettingsType.Paragraph] = {panel: "id-paragraph-settings", btn: this.btnText}; this._settings[Common.Utils.documentSettingsType.Image] = {panel: "id-image-settings", btn: this.btnImage}; @@ -130,6 +140,7 @@ define([ this._settings[Common.Utils.documentSettingsType.Chart] = {panel: "id-chart-settings", btn: this.btnChart}; this._settings[Common.Utils.documentSettingsType.TextArt] = {panel: "id-textart-settings", btn: this.btnTextArt}; this._settings[Common.Utils.documentSettingsType.Table] = {panel: "id-table-settings", btn: this.btnTable}; + this._settings[Common.Utils.documentSettingsType.Pivot] = {panel: "id-pivot-settings", btn: this.btnPivot}; return this; }, @@ -151,6 +162,7 @@ define([ this.btnShape.setElement($('#id-right-menu-shape'), false); this.btnShape.render(); this.btnTextArt.setElement($('#id-right-menu-textart'), false); this.btnTextArt.render(); this.btnTable.setElement($('#id-right-menu-table'), false); this.btnTable.render(); + this.btnPivot.setElement($('#id-right-menu-pivot'), false); this.btnPivot.render(); this.btnText.on('click', _.bind(this.onBtnMenuClick, this)); this.btnImage.on('click', _.bind(this.onBtnMenuClick, this)); @@ -158,6 +170,7 @@ define([ this.btnShape.on('click', _.bind(this.onBtnMenuClick, this)); this.btnTextArt.on('click', _.bind(this.onBtnMenuClick, this)); this.btnTable.on('click', _.bind(this.onBtnMenuClick, this)); + this.btnPivot.on('click', _.bind(this.onBtnMenuClick, this)); this.paragraphSettings = new SSE.Views.ParagraphSettings(); this.imageSettings = new SSE.Views.ImageSettings(); @@ -165,6 +178,7 @@ define([ this.shapeSettings = new SSE.Views.ShapeSettings(); this.textartSettings = new SSE.Views.TextArtSettings(); this.tableSettings = new SSE.Views.TableSettings(); + this.pivotSettings = new SSE.Views.PivotSettings(); if (_.isUndefined(this.scroller)) { this.scroller = new Common.UI.Scroller({ @@ -187,6 +201,7 @@ define([ this.shapeSettings.setApi(api); this.textartSettings.setApi(api); this.tableSettings.setApi(api); + this.pivotSettings.setApi(api); return this; }, @@ -264,6 +279,7 @@ define([ txtTextArtSettings: 'Text Art Settings', txtChartSettings: 'Chart Settings', txtSparklineSettings: 'Sparkline Settings', - txtTableSettings: 'Table Settings' + txtTableSettings: 'Table Settings', + txtPivotSettings: 'Pivot Table Settings' }, SSE.Views.RightMenu || {})); }); \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app_dev.js b/apps/spreadsheeteditor/main/app_dev.js index 051df2a76c..975b3f8ac9 100644 --- a/apps/spreadsheeteditor/main/app_dev.js +++ b/apps/spreadsheeteditor/main/app_dev.js @@ -172,6 +172,7 @@ require([ 'spreadsheeteditor/main/app/view/ChartSettings', 'spreadsheeteditor/main/app/view/ShapeSettings', 'spreadsheeteditor/main/app/view/TextArtSettings', + 'spreadsheeteditor/main/app/view/PivotSettings', 'common/main/lib/util/utils', 'common/main/lib/util/LocalStorage', 'common/main/lib/controller/Fonts',