diff --git a/apps/spreadsheeteditor/main/app/view/ChartDataDialog.js b/apps/spreadsheeteditor/main/app/view/ChartDataDialog.js
new file mode 100644
index 000000000..b1af4167a
--- /dev/null
+++ b/apps/spreadsheeteditor/main/app/view/ChartDataDialog.js
@@ -0,0 +1,585 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2020
+ *
+ * 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 20A-12 Ernesta Birznieka-Upisha
+ * street, Riga, Latvia, EU, LV-1050.
+ *
+ * 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
+ *
+ */
+
+/**
+ * ChartDataDialog.js
+ *
+ * Created by Julia Radzhabova on 06.07.2020
+ * Copyright (c) 2020 Ascensio System SIA. All rights reserved.
+ *
+ */
+
+define([
+ 'common/main/lib/util/utils',
+ 'common/main/lib/component/MetricSpinner',
+ 'common/main/lib/component/ComboBox',
+ 'common/main/lib/component/ListView',
+ 'common/main/lib/view/AdvancedSettingsWindow'
+], function () { 'use strict';
+
+ var _CustomItem = Common.UI.DataViewItem.extend({
+ initialize : function(options) {
+ Common.UI.BaseView.prototype.initialize.call(this, options);
+
+ var me = this;
+
+ me.template = me.options.template || me.template;
+
+ me.listenTo(me.model, 'change:sort', function() {
+ me.render();
+ me.trigger('change', me, me.model);
+ });
+ me.listenTo(me.model, 'change:selected', function() {
+ var el = me.$el || $(me.el);
+ el.toggleClass('selected', me.model.get('selected') && me.model.get('allowSelected'));
+ me.onSelectChange(me.model, me.model.get('selected') && me.model.get('allowSelected'));
+ });
+ me.listenTo(me.model, 'remove', me.remove);
+ }
+ });
+
+ SSE.Views.ChartDataDialog = Common.Views.AdvancedSettingsWindow.extend(_.extend({
+ options: {
+ contentWidth: 370,
+ height: 490,
+ buttons: null
+ },
+
+ initialize : function(options) {
+ var me = this;
+
+ _.extend(this.options, {
+ title: this.textTitle,
+ template: [
+ '
',
+ '
',
+ '
',
+ '
',
+ '',
+ '',
+ '', me.textDataRange, ' ',
+ ' ',
+ ' ',
+ '',
+ '',
+ '
',
+ ' ',
+ ' ',
+ '',
+ '',
+ '', me.textSeries, ' ',
+ '
',
+ ' ',
+ ' ',
+ '',
+ '',
+ '', me.textAdd, ' ',
+ '', me.textEdit, ' ',
+ '', me.textDelete, ' ',
+ '',
+ ' ',
+ ' ',
+ '',
+ '',
+ '', me.textSwitch, ' ',
+ ' ',
+ ' ',
+ '',
+ '',
+ '', me.textCategory, ' ',
+ '
',
+ ' ',
+ ' ',
+ '',
+ '',
+ '', me.textEdit, ' ',
+ ' ',
+ ' ',
+ '
',
+ '
',
+ '
',
+ '
',
+ '
',
+ ''
+ ].join('')
+ }, options);
+
+ this.handler = options.handler;
+
+ Common.Views.AdvancedSettingsWindow.prototype.initialize.call(this, this.options);
+
+ this._noApply = true;
+ this._changedProps = null;
+
+ this.api = this.options.api;
+ this.chartSettings = this.options.chartSettings;
+ this.dataRangeValid = '';
+ this.dataDirect = 0;
+ this.currentChartType = Asc.c_oAscChartTypeSettings.barNormal;
+ },
+
+ render: function() {
+ Common.Views.AdvancedSettingsWindow.prototype.render.call(this);
+ var me = this;
+
+ this.txtDataRange = new Common.UI.InputFieldBtn({
+ el : $('#chart-dlg-txt-range'),
+ name : 'range',
+ style : 'width: 100%;',
+ btnHint : this.textSelectData,
+ allowBlank : true,
+ validateOnChange: true
+ });
+ this.txtDataRange.on('button:click', _.bind(this.onSelectData_simple, this));
+ this.txtDataRange.on('changed:after', function(input, newValue, oldValue, e) {
+ if (newValue !==me.dataRangeValid) {
+ if (me.isRangeValid()) {
+ me.dataRangeValid = newValue;
+ me.txtDataRange.checkValidate();
+ me.chartSettings.putRange(me.dataRangeValid);
+ me.api.asc_editChartDrawingObject(me.chartSettings);
+ } else {
+ me.txtDataRange.setValue(me.dataRangeValid);
+ me.txtDataRange.checkValidate();
+ }
+ }
+ });
+
+ // Chart data
+ this.seriesList = new Common.UI.ListView({
+ el: $('#chart-dlg-series-list', this.$window),
+ store: new Common.UI.DataViewStore(),
+ emptyText: '',
+ scrollAlwaysVisible: true,
+ template: _.template(['
'].join('')),
+ itemTemplate: _.template([
+ '',
+ '
',
+ ' ',
+ ' ',
+ ' ',
+ '
',
+ '
<%= Common.Utils.String.htmlEncode(value) %>
',
+ '
',
+ '
'
+ ].join(''))
+ });
+ this.seriesList.createNewItem = function(record) {
+ return new _CustomItem({
+ template: this.itemTemplate,
+ model: record
+ });
+ };
+ this.seriesList.on({
+ 'item:change': this.onItemChanged.bind(this),
+ 'item:add': this.onItemChanged.bind(this),
+ 'item:select': this.onCellCheck.bind(this)
+ });
+ this.seriesList.onKeyDown = _.bind(this.onListKeyDown, this, 'series');
+ this.seriesList.createNewItem = function(record) {
+ return new _CustomItem({
+ template: this.itemTemplate,
+ model: record
+ });
+ };
+ this.seriesList.on('item:select', _.bind(this.onSelectSeries, this));
+
+ this.btnAdd = new Common.UI.Button({
+ el: $('#chart-dlg-btn-add')
+ });
+ this.btnAdd.on('click', _.bind(this.onAddSeries, this, false));
+
+ this.btnDelete = new Common.UI.Button({
+ el: $('#chart-dlg-btn-delete')
+ });
+ // this.btnDelete.on('click', _.bind(this.onDeleteSeries, this));
+
+ this.btnEdit = new Common.UI.Button({
+ el: $('#chart-dlg-btn-edit')
+ });
+ this.btnEdit.on('click', _.bind(this.onEditSeries, this, false));
+
+ this.btnUp = new Common.UI.Button({
+ parentEl: $('#chart-dlg-btn-up'),
+ cls: 'btn-toolbar',
+ iconCls: 'caret-up',
+ hint: this.textUp
+ });
+ // this.btnUp.on('click', _.bind(this.onMoveClick, this, true));
+
+ this.btnDown = new Common.UI.Button({
+ parentEl: $('#chart-dlg-btn-down'),
+ cls: 'btn-toolbar',
+ iconCls: 'caret-down',
+ hint: this.textDown
+ });
+ // this.btnDown.on('click', _.bind(this.onMoveClick, this, false));
+
+ this.btnSwitch = new Common.UI.Button({
+ el: $('#chart-dlg-btn-switch')
+ });
+ // this.btnSwitch.on('click', _.bind(this.onSwitch, this));
+
+ this.categoryList = new Common.UI.ListView({
+ el: $('#chart-dlg-category-list', this.$window),
+ store: new Common.UI.DataViewStore(),
+ emptyText: '',
+ scrollAlwaysVisible: true,
+ template: _.template(['
'].join('')),
+ itemTemplate: _.template([
+ '',
+ '
',
+ ' ',
+ ' ',
+ ' ',
+ '
',
+ '
<%= Common.Utils.String.htmlEncode(value) %>
',
+ '
',
+ '
'
+ ].join(''))
+ });
+ this.categoryList.on({
+ 'item:change': this.onItemChanged.bind(this),
+ 'item:add': this.onItemChanged.bind(this),
+ 'item:select': this.onCellCheck.bind(this)
+ });
+ this.categoryList.onKeyDown = _.bind(this.onListKeyDown, this, 'category');
+
+ this.btnEditCategory = new Common.UI.Button({
+ el: $('#chart-dlg-btn-category-edit')
+ });
+ this.btnEditCategory.on('click', _.bind(this.onEditCategory, this, false));
+
+ this.afterRender();
+ },
+
+ afterRender: function() {
+ this._setDefaults(this.chartSettings);
+ },
+
+ show: function() {
+ Common.Views.AdvancedSettingsWindow.prototype.show.apply(this, arguments);
+
+ var me = this;
+ _.delay(function(){
+ me.txtDataRange.cmpEl.find('input').focus();
+ },50);
+ },
+
+ close: function () {
+ this.api.asc_onCloseChartFrame();
+ Common.Views.AdvancedSettingsWindow.prototype.close.apply(this, arguments);
+ },
+
+ _setDefaults: function (props) {
+ var me = this;
+ if (props ){
+ this.chartSettings = props;
+
+ this.currentChartType = props.getType();
+
+ var value = props.getRange();
+ this.txtDataRange.setValue((value) ? value : '');
+ this.dataRangeValid = value;
+
+ this.txtDataRange.validation = function(value) {
+ if (_.isEmpty(value)) {
+ return true;
+ }
+
+ var isvalid = me.api.asc_checkDataRange(Asc.c_oAscSelectionDialogType.Chart, value, false);
+ return (isvalid==Asc.c_oAscError.ID.DataRangeError) ? me.textInvalidRange : true;
+ };
+
+ this.dataDirect = props.getInColumns() ? 1 : 0;
+ }
+ },
+
+ getSettings: function () {
+ this.chartSettings.putRange(this.txtDataRange.getValue());
+ return { chartSettings: this.chartSettings};
+ },
+
+ onDlgBtnClick: function(event) {
+ var me = this;
+ var state = (typeof(event) == 'object') ? event.currentTarget.attributes['result'].value : event;
+ if (state == 'ok') {
+ this.handler && this.handler.call(this, state, (state == 'ok') ? this.getSettings() : undefined);
+ }
+
+ this.close();
+ },
+
+ onPrimary: function() {
+ this.onDlgBtnClick('ok');
+ return false;
+ },
+
+ isRangeValid: function() {
+ var isvalid;
+ if (!_.isEmpty(this.txtDataRange.getValue())) {
+ isvalid = this.api.asc_checkDataRange(Asc.c_oAscSelectionDialogType.Chart, this.txtDataRange.getValue(), true, this.dataDirect===0, this.currentChartType);
+ if (isvalid == Asc.c_oAscError.ID.No)
+ return true;
+ } else
+ return true;
+
+ if (isvalid == Asc.c_oAscError.ID.StockChartError) {
+ Common.UI.warning({msg: this.errorStockChart});
+ } else if (isvalid == Asc.c_oAscError.ID.MaxDataSeriesError) {
+ Common.UI.warning({msg: this.errorMaxRows});
+ } else if (isvalid == Asc.c_oAscError.ID.MaxDataPointsError)
+ Common.UI.warning({msg: this.errorMaxPoints});
+ else
+ this.txtDataRange.cmpEl.find('input').focus();
+ return false;
+ },
+
+ onSelectData_simple: function() {
+ var me = this;
+ if (me.api) {
+ var props = me.chartSettings;
+ var handlerDlg = function(dlg, result) {
+ if (result == 'ok' && me.isRangeValid()) {
+ me.dataRangeValid = dlg.getSettings();
+ me.txtDataRange.setValue(me.dataRangeValid);
+ me.txtDataRange.checkValidate();
+ props.putRange(me.dataRangeValid);
+ me.api.asc_setSelectionDialogMode(Asc.c_oAscSelectionDialogType.None);
+ me.api.asc_editChartDrawingObject(props);
+ }
+ };
+
+ var win = new SSE.Views.CellRangeDialog({
+ handler: handlerDlg
+ }).on('close', function() {
+ me.show();
+ });
+
+ var xy = me.$window.offset();
+ me.hide();
+ win.show(xy.left + 160, xy.top + 125);
+ win.setSettings({
+ api : me.api,
+ range : (!_.isEmpty(me.txtDataRange.getValue()) && (me.txtDataRange.checkValidate()==true)) ? me.txtDataRange.getValue() : me.dataRangeValid,
+ type : Asc.c_oAscSelectionDialogType.Chart
+ });
+ }
+ },
+
+ onSelectData: function() {
+ var me = this;
+ if (me.api) {
+ var props = me.chartSettings,
+ handlerDlg = function(dlg, result) {
+ if (result == 'ok' && me.isRangeValid()) {
+ props.putRange(dlg.getSettings());
+ me.api.asc_setSelectionDialogMode(Asc.c_oAscSelectionDialogType.None);
+ me.api.asc_editChartDrawingObject(props);
+ }
+ },
+ validation = function(value) {
+ var isvalid;
+ if (!_.isEmpty(value)) {
+ isvalid = me.api.asc_checkDataRange(Asc.c_oAscSelectionDialogType.Chart, value, true, !props.getInColumns(), me.currentChartType);
+ if (isvalid == Asc.c_oAscError.ID.No)
+ return true;
+ } else return '';
+
+ if (isvalid == Asc.c_oAscError.ID.StockChartError) {
+ return this.errorStockChart;
+ } else if (isvalid == Asc.c_oAscError.ID.MaxDataSeriesError) {
+ return this.errorMaxRows;
+ }
+ return this.txtInvalidRange;
+ };
+
+ var win = new SSE.Views.CellRangeDialog({
+ handler: handlerDlg
+ }).on('close', function() {
+ me.show();
+ // me.api.asc_onCloseChartFrame();
+ });
+
+ var xy = me.$window.offset();
+ me.hide();
+ win.show(xy.left + 160, xy.top + 125);
+ win.setSettings({
+ api : me.api,
+ range : props.getRange(),
+ validation: validation,
+ type : Asc.c_oAscSelectionDialogType.Chart
+ });
+ }
+ },
+
+ onItemChanged: function (view, record) {
+ var state = record.model.get('check');
+ if ( state == 'indeterminate' )
+ $('input[type=checkbox]', record.$el).prop('indeterminate', true);
+ else $('input[type=checkbox]', record.$el).prop({checked: state, indeterminate: false});
+ },
+
+ onCellCheck: function (listView, itemView, record) {
+ if (this.checkCellTrigerBlock)
+ return;
+
+ var target = '', isLabel = false, bound = null;
+
+ var event = window.event ? window.event : window._event;
+ if (event) {
+ 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 (isLabel || event.target.className.match('checkbox')) {
+ this.updateCellCheck(listView, record);
+
+ _.delay(function () {
+ listView.$el.find('.listview').focus();
+ }, 100, this);
+ }
+ }
+ },
+
+ onListKeyDown: function (type, e, data) {
+ var record = null, listView = (type=='series') ? this.seriesList : this.categoryList;
+
+ if (listView.disabled) return;
+ if (_.isUndefined(undefined)) data = e;
+
+ if (data.keyCode == Common.UI.Keys.SPACE) {
+ data.preventDefault();
+ data.stopPropagation();
+
+ this.updateCellCheck(listView, listView.getSelectedRec());
+ } else if (type=='series' && data.keyCode==Common.UI.Keys.DELETE && !this.btnDelete.isDisabled()) {
+ // this.onDeleteSeries();
+ } else {
+ Common.UI.DataView.prototype.onKeyDown.call(listView, e, data);
+ }
+ },
+
+ updateCellCheck: function (listView, record) {
+ if (record && listView) {
+ record.set('check', !record.get('check'));
+ // listView.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true, suppressScrollX: true});
+ }
+ },
+
+ onSelectSeries: function(lisvView, itemView, record) {
+ this.updateMoveButtons();
+ },
+
+ updateMoveButtons: function() {
+ var rec = this.seriesList.getSelectedRec(),
+ index = rec ? this.seriesList.store.indexOf(rec) : -1;
+ this.btnUp.setDisabled(index<1);
+ this.btnDown.setDisabled(index<0 || index==this.seriesList.store.length-1);
+ },
+
+ onAddSeries: function() {
+ var handlerDlg = function(dlg, result) {
+ if (result == 'ok') {
+ var changedValue = dlg.getSettings();
+ }
+ };
+ this.changeDataRange(1, true, handlerDlg);
+ },
+
+ onEditSeries: function() {
+ var handlerDlg = function(dlg, result) {
+ if (result == 'ok') {
+ var changedValue = dlg.getSettings();
+ }
+ };
+ this.changeDataRange(1, false, handlerDlg);
+ },
+
+ onEditCategory: function() {
+ var handlerDlg = function(dlg, result) {
+ if (result == 'ok') {
+ var changedValue = dlg.getSettings();
+ }
+ };
+ this.changeDataRange(0, false, handlerDlg);
+ },
+
+ changeDataRange: function(type, add, handlerDlg) {
+ var me = this;
+ var win = new SSE.Views.ChartDataRangeDialog({
+ type: type, //series
+ handler: handlerDlg
+ }).on('close', function() {
+ me.show();
+ });
+
+ var xy = me.$window.offset();
+ me.hide();
+ win.show(xy.left + 160, xy.top + 125);
+ win.setSettings({
+ api : me.api
+ });
+ },
+
+ textTitle: 'Chart Data',
+ txtEmpty: 'This field is required',
+ textInvalidRange: 'ERROR! Invalid cells range',
+ textSelectData: 'Select data',
+ errorMaxRows: 'ERROR! The maximum number of data series per chart is 255.',
+ errorStockChart: 'Incorrect row order. To build a stock chart place the data on the sheet in the following order: opening price, max price, min price, closing price.',
+ errorMaxPoints: 'ERROR! The maximum number of points in series per chart is 4096.',
+ textSeries: 'Legend Entries (Series)',
+ textAdd: 'Add',
+ textEdit: 'Edit',
+ textDelete: 'Remove',
+ textSwitch: 'Switch Row/Column',
+ textCategory: 'Horizontal (Category) Axis Labels',
+ textUp: 'Up',
+ textDown: 'Down',
+ textData: 'Data'
+ }, SSE.Views.ChartDataDialog || {}))
+});
diff --git a/apps/spreadsheeteditor/main/app/view/ChartSettings.js b/apps/spreadsheeteditor/main/app/view/ChartSettings.js
index 831622d30..0afbfdec4 100644
--- a/apps/spreadsheeteditor/main/app/view/ChartSettings.js
+++ b/apps/spreadsheeteditor/main/app/view/ChartSettings.js
@@ -46,7 +46,8 @@ define([
'common/main/lib/component/Button',
'common/main/lib/component/MetricSpinner',
'common/main/lib/component/ComboDataView',
- 'spreadsheeteditor/main/app/view/ChartSettingsDlg'
+ 'spreadsheeteditor/main/app/view/ChartSettingsDlg',
+ 'spreadsheeteditor/main/app/view/ChartDataDialog'
], function (menuTemplate, $, _, Backbone) {
'use strict';
@@ -851,7 +852,7 @@ define([
}
},
- onSelectData: function() {
+ onSelectData_simple: function() {
var me = this;
if (me.api) {
var props = me.api.asc_getChartObject(),
@@ -895,7 +896,29 @@ define([
});
}
},
-
+
+ onSelectData: function() {
+ var me = this;
+ var win, props;
+ if (me.api){
+ props = me.api.asc_getChartObject();
+ if (props) {
+ (new SSE.Views.ChartDataDialog(
+ {
+ chartSettings: props,
+ api: me.api,
+ handler: function(result, value) {
+ if (result == 'ok') {
+ if (me.api) {
+ }
+ }
+ Common.NotificationCenter.trigger('edit:complete', me);
+ }
+ })).show();
+ }
+ }
+ },
+
onSelectType: function(btn, picker, itemView, record) {
if (this._noApply) return;