import $ from 'jquery';
import { inject as service } from '@ember/service';
import { A } from '@ember/array';
import { set, get } from '@ember/object';
import { isBlank, isNone } from '@ember/utils';
import { scheduleOnce } from '@ember/runloop';
import FlexberryBaseComponent from './flexberry-base-component';
import serializeSortingParam from '../utils/serialize-sorting-param';
import QueryBuilder from 'ember-flexberry-data/query/builder';
import ODataAdapter from 'ember-flexberry-data/query/odata-adapter';
/**
* Columns configuration dialog Content component.
*
* @class ColsconfigDialogContentComponent
* @extends FlexberryBaseComponent
*/
export default FlexberryBaseComponent.extend({
/**
Columns configiration menu.
@property colsConfigMenu
@type {Class}
@default service()
*/
colsConfigMenu: service(),
/**
Service that triggers objectlistview events.
@property objectlistviewEventsService
@type {Class}
@default service()
*/
objectlistviewEventsService: service('objectlistview-events'),
/**
Service for managing the state of the application.
@property appState
@type AppStateService
*/
appState: service(),
/**
Current store.
@property store
@type {Object}
@default undefined
*/
store: undefined,
init: function() {
this._super(...arguments);
if (!this.get('model.colDescs')) {
return;
}
this.set('store', this.get('model.store'));
this.set('model.colDescs', A(this.get('model.colDescs')));
},
didRender: function() {
this._super(...arguments);
let exportParams = this.get('model.exportParams') || {};
if (exportParams.isExportExcel && exportParams.immediateExport) {
exportParams.immediateExport = false;
this.actions.apply.call(this);
}
},
didInsertElement: function() {
this._super(...arguments);
this.$('.sort-direction-dropdown').each((index, element) => {
const colDesc = this.get(`model.colDescs.${index}`);
$(element).dropdown({
onChange: (value) => {
this.send('setSortOrder', colDesc, element, value);
}
});
$(element).dropdown('set selected', get(colDesc, 'sortOrder'));
});
},
actions: {
/**
Invert column visibility (On/Off)
@method actions.invertVisibility
@param {Integer} n Row number.
*/
invertVisibility: function(n) {
let newHideState = !this.get(`model.colDescs.${n}.hide`);
this.set(`model.colDescs.${n}.hide`, newHideState);
},
/**
Set sort order and priority for column.
@method actions.setSortOrder
@param {Object} colDesc Column description object.
@param {Object} element Dropdown.
@param {String} value Selected value.
*/
setSortOrder: function(colDesc, element, value) {
if (colDesc.sortOrder !== parseInt(value)) {
if (value === '0') {
set(colDesc, 'sortPriority', undefined);
set(colDesc, 'sortOrder', undefined);
} else {
if (isNone(colDesc.sortPriority)) {
let max = 0;
this.get('model.colDescs').filter(c => {
let sortPriority = parseInt(c.sortPriority);
if (max < sortPriority) {
max = sortPriority;
}
});
set(colDesc, 'sortPriority', max + 1);
}
set(colDesc, 'sortOrder', parseInt(value));
}
}
},
/**
Move row upward in list.
@method actions.rowUp
@param {Integer} n Row number.
*/
rowUp: function(n) {
let array = this.get('model.colDescs');
let row = array[n];
array.removeObject(row);
array.insertAt(n - 1, row);
},
/**
Move row downward.
@method actions.rowDown
@param {Integer} n Row number.
*/
rowDown: function(n) {
let array = this.get('model.colDescs');
let row = array[n];
array.removeObject(row);
array.insertAt(n + 1, row);
},
/**
Apply specified usersettings.
@method actions.apply
*/
apply: function() {
this.get('appState').loading();
if (!this.get('model.exportParams.isExportExcel')) {
let colsConfig = this._getSettings();
let savePromise = this._getSavePromise(undefined, colsConfig);
/* eslint-disable no-unused-vars */
savePromise.then(
record => {
let sort = serializeSortingParam(colsConfig.sorting);
this.get('appState').reset();
let mainController = this.get('currentController.mainControler');
let userSettingsApplyFunction = mainController.get('userSettingsApply');
if (userSettingsApplyFunction instanceof Function) {
userSettingsApplyFunction.apply(mainController, [this.get('model.componentName'), colsConfig.sorting, colsConfig.perPage]);
} else {
mainController.set('sort', sort);
mainController.set('perPage', colsConfig.perPage || 5);
mainController.send('refreshList', this.get('model.componentName'));
}
}
).catch((reason) => {
this.currentController.send('handleError', reason);
});
/* eslint-enable no-unused-vars */
this.get('close')(colsConfig);
} else {
let store = this.get('store.onlineStore') || this.get('store');
let modelName = this.get('model.modelName');
let adapter = store.adapterFor(modelName);
let currentQuery = this._getCurrentQuery();
adapter.query(store, modelName, currentQuery).then((result) => {
let blob = new Blob([result], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
let anchor = $('.download-anchor');
if (!isBlank(anchor)) {
if (window.navigator.msSaveOrOpenBlob) {
let downloadFunction = function() {
window.navigator.msSaveOrOpenBlob(blob, 'list.xlsx');
};
anchor.on('click', downloadFunction);
anchor.get(0).click();
anchor.off('click', downloadFunction);
} else {
let downloadUrl = URL.createObjectURL(blob);
anchor.prop('href', downloadUrl);
anchor.prop('download', 'list.xlsx');
anchor.get(0).click();
}
}
}).catch((reason) => {
this.get('close')(); // close modal window
this.currentController.send('handleError', reason);
}).finally(() => {
this.get('appState').reset();
});
}
},
/**
Save specified usersettings.
@method actions.saveColsSetting
*/
saveColsSetting: function() {
let settingName = this.get('model.settingName');
if (settingName.length <= 0) {
this.set('currentController.message.type', 'warning');
this.set('currentController.message.visible', true);
this.set('currentController.message.caption', this.get('i18n').t('components.colsconfig-dialog-content.enter-setting-name'));
this.set('currentController.message.message', '');
this._scrollToBottom();
return;
}
let colsConfig = this._getSettings();
let savePromise = this._getSavePromise(settingName, colsConfig);
this.get('colsConfigMenu').addNamedSettingTrigger(settingName, this.get('model.componentName'), this.get('model.exportParams.isExportExcel'));
savePromise.then(
() => {
this.set('currentController.message.type', 'success');
this.set('currentController.message.visible', true);
this.set('currentController.message.caption', this.get('i18n').t('components.colsconfig-dialog-content.setting') +
settingName +
this.get('i18n').t('components.colsconfig-dialog-content.is-saved'));
this.set('currentController.message.message', '');
this._scrollToBottom();
},
error => {
this.set('currentController.message.type', 'error');
this.set('currentController.message.visible', true);
this.set('currentController.message.caption', this.get('i18n').t('components.colsconfig-dialog-content.have-errors'));
this.set('currentController.message.message', JSON.stringify(error));
this._scrollToBottom();
this.get('close')(colsConfig); // close modal window
this.currentController.send('handleError', error);
}
);
},
/* eslint-disable no-unused-vars */
handleError(error) {
this._super(...arguments);
return true;
}
/* eslint-enable no-unused-vars */
},
/**
Scrolling content to bottom.
@method _scrollToBottom
*/
_scrollToBottom() {
scheduleOnce('afterRender', this, function() {
let scrollBlock = this.$('.flexberry-colsconfig.content');
let messageBlockTop = this.$('.ui.message', scrollBlock).offset().top;
if (scrollBlock.offset().top + scrollBlock.outerHeight(true) <= messageBlockTop) {
scrollBlock.animate({ scrollTop: messageBlockTop }, 1000);
}
});
},
/**
Gets current query for export excel.
@method _getCurrentQuery
*/
_getCurrentQuery: function() {
let settings = this._getSettings();
let sortString = '';
let modelName = this.get('model.modelName');
settings.sorting.map(sort => {
sortString += `${sort.propName} ${sort.direction},`;
});
sortString = sortString.slice(0, -1);
let store = this.get('store.onlineStore') || this.get('store');
let builder = new QueryBuilder(store, modelName);
let adapter = new ODataAdapter('123', store);
let exportParams = this.get('model.exportParams') || {};
builder.selectByProjection(exportParams.projectionName, true);
let colsOrder = settings.colsOrder.filter(({ hide }) => !hide)
.map(column => {
let attributeName = adapter._getODataAttributeName(modelName, column.propName).replace(/\//g, '.');
let propName = column.name || column.propName;
return encodeURIComponent(attributeName) + '/' + encodeURIComponent(propName);
})
.join();
if (sortString) {
builder.orderBy(sortString);
}
let limitFunction = this.get('objectlistviewEventsService').getLimitFunction(this.get('model.componentName'));
if (limitFunction) {
builder.where(limitFunction);
}
if (exportParams.isExportExcel) {
builder.ofDataType('blob');
let customQueryParams = { colsOrder: colsOrder, exportExcel: exportParams.isExportExcel,
detSeparateRows: exportParams.detSeparateRows, detSeparateCols: exportParams.detSeparateCols };
builder.withCustomParams(customQueryParams);
}
let query = builder.build();
return query;
},
/* eslint-disable no-unused-vars */
_getSavePromise: function(settingName, colsConfig) {
let componentName = this.get('model.componentName');
let isExportExcel = this.get('model.exportParams.isExportExcel');
return this.get('userSettingsService').saveUserSetting(componentName, settingName, colsConfig, isExportExcel)
.then(result => {
this.get('colsConfigMenu').updateNamedSettingTrigger(componentName);
});
},
/* eslint-enable no-unused-vars */
_getSettings: function() {
let colsOrder = [];
let sortSettings = [];
let widthSetting = [];
let colDescs = this.get('model.colDescs');
colDescs.forEach((colDesc) => {
colsOrder.push({ propName: colDesc.propName, hide: colDesc.hide, name: colDesc.name.toString() });
if (!isNone(colDesc.sortPriority)) {
sortSettings.push({ propName: colDesc.propName, sortOrder: colDesc.sortOrder, sortPriority: colDesc.sortPriority });
}
if (this.get('model.saveColWidthState') && !isNaN(colDesc.columnWidth)) {
widthSetting.push({ propName: colDesc.propName, width: parseInt(colDesc.columnWidth) });
}
}, this);
sortSettings = sortSettings.sort((a, b) => a.sortPriority - b.sortPriority);
sortSettings = sortSettings.map((s) => { return { propName: s.propName, direction: s.sortOrder > 0 ? 'asc' : 'desc' }; });
let perPage = parseInt(this.get('model.perPageValue'));
if (isNaN(perPage) || perPage <= 0) {
perPage = 5;
}
let colsConfig = { colsOrder: colsOrder, sorting: sortSettings, perPage: perPage };
if (this.get('model.saveColWidthState')) {
colsConfig.columnWidths = widthSetting;
}
let exportParams = this.get('model.exportParams') || {};
if (exportParams.isExportExcel) {
colsConfig.detSeparateRows = exportParams.detSeparateRows;
colsConfig.detSeparateCols = exportParams.detSeparateCols;
}
return colsConfig;
}
});