From 87fd4e7f575c8a857d440cc04606aad259de1c06 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 29 Jun 2023 15:12:57 +0300 Subject: [PATCH] ref --- client/src/views/import/index.js | 109 +-- client/src/views/import/step1.js | 1135 ++++++++++++++++-------------- 2 files changed, 646 insertions(+), 598 deletions(-) diff --git a/client/src/views/import/index.js b/client/src/views/import/index.js index 4bf1d07f43..f8b80a9af4 100644 --- a/client/src/views/import/index.js +++ b/client/src/views/import/index.js @@ -26,79 +26,80 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -define('views/import/index', ['view'], function (Dep) { +/** @module views/import/index */ - return Dep.extend({ +import View from 'view'; - template: 'import/index', +class IndexImportView extends View { - data: function () { - return { - fromAdmin: this.options.fromAdmin, - }; - }, + template = 'import/index' - formData: null, + formData = null + fileContents = null - fileContents: null, + data() { + return { + fromAdmin: this.options.fromAdmin, + }; + } - setup: function () { - this.entityType = this.options.entityType || null; + setup() { + this.entityType = this.options.entityType || null; - this.startFromStep = 1; + this.startFromStep = 1; - if (this.options.formData || this.options.fileContents) { - this.formData = this.options.formData || {}; - this.fileContents = this.options.fileContents || null; + if (this.options.formData || this.options.fileContents) { + this.formData = this.options.formData || {}; + this.fileContents = this.options.fileContents || null; - this.entityType = this.formData.entityType || null; + this.entityType = this.formData.entityType || null; - if (this.options.step) { - this.startFromStep = this.options.step; - } + if (this.options.step) { + this.startFromStep = this.options.step; } - }, + } + } - changeStep: function (num, result) { - this.step = num; + changeStep(num, result) { + this.step = num; - if (num > 1) { - this.setConfirmLeaveOut(true); - } + if (num > 1) { + this.setConfirmLeaveOut(true); + } - this.createView('step', 'views/import/step' + num.toString(), { - el: this.options.el + ' > .import-container', - entityType: this.entityType, - formData: this.formData, - result: result - }, (view) => { - view.render(); - }); + this.createView('step', 'views/import/step' + num.toString(), { + el: this.options.el + ' > .import-container', + entityType: this.entityType, + formData: this.formData, + result: result, + }, view => { + view.render(); + }); - var url = '#Import'; + var url = '#Import'; - if (this.options.fromAdmin) { - url = '#Admin/import'; - } + if (this.options.fromAdmin) { + url = '#Admin/import'; + } - if (this.step > 1) { - url += '/index/step=' + this.step; - } + if (this.step > 1) { + url += '/index/step=' + this.step; + } - this.getRouter().navigate(url, {trigger: false}); - }, + this.getRouter().navigate(url, {trigger: false}); + } - afterRender: function () { - this.changeStep(this.startFromStep); - }, + afterRender() { + this.changeStep(this.startFromStep); + } - updatePageTitle: function () { - this.setPageTitle(this.getLanguage().translate('Import', 'labels', 'Admin')); - }, + updatePageTitle() { + this.setPageTitle(this.getLanguage().translate('Import', 'labels', 'Admin')); + } - setConfirmLeaveOut: function (value) { - this.getRouter().confirmLeaveOut = value; - }, + setConfirmLeaveOut(value) { + this.getRouter().confirmLeaveOut = value; + } +} - }); -}); +export default IndexImportView; diff --git a/client/src/views/import/step1.js b/client/src/views/import/step1.js index cd4a33a8f8..f67aa561c0 100644 --- a/client/src/views/import/step1.js +++ b/client/src/views/import/step1.js @@ -26,598 +26,645 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -define('views/import/step1', ['view', 'model'], function (Dep, Model) { +import View from 'view'; +import Model from 'model'; - return Dep.extend({ +class Step1ImportView extends View { - template: 'import/step-1', + template = 'import/step-1' - events: { - 'change #import-file': function (e) { - var $file = $(e.currentTarget); - var files = e.currentTarget.files; - if (files.length) { - this.loadFile(files[0]); - } - }, + events = { + /** @this Step1ImportView */ + 'change #import-file': function (e) { + let files = e.currentTarget.files; - 'click button[data-action="next"]': function () { - this.next(); - }, - - 'click button[data-action="saveAsDefault"]': function () { - this.saveAsDefault(); - }, - }, - - getEntityList: function () { - var list = []; - var scopes = this.getMetadata().get('scopes'); - for (var scopeName in scopes) { - if (scopes[scopeName].importable) { - if (!this.getAcl().checkScope(scopeName, 'create')) continue; - list.push(scopeName); - } + if (files.length) { + this.loadFile(files[0]); } - list.sort(function (v1, v2) { - return this.translate(v1, 'scopeNamesPlural').localeCompare(this.translate(v2, 'scopeNamesPlural')); - }.bind(this)); - - return list; }, - - data: function () { - return { - entityList: this.getEntityList(), - }; + /** @this Step1ImportView */ + 'click button[data-action="next"]': function () { + this.next(); }, + /** @this Step1ImportView */ + 'click button[data-action="saveAsDefault"]': function () { + this.saveAsDefault(); + }, + } - setup: function () { - this.attributeList = [ - 'entityType', - 'action', - ]; + getEntityList() { + let list = []; + let scopes = this.getMetadata().get('scopes'); - this.paramList = [ - 'headerRow', - 'decimalMark', - 'personNameFormat', - 'delimiter', - 'dateFormat', - 'timeFormat', - 'currency', - 'timezone', - 'textQualifier', - 'silentMode', - 'idleMode', - 'skipDuplicateChecking', - 'manualMode', - ]; - - this.paramList.forEach(function (item) { - this.attributeList.push(item); - }, this); - - this.formData = this.options.formData || { - entityType: this.options.entityType || null, - create: 'create', - headerRow: true, - delimiter: ',', - textQualifier: '"', - dateFormat: 'YYYY-MM-DD', - timeFormat: 'HH:mm:ss', - currency: this.getConfig().get('defaultCurrency'), - timezone: 'UTC', - decimalMark: '.', - personNameFormat: 'f l', - idleMode: false, - skipDuplicateChecking: false, - silentMode: true, - manualMode: false, - }; - - var defaults = Espo.Utils.cloneDeep( - (this.getPreferences().get('importParams') || {}).default || {} - ); - - if (!this.options.formData) { - for (var p in defaults) { - this.formData[p] = defaults[p]; + for (let scopeName in scopes) { + if (scopes[scopeName].importable) { + if (!this.getAcl().checkScope(scopeName, 'create')) { + continue; } + + list.push(scopeName); } + } - var model = this.model = new Model; + list.sort((v1, v2) => { + return this.translate(v1, 'scopeNamesPlural') + .localeCompare(this.translate(v2, 'scopeNamesPlural')); + }); - this.attributeList.forEach(function (a) { - model.set(a, this.formData[a]); - }, this); + return list; + } - this.attributeList.forEach(function (a) { - this.listenTo(model, 'change:' + a, function (m, v, o) { - if (!o.ui) return; - this.formData[a] = this.model.get(a); - this.preview(); - }, this); - }, this); + data() { + return { + entityList: this.getEntityList(), + }; + } - var personNameFormatList = [ - 'f l', - 'l f', - 'l, f', - ]; - var personNameFormat = this.getConfig().get('personNameFormat') || 'firstLast'; - if (~personNameFormat.toString().toLowerCase().indexOf('middle')) { - personNameFormatList.push('f m l'); - personNameFormatList.push('l f m'); + setup() { + this.attributeList = [ + 'entityType', + 'action', + ]; + + this.paramList = [ + 'headerRow', + 'decimalMark', + 'personNameFormat', + 'delimiter', + 'dateFormat', + 'timeFormat', + 'currency', + 'timezone', + 'textQualifier', + 'silentMode', + 'idleMode', + 'skipDuplicateChecking', + 'manualMode', + ]; + + this.paramList.forEach(item => { + this.attributeList.push(item); + }); + + this.formData = this.options.formData || { + entityType: this.options.entityType || null, + create: 'create', + headerRow: true, + delimiter: ',', + textQualifier: '"', + dateFormat: 'YYYY-MM-DD', + timeFormat: 'HH:mm:ss', + currency: this.getConfig().get('defaultCurrency'), + timezone: 'UTC', + decimalMark: '.', + personNameFormat: 'f l', + idleMode: false, + skipDuplicateChecking: false, + silentMode: true, + manualMode: false, + }; + + let defaults = Espo.Utils.cloneDeep( + (this.getPreferences().get('importParams') || {}).default || {} + ); + + if (!this.options.formData) { + for (let p in defaults) { + this.formData[p] = defaults[p]; } + } - var dateFormatDataList = this.getDateFormatDataList(); + let model = this.model = new Model; - var timeFormatDataList = this.getTimeFormatDataList(); + this.attributeList.forEach(a => { + model.set(a, this.formData[a]); + }); - var dateFormatList = []; - var dateFormatOptions = {}; - - dateFormatDataList.forEach(function (item) { - dateFormatList.push(item.key); - dateFormatOptions[item.key] = item.label; - }, this); - - var timeFormatList = []; - var timeFormatOptions = {}; - - timeFormatDataList.forEach(function (item) { - timeFormatList.push(item.key); - timeFormatOptions[item.key] = item.label; - }, this); - - this.createView('actionField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="action"]', - model: this.model, - name: 'action', - mode: 'edit', - params: { - options: [ - 'create', - 'createAndUpdate', - 'update', - ], - translatedOptions: { - create: this.translate('Create Only', 'labels', 'Admin'), - createAndUpdate: this.translate('Create and Update', 'labels', 'Admin'), - update: this.translate('Update Only', 'labels', 'Admin'), - }, - }, - }); - - this.createView('entityTypeField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="entityType"]', - model: this.model, - name: 'entityType', - mode: 'edit', - params: { - options: [''].concat(this.getEntityList()), - translation: 'Global.scopeNamesPlural', - required: true, - }, - labelText: this.translate('Entity Type', 'labels', 'Import'), - }); - - this.createView('decimalMarkField', 'views/fields/varchar', { - el: this.getSelector() + ' .field[data-name="decimalMark"]', - model: this.model, - name: 'decimalMark', - mode: 'edit', - params: { - options: [ - '.', - ',', - ], - maxLength: 1, - required: true, - }, - labelText: this.translate('Decimal Mark', 'labels', 'Import'), - }); - this.createView('personNameFormatField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="personNameFormat"]', - model: this.model, - name: 'personNameFormat', - mode: 'edit', - params: { - options: personNameFormatList, - translation: 'Import.options.personNameFormat', - }, - }); - this.createView('delimiterField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="delimiter"]', - model: this.model, - name: 'delimiter', - mode: 'edit', - params: { - options: [ - ',', - ';', - '\\t', - '|', - ], - }, - }); - this.createView('textQualifierField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="textQualifier"]', - model: this.model, - name: 'textQualifier', - mode: 'edit', - params: { - options: ['"', '\''], - translatedOptions: { - '"': this.translate('Double Quote', 'labels', 'Import'), - '\'': this.translate('Single Quote', 'labels', 'Import'), - }, - }, - }); - this.createView('dateFormatField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="dateFormat"]', - model: this.model, - name: 'dateFormat', - mode: 'edit', - params: { - options: dateFormatList, - translatedOptions: dateFormatOptions, - }, - }); - this.createView('timeFormatField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="timeFormat"]', - model: this.model, - name: 'timeFormat', - mode: 'edit', - params: { - options: timeFormatList, - translatedOptions: timeFormatOptions, - }, - }); - this.createView('currencyField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="currency"]', - model: this.model, - name: 'currency', - mode: 'edit', - params: { - options: this.getConfig().get('currencyList'), - }, - }); - this.createView('timezoneField', 'views/fields/enum', { - el: this.getSelector() + ' .field[data-name="timezone"]', - model: this.model, - name: 'timezone', - mode: 'edit', - params: { - options: this.getMetadata().get(['entityDefs', 'Settings', 'fields', 'timeZone', 'options']), - }, - }); - this.createView('headerRowField', 'views/fields/bool', { - el: this.getSelector() + ' .field[data-name="headerRow"]', - model: this.model, - name: 'headerRow', - mode: 'edit', - }); - this.createView('silentModeField', 'views/fields/bool', { - el: this.getSelector() + ' .field[data-name="silentMode"]', - model: this.model, - name: 'silentMode', - mode: 'edit', - tooltip: true, - tooltipText: this.translate('silentMode', 'tooltips', 'Import'), - }); - this.createView('idleModeField', 'views/fields/bool', { - el: this.getSelector() + ' .field[data-name="idleMode"]', - model: this.model, - name: 'idleMode', - mode: 'edit', - }); - this.createView('skipDuplicateCheckingField', 'views/fields/bool', { - el: this.getSelector() + ' .field[data-name="skipDuplicateChecking"]', - model: this.model, - name: 'skipDuplicateChecking', - mode: 'edit', - }); - this.createView('manualModeField', 'views/fields/bool', { - el: this.getSelector() + ' .field[data-name="manualMode"]', - model: this.model, - name: 'manualMode', - mode: 'edit', - tooltip: true, - tooltipText: this.translate('manualMode', 'tooltips', 'Import'), - }); - - this.listenTo(this.model, 'change', function (m, o) { - if (!o.ui) return; - - var isParamChanged = false; - this.paramList.forEach(function (a) { - if (m.hasChanged(a)) { - isParamChanged = true; - } - }, this); - - if (isParamChanged) { - this.showSaveAsDefaultButton(); - } - }, this); - - this.listenTo(this.model, 'change', function (m, o) { - if (this.isRendered()) { - this.controlFieldVisibility(); - } - }, this); - - this.listenTo(this.model, 'change:entityType', function () { - delete this.formData.defaultFieldList; - delete this.formData.defaultValues; - delete this.formData.attributeList; - delete this.formData.updateBy; - }, this); - - this.listenTo(this.model, 'change:action', function () { - delete this.formData.updateBy; - }, this); - - this.listenTo(this.model, 'change', function (m, o) { - if (!o.ui) return; - - this.getRouter().confirmLeaveOut = true; - }, this); - }, - - afterRender: function () { - this.setupFormData(); - if (this.getParentView() && this.getParentView().fileContents) { - this.setFileIsLoaded(); - this.preview(); - } - this.controlFieldVisibility(); - }, - - showSaveAsDefaultButton: function () { - this.$el.find('[data-action="saveAsDefault"]').removeClass('hidden'); - }, - - hideSaveAsDefaultButton: function () { - this.$el.find('[data-action="saveAsDefault"]').addClass('hidden'); - }, - - next: function () { - this.attributeList.forEach(function (a) { - this.getView(a + 'Field').fetchToModel(); - this.formData[a] = this.model.get(a); - }, this); - - var isInvalid = false; - this.attributeList.forEach(function (a) { - isInvalid |= this.getView(a + 'Field').validate(); - }, this); - - if (isInvalid) { - Espo.Ui.error(this.translate('Not valid')); - return; - } - - this.getParentView().formData = this.formData; - - this.getParentView().trigger('change'); - - this.getParentView().changeStep(2); - }, - - setupFormData: function () { - this.attributeList.forEach(function (a) { - this.model.set(a, this.formData[a]); - }, this); - }, - - loadFile: function (file) { - var blob = file.slice(0, 1024 * 16); - - var readerPreview = new FileReader(); - readerPreview.onloadend = function (e) { - if (e.target.readyState == FileReader.DONE) { - this.formData.previewString = e.target.result; - this.preview(); - } - }.bind(this); - readerPreview.readAsText(blob); - - var reader = new FileReader(); - reader.onloadend = function (e) { - if (e.target.readyState == FileReader.DONE) { - this.getParentView().fileContents = e.target.result; - this.setFileIsLoaded(); - - this.getRouter().confirmLeaveOut = true; - } - }.bind(this); - reader.readAsText(file); - }, - - setFileIsLoaded: function () { - this.$el.find('button[data-action="next"]').removeClass('hidden'); - }, - - preview: function () { - if (!this.formData.previewString) { - return; - } - var arr = this.csvToArray(this.formData.previewString, this.formData.delimiter, this.formData.textQualifier); - - this.formData.previewArray = arr; - - var $table = $('').addClass('table').addClass('table-bordered'); - - var $tbody = $('').appendTo($table); - - arr.forEach((row, i) => { - if (i >= 3) { + this.attributeList.forEach(a => { + this.listenTo(model, 'change:' + a, (m, v, o) => { + if (!o.ui) { return; } - let $row = $(''); + this.formData[a] = this.model.get(a); - row.forEach((value) => { - let $cell = $('
').html(this.getHelper().sanitizeHtml(value)); + this.preview(); + }); + }); - $row.append($cell); - }); + let personNameFormatList = [ + 'f l', + 'l f', + 'l, f', + ]; - $tbody.append($row); + let personNameFormat = this.getConfig().get('personNameFormat') || 'firstLast'; + + if (~personNameFormat.toString().toLowerCase().indexOf('middle')) { + personNameFormatList.push('f m l'); + personNameFormatList.push('l f m'); + } + + let dateFormatDataList = this.getDateFormatDataList(); + let timeFormatDataList = this.getTimeFormatDataList(); + + let dateFormatList = []; + let dateFormatOptions = {}; + + dateFormatDataList.forEach(item => { + dateFormatList.push(item.key); + + dateFormatOptions[item.key] = item.label; + }); + + let timeFormatList = []; + let timeFormatOptions = {}; + + timeFormatDataList.forEach(item => { + timeFormatList.push(item.key); + + timeFormatOptions[item.key] = item.label; + }); + + this.createView('actionField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="action"]', + model: this.model, + name: 'action', + mode: 'edit', + params: { + options: [ + 'create', + 'createAndUpdate', + 'update', + ], + translatedOptions: { + create: this.translate('Create Only', 'labels', 'Admin'), + createAndUpdate: this.translate('Create and Update', 'labels', 'Admin'), + update: this.translate('Update Only', 'labels', 'Admin'), + }, + }, + }); + + this.createView('entityTypeField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="entityType"]', + model: this.model, + name: 'entityType', + mode: 'edit', + params: { + options: [''].concat(this.getEntityList()), + translation: 'Global.scopeNamesPlural', + required: true, + }, + labelText: this.translate('Entity Type', 'labels', 'Import'), + }); + + this.createView('decimalMarkField', 'views/fields/varchar', { + el: this.getSelector() + ' .field[data-name="decimalMark"]', + model: this.model, + name: 'decimalMark', + mode: 'edit', + params: { + options: [ + '.', + ',', + ], + maxLength: 1, + required: true, + }, + labelText: this.translate('Decimal Mark', 'labels', 'Import'), + }); + + this.createView('personNameFormatField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="personNameFormat"]', + model: this.model, + name: 'personNameFormat', + mode: 'edit', + params: { + options: personNameFormatList, + translation: 'Import.options.personNameFormat', + }, + }); + + this.createView('delimiterField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="delimiter"]', + model: this.model, + name: 'delimiter', + mode: 'edit', + params: { + options: [ + ',', + ';', + '\\t', + '|', + ], + }, + }); + + this.createView('textQualifierField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="textQualifier"]', + model: this.model, + name: 'textQualifier', + mode: 'edit', + params: { + options: ['"', '\''], + translatedOptions: { + '"': this.translate('Double Quote', 'labels', 'Import'), + '\'': this.translate('Single Quote', 'labels', 'Import'), + }, + }, + }); + + this.createView('dateFormatField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="dateFormat"]', + model: this.model, + name: 'dateFormat', + mode: 'edit', + params: { + options: dateFormatList, + translatedOptions: dateFormatOptions, + }, + }); + + this.createView('timeFormatField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="timeFormat"]', + model: this.model, + name: 'timeFormat', + mode: 'edit', + params: { + options: timeFormatList, + translatedOptions: timeFormatOptions, + }, + }); + + this.createView('currencyField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="currency"]', + model: this.model, + name: 'currency', + mode: 'edit', + params: { + options: this.getConfig().get('currencyList'), + }, + }); + + this.createView('timezoneField', 'views/fields/enum', { + el: this.getSelector() + ' .field[data-name="timezone"]', + model: this.model, + name: 'timezone', + mode: 'edit', + params: { + options: this.getMetadata().get(['entityDefs', 'Settings', 'fields', 'timeZone', 'options']), + }, + }); + + this.createView('headerRowField', 'views/fields/bool', { + el: this.getSelector() + ' .field[data-name="headerRow"]', + model: this.model, + name: 'headerRow', + mode: 'edit', + }); + + this.createView('silentModeField', 'views/fields/bool', { + el: this.getSelector() + ' .field[data-name="silentMode"]', + model: this.model, + name: 'silentMode', + mode: 'edit', + tooltip: true, + tooltipText: this.translate('silentMode', 'tooltips', 'Import'), + }); + + this.createView('idleModeField', 'views/fields/bool', { + el: this.getSelector() + ' .field[data-name="idleMode"]', + model: this.model, + name: 'idleMode', + mode: 'edit', + }); + + this.createView('skipDuplicateCheckingField', 'views/fields/bool', { + el: this.getSelector() + ' .field[data-name="skipDuplicateChecking"]', + model: this.model, + name: 'skipDuplicateChecking', + mode: 'edit', + }); + + this.createView('manualModeField', 'views/fields/bool', { + el: this.getSelector() + ' .field[data-name="manualMode"]', + model: this.model, + name: 'manualMode', + mode: 'edit', + tooltip: true, + tooltipText: this.translate('manualMode', 'tooltips', 'Import'), + }); + + this.listenTo(this.model, 'change', (m, o) => { + if (!o.ui) { + return; + } + + let isParamChanged = false; + + this.paramList.forEach(a => { + if (m.hasChanged(a)) { + isParamChanged = true; + } }); - var $container = $('#import-preview'); + if (isParamChanged) { + this.showSaveAsDefaultButton(); + } + }); - $container.empty().append($table); - }, + this.listenTo(this.model, 'change', () => { + if (this.isRendered()) { + this.controlFieldVisibility(); + } + }); - csvToArray: function (strData, strDelimiter, strQualifier) { - strDelimiter = (strDelimiter || ','); - strQualifier = (strQualifier || '\"'); + this.listenTo(this.model, 'change:entityType', () => { + delete this.formData.defaultFieldList; + delete this.formData.defaultValues; + delete this.formData.attributeList; + delete this.formData.updateBy; + }); - strDelimiter = strDelimiter.replace(/\\t/, '\t'); + this.listenTo(this.model, 'change:action', () => { + delete this.formData.updateBy; + }); - var objPattern = new RegExp( - ( - // Delimiters. - "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + - - // Quoted fields. - "(?:"+strQualifier+"([^"+strQualifier+"]*(?:"+strQualifier+""+strQualifier+ - "[^"+strQualifier+"]*)*)"+strQualifier+"|" + - - // Standard fields. - "([^"+strQualifier+"\\" + strDelimiter + "\\r\\n]*))" - ), - "gi" - ); - - var arrData = [[]]; - var arrMatches = null; - - while (arrMatches = objPattern.exec(strData)) { - var strMatchedDelimiter = arrMatches[1]; - - if ( - strMatchedDelimiter.length && - (strMatchedDelimiter != strDelimiter) - ) { - arrData.push([]); - } - - if (arrMatches[2]) { - var strMatchedValue = arrMatches[2].replace( - new RegExp( "\"\"", "g" ), - "\"" - ); - } else { - var strMatchedValue = arrMatches[3]; - } - - arrData[arrData.length - 1].push(strMatchedValue); + this.listenTo(this.model, 'change', (m, o) => { + if (!o.ui) { + return; } - return arrData; - }, + this.getRouter().confirmLeaveOut = true; + }); + } - saveAsDefault: function () { - var preferences = this.getPreferences(); + afterRender() { + this.setupFormData(); - var importParams = Espo.Utils.cloneDeep(preferences.get('importParams') || {}); + if (this.getParentIndexView() && this.getParentIndexView().fileContents) { + this.setFileIsLoaded(); + this.preview(); + } - var data = {}; + this.controlFieldVisibility(); + } - this.paramList.forEach(function (a) { - data[a] = this.model.get(a); - }, this); + getParentIndexView() { + return this.getParentView(); + } - importParams.default = data; + showSaveAsDefaultButton() { + this.$el.find('[data-action="saveAsDefault"]').removeClass('hidden'); + } - preferences.save({ - 'importParams': importParams, - }).then( - function () { - Espo.Ui.success(this.translate('Saved')) - }.bind(this) - ); + hideSaveAsDefaultButton() { + this.$el.find('[data-action="saveAsDefault"]').addClass('hidden'); + } - this.hideSaveAsDefaultButton(); - }, + /** + * @return {module:views/fields/base} + */ + getFieldView(field) { + return this.getView(field + 'Field'); + } - controlFieldVisibility: function () { - if (this.model.get('idleMode')) { - this.hideField('manualMode'); + next() { + this.attributeList.forEach(field => { + this.getFieldView(field).fetchToModel(); + + this.formData[field] = this.model.get(field); + }); + + let isInvalid = false; + + this.attributeList.forEach(field => { + isInvalid |= this.getFieldView(field).validate(); + }); + + if (isInvalid) { + Espo.Ui.error(this.translate('Not valid')); + + return; + } + + this.getParentIndexView().formData = this.formData; + this.getParentIndexView().trigger('change'); + this.getParentIndexView().changeStep(2); + } + + setupFormData() { + this.attributeList.forEach(field => { + this.model.set(field, this.formData[field]); + }); + } + + loadFile(file) { + let blob = file.slice(0, 1024 * 16); + + let readerPreview = new FileReader(); + + readerPreview.onloadend = e => { + if (e.target.readyState === FileReader.DONE) { + this.formData.previewString = e.target.result; + + this.preview(); + } + }; + + readerPreview.readAsText(blob); + + let reader = new FileReader(); + + reader.onloadend = e => { + if (e.target.readyState === FileReader.DONE) { + this.getParentIndexView().fileContents = e.target.result; + + this.setFileIsLoaded(); + + this.getRouter().confirmLeaveOut = true; + } + }; + + reader.readAsText(file); + } + + setFileIsLoaded() { + this.$el.find('button[data-action="next"]').removeClass('hidden'); + } + + preview() { + if (!this.formData.previewString) { + return; + } + + let arr = this.csvToArray( + this.formData.previewString, + this.formData.delimiter, + this.formData.textQualifier + ); + + this.formData.previewArray = arr; + + let $table = $('').addClass('table').addClass('table-bordered'); + let $tbody = $('').appendTo($table); + + arr.forEach((row, i) => { + if (i >= 3) { + return; + } + + let $row = $(''); + + row.forEach((value) => { + let $cell = $('
').html(this.getHelper().sanitizeHtml(value)); + + $row.append($cell); + }); + + $tbody.append($row); + }); + + let $container = $('#import-preview'); + + $container.empty().append($table); + } + + csvToArray(strData, strDelimiter, strQualifier) { + strDelimiter = (strDelimiter || ','); + strQualifier = (strQualifier || '\"'); + + strDelimiter = strDelimiter.replace(/\\t/, '\t'); + + let objPattern = new RegExp( + ( + // Delimiters. + "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + + + // Quoted fields. + "(?:"+strQualifier+"([^"+strQualifier+"]*(?:"+strQualifier+""+strQualifier+ + "[^"+strQualifier+"]*)*)"+strQualifier+"|" + + + // Standard fields. + "([^"+strQualifier+"\\" + strDelimiter + "\\r\\n]*))" + ), + "gi" + ); + + let arrData = [[]]; + let arrMatches = null; + + while (arrMatches = objPattern.exec(strData)) { + let strMatchedDelimiter = arrMatches[1]; + let strMatchedValue; + + if ( + strMatchedDelimiter.length && + (strMatchedDelimiter !== strDelimiter) + ) { + arrData.push([]); + } + + if (arrMatches[2]) { + strMatchedValue = arrMatches[2].replace(new RegExp( "\"\"", "g" ), "\""); } else { - this.showField('manualMode'); + strMatchedValue = arrMatches[3]; } - if (this.model.get('manualMode')) { - this.hideField('idleMode'); - } else { - this.showField('idleMode'); - } - }, + arrData[arrData.length - 1].push(strMatchedValue); + } - hideField: function (name) { - this.$el.find('.field[data-name="'+name+'"]').parent().addClass('hidden-cell'); - }, + return arrData; + } - showField: function (name) { - this.$el.find('.field[data-name="'+name+'"]').parent().removeClass('hidden-cell'); - }, + saveAsDefault() { + let preferences = this.getPreferences(); - convertFormatToLabel: function (format) { - var formatItemLabelMap = { - 'YYYY': '2021', - 'DD': '27', - 'MM': '12', - 'HH': '23', - 'mm': '00', - 'hh': '11', - 'ss': '00', - 'a': 'pm', - 'A': 'PM', + let importParams = Espo.Utils.cloneDeep(preferences.get('importParams') || {}); + + let data = {}; + + this.paramList.forEach(attribute => { + data[attribute] = this.model.get(attribute); + }); + + importParams.default = data; + + preferences.save({importParams: importParams}) + .then(() => { + Espo.Ui.success(this.translate('Saved')) + }); + + this.hideSaveAsDefaultButton(); + } + + controlFieldVisibility() { + if (this.model.get('idleMode')) { + this.hideField('manualMode'); + } else { + this.showField('manualMode'); + } + + if (this.model.get('manualMode')) { + this.hideField('idleMode'); + } else { + this.showField('idleMode'); + } + } + + hideField(name) { + this.$el.find('.field[data-name="'+name+'"]').parent().addClass('hidden-cell'); + } + + showField(name) { + this.$el.find('.field[data-name="'+name+'"]').parent().removeClass('hidden-cell'); + } + + convertFormatToLabel(format) { + let formatItemLabelMap = { + 'YYYY': '2021', + 'DD': '27', + 'MM': '12', + 'HH': '23', + 'mm': '00', + 'hh': '11', + 'ss': '00', + 'a': 'pm', + 'A': 'PM', + }; + + let label = format; + + for (let item in formatItemLabelMap) { + let value = formatItemLabelMap[item]; + + label = label.replace(new RegExp(item, 'g'), value); + } + + return format + ' - ' + label; + } + + getDateFormatDataList() { + let dateFormatList = this.getMetadata().get(['clientDefs', 'Import', 'dateFormatList']) || []; + + return dateFormatList.map(item => { + return { + key: item, + label: this.convertFormatToLabel(item), }; + }); + } - var label = format; + getTimeFormatDataList() { + let timeFormatList = this.getMetadata().get(['clientDefs', 'Import', 'timeFormatList']) || []; - for (let item in formatItemLabelMap) { - var value = formatItemLabelMap[item]; + return timeFormatList.map(item => { + return { + key: item, + label: this.convertFormatToLabel(item), + }; + }); + } +} - label = label.replace(new RegExp(item, 'g'), value); - } - - return format + ' - ' + label; - }, - - getDateFormatDataList: function () { - var dateFormatList = this.getMetadata().get(['clientDefs', 'Import', 'dateFormatList']) || []; - - return dateFormatList.map( - function (item) { - return { - key: item, - label: this.convertFormatToLabel(item), - }; - }.bind(this) - ); - }, - - getTimeFormatDataList: function () { - var timeFormatList = this.getMetadata().get(['clientDefs', 'Import', 'timeFormatList']) || []; - - return timeFormatList.map( - function (item) { - return { - key: item, - label: this.convertFormatToLabel(item), - }; - }.bind(this) - ); - }, - - }); -}); +export default Step1ImportView;