From ccc339cf483af0a3a2bbb47efeadfb189566bbcd Mon Sep 17 00:00:00 2001 From: yuri Date: Thu, 26 Mar 2015 17:23:26 +0200 Subject: [PATCH] import 1 --- application/Espo/Controllers/Import.php | 53 ++++-- .../Database/Schema/tables/importEntity.php | 67 ++++++++ application/Espo/Entities/Import.php | 28 +++ .../Espo/Resources/i18n/en_US/Global.json | 6 +- .../Resources/metadata/clientDefs/Import.json | 11 ++ .../Resources/metadata/entityDefs/Import.json | 26 +++ .../Resources/metadata/scopes/Import.json | 7 + application/Espo/Services/Import.php | 83 ++++++--- .../client/res/templates/import/index.tpl | 16 +- frontend/client/src/controllers/import.js | 24 +-- frontend/client/src/views/import/index.js | 26 +-- frontend/client/src/views/import/list.js | 57 +++++++ .../client/src/views/import/record/detail.js | 31 ++++ .../client/src/views/import/record/list.js | 36 ++++ frontend/client/src/views/import/step1.js | 86 +++++----- frontend/client/src/views/import/step2.js | 159 +++++++++--------- .../views/record/row-actions/remove-only.js | 53 ++++++ 17 files changed, 571 insertions(+), 198 deletions(-) create mode 100644 application/Espo/Core/Utils/Database/Schema/tables/importEntity.php create mode 100644 application/Espo/Entities/Import.php create mode 100644 application/Espo/Resources/metadata/clientDefs/Import.json create mode 100644 application/Espo/Resources/metadata/entityDefs/Import.json create mode 100644 application/Espo/Resources/metadata/scopes/Import.json create mode 100644 frontend/client/src/views/import/list.js create mode 100644 frontend/client/src/views/import/record/detail.js create mode 100644 frontend/client/src/views/import/record/list.js create mode 100644 frontend/client/src/views/record/row-actions/remove-only.js diff --git a/application/Espo/Controllers/Import.php b/application/Espo/Controllers/Import.php index 9e631c9920..2bdee9852a 100644 --- a/application/Espo/Controllers/Import.php +++ b/application/Espo/Controllers/Import.php @@ -18,50 +18,67 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ + ************************************************************************/ namespace Espo\Controllers; use Espo\Core\Utils as Utils; use \Espo\Core\Exceptions\Error; use \Espo\Core\Exceptions\Forbidden; +use \Espo\Core\Exceptions\BadRequest; + +class Import extends \Espo\Core\Controllers\Record +{ + protected function checkControllerAccess() + { + if (!$this->getUser()->isAdmin()) { + throw new Forbidden(); + } + } + + public function actionPatch($params, $data) + { + throw new BadRequest(); + } + + public function actionUpdate($params, $data) + { + throw new BadRequest(); + } -class Import extends \Espo\Core\Controllers\Base -{ - protected function getFileManager() { return $this->getContainer()->get('fileManager'); } - + protected function getEntityManager() { return $this->getContainer()->get('entityManager'); } - + public function actionUploadFile($params, $data) - { + { $contents = $data; - + $attachment = $this->getEntityManager()->getEntity('Attachment'); $attachment->set('type', 'text/csv'); - $attachment->set('role', 'Import File'); + $attachment->set('role', 'Import File'); $this->getEntityManager()->saveEntity($attachment); - + $this->getFileManager()->putContents('data/upload/' . $attachment->id, $contents); - + return array( 'attachmentId' => $attachment->id ); } - + public function actionRevert($params, $data) - { + { return $this->getService('Import')->revert($data['entityType'], $data['idsToRemove']); } - + public function actionCreate($params, $data) - { + { $importParams = array( 'headerRow' => $data['headerRow'], 'fieldDelimiter' => $data['fieldDelimiter'], @@ -74,13 +91,13 @@ class Import extends \Espo\Core\Controllers\Base 'defaultValues' => $data['defaultValues'], 'action' => $data['action'], ); - + $attachmentId = $data['attachmentId']; - + if (!$this->getAcl()->check($data['entityType'], 'edit')) { throw new Forbidden(); } - + return $this->getService('Import')->import($data['entityType'], $data['fields'], $attachmentId, $importParams); } } diff --git a/application/Espo/Core/Utils/Database/Schema/tables/importEntity.php b/application/Espo/Core/Utils/Database/Schema/tables/importEntity.php new file mode 100644 index 0000000000..bbb8f18bb9 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Schema/tables/importEntity.php @@ -0,0 +1,67 @@ + array( + 'fields' => array( + 'id' => array( + 'type' => 'id', + 'dbType' => 'int', + 'len' => '11', + 'autoincrement' => true, + 'unique' => true + ), + 'entityId' => array( + 'type' => 'varchar', + 'len' => '24', + 'index' => 'entity' + ), + 'entityType' => array( + 'type' => 'varchar', + 'len' => '100', + 'index' => 'entity' + ), + 'importId' => array( + 'type' => 'varchar', + 'len' => '24', + 'index' => true + ), + 'isImported' => array( + 'type' => 'bool' + ), + 'isUpdated' => array( + 'type' => 'bool' + ), + 'isDuplicate' => array( + 'type' => 'bool' + ), + ), + "indexes" => array( + "entityImport" => array( + "columns" => ["importId", "entityType"] + ) + ) + ), + +); + diff --git a/application/Espo/Entities/Import.php b/application/Espo/Entities/Import.php new file mode 100644 index 0000000000..4be15c6b48 --- /dev/null +++ b/application/Espo/Entities/Import.php @@ -0,0 +1,28 @@ +dependencies[] = 'serviceFactory'; + $this->dependencies[] = 'fileManager'; + $this->dependencies[] = 'selectManagerFactory'; + } protected $dateFormatsMap = array( 'YYYY-MM-DD' => 'Y-m-d', @@ -60,6 +56,8 @@ class Import extends \Espo\Core\Services\Base 'hh:mmA' => 'h:iA', ); + protected $services = array(); + protected function getSelectManagerFactory() { return $this->injections['selectManagerFactory']; @@ -85,7 +83,6 @@ class Import extends \Espo\Core\Services\Base return $this->injections['serviceFactory']; } - protected function readCsvString(&$string, $CSV_SEPARATOR = ';', $CSV_ENCLOSURE = '"', $CSV_LINEBREAK = "\n") { $o = array(); @@ -174,12 +171,20 @@ class Import extends \Espo\Core\Services\Base } $contents = $this->getFileManager()->getContents('data/upload/' . $attachmentId); - if (empty($contents)) { throw new Error('Import error'); } - $result = array( + $import = $this->getEntityManager()->getEntity('Import'); + $import->set(array( + 'enityType' => $scope + )); + $this->getEntityManager()->saveEntity($import); + + $pdo = $this->getEntityManager()->getPDO(); + + + $result = array( 'importedIds' => array(), 'updatedIds' => array(), 'duplicateIds' => array(), @@ -194,22 +199,36 @@ class Import extends \Espo\Core\Services\Base continue; } $r = $this->importRow($scope, $fields, $arr, $params); - if (!empty($r['imported'])) { + if (!empty($r['isImported'])) { $result['importedIds'][] = $r['id']; } - if (!empty($r['updated'])) { + if (!empty($r['isUpdated'])) { $result['updatedIds'][] = $r['id']; } - if (!empty($r['duplicate'])) { + if (!empty($r['isDuplicate'])) { $result['duplicateIds'][] = $r['id']; } + $sql = " + INSERT INTO import_entity (entity_type, entity_id, import_id, is_imported, is_updated, is_duplicate) + (:entityType, :entityId, :importId, :isImported, :isUpdated, :isDuplicate) + "; + $sth = $pdo->prepare($sql); + $sth->execute(array( + ':entityType' => $scope, + ':entityId' => $r['id'], + ':importId' => $import->id, + ':isImported' => !empty($r['isImported']), + ':isUpdated' => !empty($r['isUpdated']), + ':isDuplicate' => !empty($r['isDuplicate']), + )); } return array( + 'id' => $import->id, 'countCreated' => count($result['importedIds']), 'countUpdated' => count($result['updatedIds']), - 'importedIds' => $result['importedIds'], - 'duplicateIds' => $result['duplicateIds'], + //'importedIds' => $result['importedIds'], + //'duplicateIds' => $result['duplicateIds'], ); } @@ -229,6 +248,7 @@ class Import extends \Espo\Core\Services\Base } } + $recordService = $this->getRecordService($scope); $entity = $this->getEntityManager()->getEntity($scope, $id); @@ -260,7 +280,6 @@ class Import extends \Espo\Core\Services\Base $firstName = ''; $lastName = $value; switch ($params['personNameFormat']) { - case 'f l': $pos = strpos($value, ' '); if ($pos) { @@ -298,8 +317,6 @@ class Import extends \Espo\Core\Services\Base } } - - foreach ($fields as $i => $field) { if (array_key_exists($field, $fieldsDefs) && $fieldsDefs[$field]['type'] == Entity::FOREIGN) { if ($entity->has($field)) { @@ -314,7 +331,6 @@ class Import extends \Espo\Core\Services\Base $entity->set($relation . 'Id', $found->id); } else { if (!in_array($scope, 'User', 'Team')) { - // TODO create related record with name $name and relate } } @@ -330,15 +346,21 @@ class Import extends \Espo\Core\Services\Base $a = $entity->toArray(); try { + $isDuplicate = $recordService->checkEntityForDuplicate($entity); if ($this->getEntityManager()->saveEntity($entity)) { $result['id'] = $entity->id; if (empty($id)) { - $result['imported'] = true; + $result['isImported'] = true; + if ($isDuplicate) { + $result['isDuplicate'] = true; + } } else { - $result['updated'] = true; + $result['isUpdated'] = true; } } - } catch (\Exception $e) {} + } catch (\Exception $e) { + $GLOBALS['log']->error('Import: [' . $e->getCode() . '] ' .$e->getMessage()); + } return $result; } @@ -401,9 +423,16 @@ class Import extends \Espo\Core\Services\Base } break; } - } return $value; } + + protected function getRecordService($scope) + { + if (empty($this->services[$scope])) { + $this->services[$scope] = $this->getServiceFactory()->create($scope); + } + return $this->services[$scope]; + } } diff --git a/frontend/client/res/templates/import/index.tpl b/frontend/client/res/templates/import/index.tpl index 8ce14a7965..e94e0800c8 100644 --- a/frontend/client/res/templates/import/index.tpl +++ b/frontend/client/res/templates/import/index.tpl @@ -1,9 +1,17 @@ - +
{{{step}}}
- - - diff --git a/frontend/client/src/controllers/import.js b/frontend/client/src/controllers/import.js index f658f69ee7..661a125004 100644 --- a/frontend/client/src/controllers/import.js +++ b/frontend/client/src/controllers/import.js @@ -17,22 +17,24 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ -Espo.define('Controllers.Import', 'Controller', function (Dep) { - - return Dep.extend({ - + ************************************************************************/ +Espo.define('Controllers.Import', 'Controllers.Record', function (Dep) { + + return Dep.extend({ + + defaultAction: 'index', + checkAccess: function () { if (this.getUser().isAdmin()) { return true; } return false; - }, - - index: function () { - this.main('Import.Index', null); }, - + + index: function () { + this.main('Import.Index', null); + } + }); - + }); diff --git a/frontend/client/src/views/import/index.js b/frontend/client/src/views/import/index.js index 4897584bcf..8688a6518e 100644 --- a/frontend/client/src/views/import/index.js +++ b/frontend/client/src/views/import/index.js @@ -17,27 +17,27 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ + ************************************************************************/ Espo.define('Views.Import.Index', 'View', function (Dep) { - + return Dep.extend({ - + template: 'import.index', - + data: function () { return { - + }; }, - + formData: null, - + fileContents: null, - + setup: function () { this.entityType = this.options.entityType || false; - }, - + }, + changeStep: function (num, result) { this.createView('step', 'Import.Step' + num.toString(), { el: this.options.el + ' > .import-container', @@ -48,14 +48,14 @@ Espo.define('Views.Import.Index', 'View', function (Dep) { view.render(); }); }, - + afterRender: function () { this.changeStep(1); }, - + updatePageTitle: function () { this.setPageTitle(this.getLanguage().translate('Import')); }, - + }); }); diff --git a/frontend/client/src/views/import/list.js b/frontend/client/src/views/import/list.js new file mode 100644 index 0000000000..02eaa38d48 --- /dev/null +++ b/frontend/client/src/views/import/list.js @@ -0,0 +1,57 @@ +/************************************************************************ + * This file is part of EspoCRM. + * + * EspoCRM - Open Source CRM application. + * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko + * Website: http://www.espocrm.com + * + * EspoCRM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EspoCRM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EspoCRM. If not, see http://www.gnu.org/licenses/. + ************************************************************************/ + +Espo.define('Views.Import.List', 'Views.List', function (Dep) { + + return Dep.extend({ + + createButton: false, + + setup: function () { + Dep.prototype.setup.call(this); + + this.menu.buttons.unshift({ + label: this.translate('Import', 'scopeNames'), + link: '#Import', + style: 'danger', + acl: 'edit' + }); + }, + + actionCreateEmailAccount: function () { + if (this.options.userId) { + this.getRouter().dispatch('EmailAccount', 'create', { + attributes: { + assignedUserId: this.options.userId, + assignedUserName: this.options.userId + } + }); + this.getRouter().navigate('#EmailAccount/create', {trigger: false}); + } else { + this.getRouter().navigate('#EmailAccount/create', {trigger: true}); + } + + }, + + + }); +}); + diff --git a/frontend/client/src/views/import/record/detail.js b/frontend/client/src/views/import/record/detail.js new file mode 100644 index 0000000000..86008c1ddd --- /dev/null +++ b/frontend/client/src/views/import/record/detail.js @@ -0,0 +1,31 @@ +/************************************************************************ + * This file is part of EspoCRM. + * + * EspoCRM - Open Source CRM application. + * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko + * Website: http://www.espocrm.com + * + * EspoCRM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EspoCRM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EspoCRM. If not, see http://www.gnu.org/licenses/. + ************************************************************************/ + +Espo.define('Views.Import.Record.Detail', 'Views.Record.Detail', function (Dep) { + + return Dep.extend({ + + readOnly: true + + }); + +}); + diff --git a/frontend/client/src/views/import/record/list.js b/frontend/client/src/views/import/record/list.js new file mode 100644 index 0000000000..56bec5072e --- /dev/null +++ b/frontend/client/src/views/import/record/list.js @@ -0,0 +1,36 @@ +/************************************************************************ + * This file is part of EspoCRM. + * + * EspoCRM - Open Source CRM application. + * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko + * Website: http://www.espocrm.com + * + * EspoCRM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EspoCRM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EspoCRM. If not, see http://www.gnu.org/licenses/. + ************************************************************************/ + +Espo.define('Views.Import.Record.List', 'Views.Record.List', function (Dep) { + + return Dep.extend({ + + allowQuickEdit: false, + + checkAllResultDisabled: true, + + massActionList: ['remove'], + + rowActionsView: 'Record.RowActions.RemoveOnly' + + }); +}); + diff --git a/frontend/client/src/views/import/step1.js b/frontend/client/src/views/import/step1.js index 20eecaa457..55e5a61b80 100644 --- a/frontend/client/src/views/import/step1.js +++ b/frontend/client/src/views/import/step1.js @@ -17,13 +17,13 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ + ************************************************************************/ Espo.define('Views.Import.Step1', 'View', function (Dep) { - + return Dep.extend({ - + template: 'import.step-1', - + events: { 'change #import-file': function (e) { var $file = $(e.currentTarget); @@ -32,25 +32,25 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { this.loadFile(files[0]); } }, - + 'change #import-field-delimiter': function (e) { this.formData.fieldDelimiter = e.currentTarget.value; this.preview(); }, - + 'change #import-text-qualifier': function (e) { this.formData.textQualifier = e.currentTarget.value; this.preview(); }, - + 'click button[data-action="next"]': function () { this.next(); } }, - + getEntityList: function () { var list = []; - var scopes = this.getMetadata().get('scopes'); + var scopes = this.getMetadata().get('scopes'); for (var scopeName in scopes) { if (scopes[scopeName].importable) { list.push(scopeName); @@ -61,15 +61,15 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { }.bind(this)); return list; }, - + data: function () { return { entityList: this.getEntityList(), currencyList: this.getConfig().get('currencyList'), }; }, - - setup: function () { + + setup: function () { this.formData = this.options.formData || { entityType: this.options.entityType || false, headerRow: true, @@ -79,9 +79,9 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { timeFormat: 'HH:mm', decimalMark: '.', personNameFormat: 'f l', - }; + }; }, - + afterRender: function () { this.setupFormData(); if (this.getParentView() && this.getParentView().fileContents) { @@ -89,7 +89,7 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { this.preview(); } }, - + next: function () { this.formData.headerRow = $('#import-header-row').get(0).checked; this.formData.entityType = $('#import-entity-type').val(); @@ -101,69 +101,69 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { this.formData.decimalMark = $('#import-decimal-mark').val(); this.formData.currency = $('#import-currency').val(); this.formData.personNameFormat = $('#import-person-name-format').val(); - + this.getParentView().formData = this.formData; this.getParentView().changeStep(2); }, - - setupFormData: function () { + + setupFormData: function () { $('#import-header-row').get(0).checked = this.formData.headerRow || false; - + if (this.formData.entityType) { $('#import-entity-type').val(this.formData.entityType); } if (this.formData.action) { $('#import-action').val(this.formData.action); } - + $('#import-field-delimiter').val(this.formData.fieldDelimiter); $('#import-text-qualifier').val(this.formData.textQualifier); $('#import-date-format').val(this.formData.dateFormat); $('#import-time-format').val(this.formData.timeFormat); $('#import-decimal-mark').val(this.formData.decimalMark); $('#import-person-name-format').val(this.formData.personNameFormat); - + if (this.formData.currency) { $('#import-currency').val(this.formData.currency); } }, - + loadFile: function (file) { var blob = file.slice(0, 1024 * 16); - - var readerPreview = new FileReader(); + + var readerPreview = new FileReader(); readerPreview.onloadend = function (e) { if (e.target.readyState == FileReader.DONE) { this.formData.previewString = e.target.result; this.preview(); - } - }.bind(this); + } + }.bind(this); readerPreview.readAsText(blob); - - var reader = new FileReader(); + + var reader = new FileReader(); reader.onloadend = function (e) { if (e.target.readyState == FileReader.DONE) { this.getParentView().fileContents = e.target.result; this.setFileIsLoaded(); - } - }.bind(this); - reader.readAsText(file); + } + }.bind(this); + reader.readAsText(file); }, - + setFileIsLoaded: function () { this.$el.find('button[data-action="next"]').removeClass('hidden'); }, - - preview: function () { + + preview: function () { if (!this.formData.previewString) { return; - } + } var arr = this.csvToArray(this.formData.previewString, this.formData.fieldDelimiter, this.formData.textQualifier); - + this.formData.previewArray = arr; - + var $table = $('').addClass('table').addClass('table-bordered'); - + arr.forEach(function (row, i) { if (i >= 3) { return; @@ -173,15 +173,15 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { $cell = $('
').html(value); $row.append($cell); }); - + $table.append($row); }); - + var $container = $('#import-preview'); $container.empty().append($table); }, - - csvToArray: function (strData, strDelimiter, strQualifier) { + + csvToArray: function (strData, strDelimiter, strQualifier) { strDelimiter = (strDelimiter || ','); strQualifier = (strQualifier || '\"'); @@ -226,6 +226,6 @@ Espo.define('Views.Import.Step1', 'View', function (Dep) { return arrData; } - + }); }); diff --git a/frontend/client/src/views/import/step2.js b/frontend/client/src/views/import/step2.js index 23cac11975..99d0593562 100644 --- a/frontend/client/src/views/import/step2.js +++ b/frontend/client/src/views/import/step2.js @@ -17,14 +17,14 @@ * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. - ************************************************************************/ + ************************************************************************/ Espo.define('Views.Import.Step2', 'View', function (Dep) { - + return Dep.extend({ - + template: 'import.step-2', - - events: { + + events: { 'click button[data-action="back"]': function () { this.back(); }, @@ -36,36 +36,36 @@ Espo.define('Views.Import.Step2', 'View', function (Dep) { $(e.currentTarget).parent().addClass('hidden'); this.addField(field); }, - + 'click a[data-action="removeField"]': function (e) { var field = $(e.currentTarget).data('name'); - - this.$el.find('a[data-action="addField"]').parent().removeClass('hidden'); - var index = this.additionalFields.indexOf(field); + this.$el.find('a[data-action="addField"]').parent().removeClass('hidden'); + + var index = this.additionalFields.indexOf(field); if (~index) { this.additionalFields.splice(index, 1); } this.$el.find('.field-' + field).parent().remove(); }, - }, - + }, + data: function () { return { scope: this.scope, fieldList: this.getFieldList(), }; }, - - setup: function () { + + setup: function () { this.formData = this.options.formData; - + this.scope = this.formData.entityType; - + var mapping = []; - + this.additionalFields = []; - + if (this.formData.previewArray) { var index = 0; if (this.formData.headerRow) { @@ -81,23 +81,23 @@ Espo.define('Views.Import.Step2', 'View', function (Dep) { } mapping.push(d); }, this); - } + } } - + this.wait(true); this.getModelFactory().create(this.scope, function (model) { this.model = model; - this.wait(false); + this.wait(false); }, this); - - this.mapping = mapping; + + this.mapping = mapping; }, - + afterRender: function () { $container = $('#mapping-container'); - + $table = $('').addClass('table').addClass('table-bordered'); - + $row = $(''); if (this.formData.headerRow) { $cell = $(''); if (this.formData.headerRow) { @@ -117,59 +117,59 @@ Espo.define('Views.Import.Step2', 'View', function (Dep) { } $select = this.getFieldDropdown(i, d.name); $cell = $('
').html(this.translate('Header Row Value', 'labels', 'Import')); @@ -108,7 +108,7 @@ Espo.define('Views.Import.Step2', 'View', function (Dep) { $cell = $('').html(this.translate('First Row Value', 'labels', 'Import')); $row.append($cell); $table.append($row); - + this.mapping.forEach(function (d, i) { $row = $('
').append($select); - $row.append($cell); - + $row.append($cell); + $cell = $('').html(d.value); $row.append($cell); - + $table.append($row); }, this); - + $container.empty(); $container.append($table); }, - + getFieldList: function () { var defs = this.getMetadata().get('entityDefs.' + this.scope + '.fields'); - + var fieldList = []; for (var field in defs) { fieldList.push(field); } - - return fieldList; + + return fieldList; }, - + getFieldDropdown: function (num, name) { name = name || false; - + var fields = this.getMetadata().get('entityDefs.' + this.scope + '.fields'); - + var fieldList = []; fieldList.push('id'); - + for (var field in fields) { var d = fields[field]; - + if (['modifiedBy', 'createdBy', 'modifiedAt', 'createdAt'].indexOf(field) !== -1) { continue; } - + if (d.type == 'link') { fieldList.push(field + 'Name'); fieldList.push(field + 'Id'); } - + if (['linkMultiple', 'foreign'].indexOf(d.type) !== -1) { continue; } - + if (d.type == 'personName') { fieldList.push(field); } - - var type = d.type; + + var type = d.type; var actualFields = this.getFieldManager().getActualAttributes(type, field); actualFields.forEach(function (f) { if (fieldList.indexOf(f) === -1) { @@ -177,14 +177,14 @@ Espo.define('Views.Import.Step2', 'View', function (Dep) { } }, this); } - + $select = $('