From 80cc8501125c2bbf19c52e5e5c23a3cd98585e8b Mon Sep 17 00:00:00 2001 From: acognet Date: Tue, 23 Mar 2021 11:23:55 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B03582=20-=20Migrate=20backoffice=20pages?= =?UTF-8?q?=20to=20new=20UIBlock=20system=20:=20Import=20CSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/csvbulkexport.class.inc.php | 8 +- core/excelbulkexport.class.inc.php | 26 +- core/pdfbulkexport.class.inc.php | 4 + core/spreadsheetbulkexport.class.inc.php | 25 +- core/xmlbulkexport.class.inc.php | 23 +- css/backoffice/components/_datatable.scss | 18 +- css/backoffice/components/input/_input.scss | 2 + css/backoffice/pages/_all.scss | 1 + css/backoffice/pages/_csv-import.scss | 45 + pages/ajax.csvimport.php | 558 ++++----- pages/csvimport.php | 1041 +++++++++-------- .../FieldBadge/FieldBadgeUIBlockFactory.php | 4 +- .../static/formtable/layout.ready.js.twig | 1 + .../static/formtablerow/layout.html.twig | 3 +- 14 files changed, 923 insertions(+), 836 deletions(-) create mode 100644 css/backoffice/pages/_csv-import.scss diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index bb9473fd2..1b1ff501e 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -141,7 +141,8 @@ class CSVBulkExport extends TabularBulkExport $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "separator", htmlentities($sVal, ENT_QUOTES, 'UTF-8'), $sLabel, "radio"); $oRadio->GetInput()->SetIsChecked(($sVal == $sRawSeparator)); $oRadio->SetBeforeInput(false); - $oRadio->AddCSSClass('ibo-input--label-right'); + $oRadio->GetInput()->AddCSSClass('ibo-input--label-right'); + $oRadio->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetSeparator->AddSubBlock($oRadio); $oFieldSetSeparator->AddSubBlock(new Html('
')); } @@ -168,6 +169,7 @@ class CSVBulkExport extends TabularBulkExport $oRadio->GetInput()->SetIsChecked(($sVal == $sRawSeparator)); $oRadio->SetBeforeInput(false); $oRadio->GetInput()->AddCSSClass('ibo-input--label-right'); + $oRadio->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetTextQualifier->AddSubBlock($oRadio); $oFieldSetTextQualifier->AddSubBlock(new Html('
')); } @@ -181,6 +183,7 @@ class CSVBulkExport extends TabularBulkExport $oCheckBox->GetInput()->SetIsChecked((utils::ReadParam('no_localize', 0) == 1)); $oCheckBox->SetBeforeInput(false); $oCheckBox->GetInput()->AddCSSClass('ibo-input--label-right'); + $oCheckBox->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetLocalization->AddSubBlock($oCheckBox); $oFieldSetLocalization->AddSubBlock(new Html('
')); @@ -201,6 +204,7 @@ class CSVBulkExport extends TabularBulkExport $oCheckBoxMarkup = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionFormattedText'), "formatted_text", "1", "csv_formatted_text", "checkbox"); $oCheckBoxMarkup->GetInput()->SetIsChecked((utils::ReadParam('formatted_text', 0) == 1)); $oCheckBoxMarkup->SetBeforeInput(false); + $oCheckBoxMarkup->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetMarkup->AddSubBlock($oCheckBoxMarkup); //date format @@ -215,6 +219,7 @@ class CSVBulkExport extends TabularBulkExport $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "csv_custom_date_time_format", "default", "csv_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); $oRadioDefault->SetBeforeInput(false); + $oRadioDefault->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); @@ -222,6 +227,7 @@ class CSVBulkExport extends TabularBulkExport $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "csv_custom_date_time_format", "custom", "csv_date_time_format_custom", "radio"); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); $oRadioCustom->SetBeforeInput(false); + $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); $sJSTooltip = json_encode('
'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'
'); diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index 5a1dc9a29..b09d627c4 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -1,25 +1,6 @@ - -/** - * Bulk export: Excel (xlsx) export - * - * @copyright Copyright (C) 2015-2021 Combodo SARL +/* + * @copyright Copyright (C) 2010-2021 Combodo SARL * @license http://opensource.org/licenses/AGPL-3.0 */ @@ -112,6 +93,7 @@ class ExcelBulkExport extends TabularBulkExport $oCheckBox = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionFormattedText'), "formatted_text", "1", "xlsx_formatted_text", "checkbox"); $oCheckBox->GetInput()->SetIsChecked((utils::ReadParam('formatted_text', 0) == 1)); $oCheckBox->SetBeforeInput(false); + $oCheckBox->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetFormat->AddSubBlock($oCheckBox); $oFieldSetDate = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:DateTimeFormat')); @@ -125,6 +107,7 @@ class ExcelBulkExport extends TabularBulkExport $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "excel_date_format_radio", "default", "excel_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); $oRadioDefault->SetBeforeInput(false); + $oRadioDefault->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); @@ -132,6 +115,7 @@ class ExcelBulkExport extends TabularBulkExport $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "excel_date_format_radio", "custom", "excel_date_time_format_custom", "radio"); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); $oRadioCustom->SetBeforeInput(false); + $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); diff --git a/core/pdfbulkexport.class.inc.php b/core/pdfbulkexport.class.inc.php index e3aa33ab6..6d2e6193c 100644 --- a/core/pdfbulkexport.class.inc.php +++ b/core/pdfbulkexport.class.inc.php @@ -57,6 +57,7 @@ class PDFBulkExport extends HTMLBulkExport //page format $oSelectFormat = SelectUIBlockFactory::MakeForSelectWithLabel("page_size", Dict::S('Core:BulkExport:PDFPageSize')); $oSelectFormat->SetBeforeInput(false); + $oSelectFormat->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetFormat->AddSubBlock($oSelectFormat); $aPossibleFormat = ['A3', 'A4', 'Letter']; @@ -69,6 +70,7 @@ class PDFBulkExport extends HTMLBulkExport $oSelectOrientation = SelectUIBlockFactory::MakeForSelectWithLabel("page_size", Dict::S('Core:BulkExport:PDFPageOrientation')); $oSelectOrientation->SetBeforeInput(false); + $oSelectOrientation->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetFormat->AddSubBlock($oSelectOrientation); $aPossibleOrientation = ['P', 'L']; @@ -89,6 +91,7 @@ class PDFBulkExport extends HTMLBulkExport $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "pdf_custom_date_time_format", "default", "pdf_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); $oRadioDefault->SetBeforeInput(false); + $oRadioDefault->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); @@ -96,6 +99,7 @@ class PDFBulkExport extends HTMLBulkExport $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "pdf_custom_date_time_format", "custom", "pdf_date_time_format_custom", "radio"); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); $oRadioCustom->SetBeforeInput(false); + $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); $sJSTooltip = json_encode('
'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'
'); diff --git a/core/spreadsheetbulkexport.class.inc.php b/core/spreadsheetbulkexport.class.inc.php index c76324d94..393745e4c 100644 --- a/core/spreadsheetbulkexport.class.inc.php +++ b/core/spreadsheetbulkexport.class.inc.php @@ -1,20 +1,9 @@ +/* + * @copyright Copyright (C) 2010-2021 Combodo SARL + * @license http://opensource.org/licenses/AGPL-3.0 + */ + use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; @@ -69,12 +58,14 @@ class SpreadsheetBulkExport extends TabularBulkExport $oCheckBox = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionFormattedText'), "formatted_text", "1", "spreadsheet_formatted_text", "checkbox"); $oCheckBox->GetInput()->SetIsChecked((utils::ReadParam('formatted_text', 0) == 1)); + $oCheckBox->GetInput()->AddCSSClass('ibo-input-checkbox'); $oCheckBox->SetBeforeInput(false); $oFieldSetFormat->AddSubBlock($oCheckBox); $oFieldSetFormat->AddSubBlock(new Html('
')); $oCheckBox = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionNoLocalize'), "no_localize", "1", "spreadsheet_no_localize", "checkbox"); $oCheckBox->GetInput()->SetIsChecked((utils::ReadParam('no_localize', 0) == 1)); + $oCheckBox->GetInput()->AddCSSClass('ibo-input-checkbox'); $oCheckBox->SetBeforeInput(false); $oFieldSetFormat->AddSubBlock($oCheckBox); @@ -88,6 +79,7 @@ class SpreadsheetBulkExport extends TabularBulkExport $sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8'); $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "spreadsheet_date_format_radio", "default", "spreadsheet_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); + $oRadioDefault->GetInput()->AddCSSClass('ibo-input-checkbox'); $oRadioDefault->SetBeforeInput(false); $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); @@ -95,6 +87,7 @@ class SpreadsheetBulkExport extends TabularBulkExport $sFormatInput = ''; $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "spreadsheet_date_format_radio", "custom", "spreadsheet_date_time_format_custom", "radio"); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); + $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oRadioCustom->SetBeforeInput(false); $oFieldSetDate->AddSubBlock($oRadioCustom); diff --git a/core/xmlbulkexport.class.inc.php b/core/xmlbulkexport.class.inc.php index babc76b8d..393b720ef 100644 --- a/core/xmlbulkexport.class.inc.php +++ b/core/xmlbulkexport.class.inc.php @@ -1,20 +1,9 @@ +/* + * @copyright Copyright (C) 2010-2021 Combodo SARL + * @license http://opensource.org/licenses/AGPL-3.0 + */ + use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory; @@ -59,11 +48,13 @@ class XMLBulkExport extends BulkExport $oCheckBoxLocalize = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionNoLocalize'), "no_localize", "1", "xml_no_localize", "checkbox"); $oCheckBoxLocalize->GetInput()->SetIsChecked((utils::ReadParam('no_localize', 0) == 1)); $oCheckBoxLocalize->SetBeforeInput(false); + $oCheckBoxLocalize->GetInput()->AddCSSClass('ibo-input-checkbox'); $oPanel->AddSubBlock($oCheckBoxLocalize); $oCheckBoxLink = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('Core:BulkExport:OptionLinkSets'), "linksets", "1", "xml_linksets", "checkbox"); $oCheckBoxLink->GetInput()->SetIsChecked((utils::ReadParam('linksets', 0) == 1)); $oCheckBoxLink->SetBeforeInput(false); + $oCheckBoxLink->GetInput()->AddCSSClass('ibo-input-checkbox'); $oPanel->AddSubBlock($oCheckBoxLink); return $oPanel; diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss index f5708749d..c588b322c 100644 --- a/css/backoffice/components/_datatable.scss +++ b/css/backoffice/components/_datatable.scss @@ -1,3 +1,8 @@ +/*! + * @copyright Copyright (C) 2010-2021 Combodo SARL + * @license http://opensource.org/licenses/AGPL-3.0 + */ + $ibo-datatable--padding-y: 2em !default; $ibo-datatable-cell-row--line-height: 30px !default; @@ -51,11 +56,16 @@ $ibo-list-column--max-height: 150px; // For cancel / OK / next... selection validation buttons .ibo-datatable--selection-validation-buttons-toolbar { - clear: both; - margin-top: $ibo-datatable--selection-validation-buttons-toolbar--margin-top; + clear: both; + margin-top: $ibo-datatable--selection-validation-buttons-toolbar--margin-top; } .ibo-list-column { - max-height: $ibo-list-column--max-height; - overflow-y: auto; + max-height: $ibo-list-column--max-height; + overflow-y: auto; +} + +.ibo-datatable .ibo-field-badge { + margin: 0; + padding: 0px 4px; } \ No newline at end of file diff --git a/css/backoffice/components/input/_input.scss b/css/backoffice/components/input/_input.scss index 81040094e..9e1e1d5ce 100644 --- a/css/backoffice/components/input/_input.scss +++ b/css/backoffice/components/input/_input.scss @@ -67,8 +67,10 @@ $ibo-input--margin-x: 5px !default; .ibo-input--label-right { margin-right: $ibo-input--margin-x; + display: inline; } .ibo-input--label-left { margin-leftt: $ibo-input--margin-x; + display: inline; } diff --git a/css/backoffice/pages/_all.scss b/css/backoffice/pages/_all.scss index 1e6b5b2f3..5cb07654d 100644 --- a/css/backoffice/pages/_all.scss +++ b/css/backoffice/pages/_all.scss @@ -10,4 +10,5 @@ @import "audit"; @import "data-synchro"; @import "datamodel-viewer"; +@import "csv-import"; @import "global-search"; \ No newline at end of file diff --git a/css/backoffice/pages/_csv-import.scss b/css/backoffice/pages/_csv-import.scss new file mode 100644 index 000000000..46dc06807 --- /dev/null +++ b/css/backoffice/pages/_csv-import.scss @@ -0,0 +1,45 @@ +/*! + * @copyright Copyright (C) 2010-2021 Combodo SARL + * @license http://opensource.org/licenses/AGPL-3.0 + */ +#tabs1-import .ibo-field--label { + max-width: 50%; +} + +div.cell_modified { + font-weight: bold; + color: #004e91; +} + +div.cell_error { + font-weight: bold; + color: #D81515; +} + +div.cell_error > p { + font-weight: bold; + color: #D81515; +} + +tr.row_unchanged td { + border-bottom: 1px #ccc solid; +} + +.wizContainer table tr.row_error td { + border-bottom: 1px #ccc solid; + background-color: #fdd; +} + +tr.row_modified td { + border-bottom: 1px #ccc solid; +} + +tr.row_added td { + border-bottom: 1px #ccc solid; +} + +.ibo-import-csv--download-file { + font-size: 4em; + color: $ibo-color-primary-400; + margin: 20px; +} \ No newline at end of file diff --git a/pages/ajax.csvimport.php b/pages/ajax.csvimport.php index d7c1dec28..88492a633 100644 --- a/pages/ajax.csvimport.php +++ b/pages/ajax.csvimport.php @@ -1,22 +1,18 @@ Dict::S('UI:CSVImport:MappingSelectOne')); $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable'); $sFieldCode = ''; // Code of the attribute, if there is a match - $aMatches = array(); - if (preg_match('/^(.+)\*$/', $sFieldName, $aMatches)) - { + $aMatches = array(); + if (preg_match('/^(.+)\*$/', $sFieldName, $aMatches)) { // Remove any trailing "star" character. // A star character at the end can be used to indicate a mandatory field $sFieldName = $aMatches[1]; - } - else if (preg_match('/^(.+)\*->(.+)$/', $sFieldName, $aMatches)) - { + } else if (preg_match('/^(.+)\*->(.+)$/', $sFieldName, $aMatches)) { // Remove any trailing "star" character before the arrow (->) // A star character at the end can be used to indicate a mandatory field $sFieldName = $aMatches[1].'->'.$aMatches[2]; } - if (($sFieldName == 'id') || ($sFieldName == Dict::S('UI:CSVImport:idField'))) - { + if (($sFieldName == 'id') || ($sFieldName == Dict::S('UI:CSVImport:idField'))) { $sFieldCode = 'id'; } - if ($bAdvancedMode) - { + if ($bAdvancedMode) { $aChoices['id'] = Dict::S('UI:CSVImport:idField'); } - foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) - { + foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) { $sStar = ''; - if ($oAttDef->IsExternalKey()) - { - if (($sFieldName == $oAttDef->GetLabel()) || ($sFieldName == $sAttCode)) - { + if ($oAttDef->IsExternalKey()) { + if (($sFieldName == $oAttDef->GetLabel()) || ($sFieldName == $sAttCode)) { $sFieldCode = $sAttCode; } - if ($bAdvancedMode) - { + if ($bAdvancedMode) { $aChoices[$sAttCode] = $oAttDef->GetLabel(); } $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode()); - if (!$oExtKeyAttDef->IsNullAllowed()) - { + if (!$oExtKeyAttDef->IsNullAllowed()) { $sStar = '*'; } // Get fields of the external class that are considered as reconciliation keys $sTargetClass = $oAttDef->GetTargetClass(); - foreach(MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) - { + foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) { // Note: Could not use "MetaModel::GetFriendlyNameAttributeCode($sTargetClass) === $sTargetAttCode" as it would return empty because the friendlyname is composite. - if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode) || ($oTargetAttDef instanceof AttributeFriendlyName)) - { + if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode) || ($oTargetAttDef instanceof AttributeFriendlyName)) { $bExtKey = $oTargetAttDef->IsExternalKey(); $aSignatures = array(); $aSignatures[] = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel(); $aSignatures[] = $sAttCode.'->'.$sTargetAttCode; - if ($bExtKey) - { + if ($bExtKey) { $aSignatures[] = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel().'->id'; $aSignatures[] = $sAttCode.'->'.$sTargetAttCode.'->id'; } - if ($bAdvancedMode || !$bExtKey) - { - + if ($bAdvancedMode || !$bExtKey) { + // When not in advanced mode do not allow to use reconciliation keys (on external keys) if they are themselves external keys ! $aChoices[$sAttCode.'->'.$sTargetAttCode] = MetaModel::GetLabel($sClassName, $sAttCode.'->'.$sTargetAttCode, true); - foreach ($aSignatures as $sSignature) - { - if (strcasecmp($sFieldName, $sSignature) == 0) - { - $sFieldCode = $sAttCode.'->'.$sTargetAttCode; + foreach ($aSignatures as $sSignature) { + if (strcasecmp($sFieldName, $sSignature) == 0) { + $sFieldCode = $sAttCode.'->'.$sTargetAttCode.$sStar; } } } @@ -181,49 +161,38 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo else if ( ($oAttDef->IsWritable() && (!$oAttDef->IsLinkset() || ($bAdvancedMode && $oAttDef->IsIndirect()))) || ($oAttDef instanceof AttributeFriendlyName) - ) - { + ) { $aChoices[$sAttCode] = MetaModel::GetLabel($sClassName, $sAttCode, true); - if ( ($sFieldName == $oAttDef->GetLabel()) || ($sFieldName == $sAttCode)) - { + if (($sFieldName == $oAttDef->GetLabel()) || ($sFieldName == $sAttCode)) { $sFieldCode = $sAttCode; } } } asort($aChoices); - $sHtml = "\n"; - return $sHtml; + + return $oSelect; } try @@ -239,259 +208,231 @@ try switch($sOperation) { case 'parser_preview': - $oPage = new ajax_page(""); - $oPage->SetContentType('text/html'); - $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data'); - if ($sSeparator == 'tab') $sSeparator = "\t"; - $sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data'); - $iLinesToSkip = utils::ReadParam('do_skip_lines', 0); - $bFirstLineAsHeader = utils::ReadParam('header_line', true); - $sEncoding = utils::ReadParam('encoding', 'UTF-8'); - $sData = stripslashes(utils::ReadParam('csvdata', true, false, 'raw_data')); - $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier, MetaModel::GetConfig()->Get('max_execution_time_per_loop')); - $iMaxIndex= 10; // Display maximum 10 lines for the preview - $aData = $oCSVParser->ToArray($iLinesToSkip, null, $iMaxIndex); - $iTarget = count($aData); - if ($iTarget == 0) - { - $oPage->p(Dict::S('UI:CSVImport:NoData')); - } - else - { - $sMaxLen = (strlen(''.$iTarget) < 3) ? 3 : strlen(''.$iTarget); // Pad line numbers to the appropriate number of chars, but at least 3 - $sFormat = '%0'.$sMaxLen.'d'; - $oPage->p("

".Dict::S('UI:Title:DataPreview')."

\n"); - $oPage->p("
\n"); - $oPage->add(""); - $index = 1; - foreach($aData as $aRow) - { - $sCSSClass = 'csv_row'.($index % 2); - if ( ($bFirstLineAsHeader) && ($index == 1)) - { - $oPage->add(""); - foreach ($aRow as $sCell) - { - $oPage->add(''); + $oPage = new AjaxPage(""); + $oPage->SetContentType('text/html'); + $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data'); + if ($sSeparator == 'tab') { + $sSeparator = "\t"; + } + $sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data'); + $iLinesToSkip = utils::ReadParam('do_skip_lines', 0); + $bFirstLineAsHeader = utils::ReadParam('header_line', true); + $sEncoding = utils::ReadParam('encoding', 'UTF-8'); + $sData = stripslashes(utils::ReadParam('csvdata', true, false, 'raw_data')); + $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier, MetaModel::GetConfig()->Get('max_execution_time_per_loop')); + $iMaxIndex = 10; // Display maximum 10 lines for the preview + $aData = $oCSVParser->ToArray($iLinesToSkip, null, $iMaxIndex); + $iTarget = count($aData); + if ($iTarget == 0) { + $oPage->p(Dict::S('UI:CSVImport:NoData')); + } else { + $sMaxLen = (strlen(''.$iTarget) < 3) ? 3 : strlen(''.$iTarget); // Pad line numbers to the appropriate number of chars, but at least 3 + $sFormat = '%0'.$sMaxLen.'d'; + + $oTitle = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:DataPreview')); + $oPage->AddSubBlock($oTitle); + + $oContainer = UIContentBlockUIBlockFactory::MakeStandard(); + $oContainer->AddCSSClass("ibo-is-visible"); + $oPage->AddSubBlock($oContainer); + + $index = 1; + $aColumns = []; + $aTableData = []; + foreach ($aData as $aRow) { + $sCSSClass = 'csv_row'.($index % 2); + if (($bFirstLineAsHeader) && ($index == 1)) { + $aColumns[] = ["label" => sprintf($sFormat, $index)]; + foreach ($aRow as $sCell) { + $aColumns[] = ["label" => htmlentities($sCell, ENT_QUOTES, 'UTF-8')]; + } + $iNbCols = count($aRow); + } else { + $aTableRow = []; + if ($index == 1) { + $iNbCols = count($aRow); + } + $aTableRow[] = sprintf($sFormat, $index); + foreach ($aRow as $sCell) { + $aTableRow[] = htmlentities($sCell, ENT_QUOTES, 'UTF-8'); + } + $aTableData[$index] = $aTableRow; } - $oPage->add("\n"); - $iNbCols = count($aRow); - - } - else - { - if ($index == 1) $iNbCols = count($aRow); - $oPage->add(""); - foreach ($aRow as $sCell) - { - $oPage->add(''); + $index++; + if ($index > $iMaxIndex) { + break; } - $oPage->add("\n"); } - $index++; - if ($index > $iMaxIndex) break; + $oTable = DataTableUIBlockFactory::MakeForForm("parser_preview", $aColumns, $aTableData); + $oContainer->AddSubBlock($oTable); + if ($iNbCols == 1) { + $oAlertMessage = \Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory::MakeForFailure(Dict::S('UI:CSVImport:ErrorOnlyOneColumn')); + $oPage->AddSubBlock($oAlertMessage); + } } - $oPage->add("
".sprintf($sFormat, $index)."'.htmlentities($sCell, ENT_QUOTES, 'UTF-8').'
".sprintf($sFormat, $index)."'.htmlentities($sCell, ENT_QUOTES, 'UTF-8').'
\n"); - $oPage->add("
\n"); - if($iNbCols == 1) - { - $oPage->p(' '.Dict::S('UI:CSVImport:ErrorOnlyOneColumn')); - } - else - { - $oPage->p(' '); - } - } - break; + break; case 'display_mapping_form': - $oPage = new ajax_page(""); - $oPage->no_cache(); - $oPage->SetContentType('text/html'); - $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data'); - $sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data'); - $iLinesToSkip = utils::ReadParam('do_skip_lines', 0); - $bFirstLineAsHeader = utils::ReadParam('header_line', false); - $sData = stripslashes(utils::ReadParam('csvdata', '', false, 'raw_data')); - $sClassName = utils::ReadParam('class_name', ''); - $bAdvanced = utils::ReadParam('advanced', false); - $sEncoding = utils::ReadParam('encoding', 'UTF-8'); + $oPage = new AjaxPage(""); + $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data'); + $sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data'); + $iLinesToSkip = utils::ReadParam('do_skip_lines', 0); + $bFirstLineAsHeader = utils::ReadParam('header_line', false); + $sData = stripslashes(utils::ReadParam('csvdata', '', false, 'raw_data')); + $sClassName = utils::ReadParam('class_name', ''); + $bAdvanced = utils::ReadParam('advanced', false); + $sEncoding = utils::ReadParam('encoding', 'UTF-8'); - $sInitFieldMapping = utils::ReadParam('init_field_mapping', '', false, 'raw_data'); - $sInitSearchField = utils::ReadParam('init_search_field', '', false, 'raw_data'); - $aInitFieldMapping = empty($sInitFieldMapping) ? array() : json_decode($sInitFieldMapping, true); - $aInitSearchField = empty($sInitSearchField) ? array() : json_decode($sInitSearchField, true); + $sInitFieldMapping = utils::ReadParam('init_field_mapping', '', false, 'raw_data'); + $sInitSearchField = utils::ReadParam('init_search_field', '', false, 'raw_data'); + $aInitFieldMapping = empty($sInitFieldMapping) ? array() : json_decode($sInitFieldMapping, true); + $aInitSearchField = empty($sInitSearchField) ? array() : json_decode($sInitSearchField, true); - $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier, MetaModel::GetConfig()->Get('max_execution_time_per_loop')); - $aData = $oCSVParser->ToArray($iLinesToSkip, null, 3 /* Max: 1 header line + 2 lines of sample data */); - $iTarget = count($aData); - if ($iTarget == 0) - { - $oPage->p(Dict::S('UI:CSVImport:NoData')); - } - else - { - $oPage->add(""); - $aFirstLine = $aData[0]; // Use the first row to determine the number of columns - $iStartLine = 0; - $iNbColumns = count($aFirstLine); - if ($bFirstLineAsHeader) - { - $iStartLine = 1; - foreach($aFirstLine as $sField) - { - $aHeader[] = $sField; + $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier, MetaModel::GetConfig()->Get('max_execution_time_per_loop')); + $aData = $oCSVParser->ToArray($iLinesToSkip, null, 3 /* Max: 1 header line + 2 lines of sample data */); + $iTarget = count($aData); + if ($iTarget == 0) { + $oPage->p(Dict::S('UI:CSVImport:NoData')); + } else { + $aFirstLine = $aData[0]; // Use the first row to determine the number of columns + $iStartLine = 0; + $iNbColumns = count($aFirstLine); + if ($bFirstLineAsHeader) { + $iStartLine = 1; + foreach ($aFirstLine as $sField) { + $aHeader[] = $sField; + } + } else { + // Build some conventional name for the fields: field1...fieldn + $index = 1; + foreach ($aFirstLine as $sField) { + $aHeader[] = Dict::Format('UI:CSVImport:FieldName', $index); + $index++; + } } - } - else - { - // Build some conventional name for the fields: field1...fieldn - $index= 1; - foreach($aFirstLine as $sField) - { - $aHeader[] = Dict::Format('UI:CSVImport:FieldName', $index); + $aColumns = []; + $aColumns ["HeaderFields"] = ["label" => Dict::S('UI:CSVImport:HeaderFields')]; + $aColumns ["HeaderMapipngs"] = ["label" => Dict::S('UI:CSVImport:HeaderMappings')]; + $aColumns ["HeaderSearch"] = ["label" => Dict::S('UI:CSVImport:HeaderSearch')]; + $aColumns ["DataLine1"] = ["label" => Dict::S('UI:CSVImport:DataLine1')]; + $aColumns ["DataLine2"] = ["label" => Dict::S('UI:CSVImport:DataLine2')]; + + $aTableData = []; + $index = 1; + foreach ($aHeader as $sField) { + $aTableRow = []; + $sDefaultChoice = null; + if (isset($aInitFieldMapping[$index])) { + $sDefaultChoice = $aInitFieldMapping[$index]; + } + $aTableRow['HeaderFields'] = utils::HtmlEntities($sField); + $aTableRow['HeaderMapipngs'] = BlockRenderer::RenderBlockTemplates(GetMappingForField($sClassName, $sField, $index, $bAdvanced, $sDefaultChoice)); + $aTableRow['HeaderSearch'] = ''; + $aTableRow['DataLine1'] = (isset($aData[$iStartLine][$index - 1]) ? htmlentities($aData[$iStartLine][$index - 1], ENT_QUOTES, 'UTF-8') : ' '); + $aTableRow['DataLine2'] = (isset($aData[$iStartLine + 1][$index - 1]) ? htmlentities($aData[$iStartLine + 1][$index - 1], ENT_QUOTES, 'UTF-8') : ' '); + $aTableData[$index] = $aTableRow; $index++; } - } - $oPage->add("
\n"); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $index = 1; - foreach($aHeader as $sField) - { - $sDefaultChoice = null; - if (isset($aInitFieldMapping[$index])) - { - $sDefaultChoice = $aInitFieldMapping[$index]; - } - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $index++; - } - $oPage->add("
'.Dict::S('UI:CSVImport:HeaderFields').''.Dict::S('UI:CSVImport:HeaderMappings').' '.Dict::S('UI:CSVImport:HeaderSearch').''.Dict::S('UI:CSVImport:DataLine1').''.Dict::S('UI:CSVImport:DataLine2').'
'.utils::HtmlEntities($sField).''.GetMappingForField($sClassName, $sField, $index, $bAdvanced, $sDefaultChoice).' '.(isset($aData[$iStartLine][$index-1]) ? htmlentities($aData[$iStartLine][$index-1], ENT_QUOTES, 'UTF-8') : ' ').''.(isset($aData[$iStartLine+1][$index-1]) ? htmlentities($aData[$iStartLine+1][$index-1], ENT_QUOTES, 'UTF-8') : ' ').'
\n"); - - if (empty($sInitSearchField)) - { - // Propose a reconciliation scheme - // - $aReconciliationKeys = MetaModel::GetReconcKeys($sClassName); - $aMoreReconciliationKeys = array(); // Store: key => void to automatically remove duplicates - foreach($aReconciliationKeys as $sAttCode) - { - if (!MetaModel::IsValidAttCode($sClassName, $sAttCode)) continue; - $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); - if ($oAttDef->IsExternalKey()) - { - // An external key is specified as a reconciliation key: this means that all the reconciliation - // keys of this class are proposed to identify the target object - $aMoreReconciliationKeys = array_merge($aMoreReconciliationKeys, GetMappingsForExtKey($sAttCode, $oAttDef, $bAdvanced)); + $oTable = DataTableUIBlockFactory::MakeForForm("mapping", $aColumns, $aTableData); + $oPage->AddSubBlock($oTable); + if (empty($sInitSearchField)) { + // Propose a reconciliation scheme + // + $aReconciliationKeys = MetaModel::GetReconcKeys($sClassName); + $aMoreReconciliationKeys = array(); // Store: key => void to automatically remove duplicates + foreach ($aReconciliationKeys as $sAttCode) { + if (!MetaModel::IsValidAttCode($sClassName, $sAttCode)) { + continue; + } + $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); + if ($oAttDef->IsExternalKey()) { + // An external key is specified as a reconciliation key: this means that all the reconciliation + // keys of this class are proposed to identify the target object + $aMoreReconciliationKeys = array_merge($aMoreReconciliationKeys, GetMappingsForExtKey($sAttCode, $oAttDef, $bAdvanced)); + } elseif ($oAttDef->IsExternalField()) { + // An external field is specified as a reconciliation key, translate the field into a field on the target class + // since external fields are not writable, and thus never appears in the mapping form + $sKeyAttCode = $oAttDef->GetKeyAttCode(); + $sTargetAttCode = $oAttDef->GetExtAttCode(); + $aMoreReconciliationKeys[$sKeyAttCode.'->'.$sTargetAttCode] = ''; + } } - elseif($oAttDef->IsExternalField()) - { - // An external field is specified as a reconciliation key, translate the field into a field on the target class - // since external fields are not writable, and thus never appears in the mapping form - $sKeyAttCode = $oAttDef->GetKeyAttCode(); - $sTargetAttCode = $oAttDef->GetExtAttCode(); - $aMoreReconciliationKeys[$sKeyAttCode.'->'.$sTargetAttCode] = ''; + $sDefaultKeys = '"'.implode('", "', array_merge($aReconciliationKeys, array_keys($aMoreReconciliationKeys))).'"'; + } else { + // The reconciliation scheme is given (navigating back in the wizard) + // + $aDefaultKeys = array(); + foreach ($aInitSearchField as $iSearchField => $void) { + $sAttCodeEx = $aInitFieldMapping[$iSearchField]; + $aDefaultKeys[] = $sAttCodeEx; + } + $sDefaultKeys = '"'.implode('", "', $aDefaultKeys).'"'; + } + + // Read only attributes (will be forced to "search") + $aReadOnlyKeys = array(); + foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) { + if (!$oAttDef->IsWritable()) { + $aReadOnlyKeys[] = $sAttCode; } } - $sDefaultKeys = '"'.implode('", "',array_merge($aReconciliationKeys, array_keys($aMoreReconciliationKeys))).'"'; - } - else - { - // The reconciliation scheme is given (navigating back in the wizard) - // - $aDefaultKeys = array(); - foreach ($aInitSearchField as $iSearchField => $void) - { - $sAttCodeEx = $aInitFieldMapping[$iSearchField]; - $aDefaultKeys[] = $sAttCodeEx; - } - $sDefaultKeys = '"'.implode('", "', $aDefaultKeys).'"'; - } + $sReadOnlyKeys = '"'.implode('", "', $aReadOnlyKeys).'"'; - // Read only attributes (will be forced to "search") - $aReadOnlyKeys = array(); - foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) - { - if(!$oAttDef->IsWritable()) - { - $aReadOnlyKeys[] = $sAttCode; - } - } - $sReadOnlyKeys = '"'.implode('", "', $aReadOnlyKeys).'"'; - - $oPage->add_ready_script( -<<add_ready_script( + <<AddCondition('id', 0, '='); // Make sure we create an empty set - $oSet = new CMDBObjectSet($oSearch); - $sResult = cmdbAbstractObject::GetSetAsCSV($oSet, array('showMandatoryFields' => true)); - - $sClassDisplayName = MetaModel::GetName($sClassName); - $sDisposition = utils::ReadParam('disposition', 'inline'); - if ($sDisposition == 'attachment') - { - switch($sFormat) - { - case 'xlsx': - $oPage = new ajax_page(""); - $oPage->SetContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); - $oPage->SetContentDisposition('attachment', $sClassDisplayName.'.xlsx'); - require_once(APPROOT.'/application/excelexporter.class.inc.php'); - $writer = new XLSXWriter(); - $writer->setAuthor(UserRights::GetUserFriendlyName()); - $aHeaders = array( 0 => explode(',', $sResult)); // comma is the default separator - $writer->writeSheet($aHeaders, $sClassDisplayName, array()); - $oPage->add($writer->writeToString()); - break; - - case 'csv': - default: - $oPage = new CSVPage(""); - $oPage->add_header("Content-type: text/csv; charset=utf-8"); - $oPage->add_header("Content-disposition: attachment; filename=\"{$sClassDisplayName}.csv\""); - $oPage->no_cache(); - $oPage->add($sResult); + $sClassName = utils::ReadParam('class_name'); + $sFormat = utils::ReadParam('format', 'csv'); + if (MetaModel::IsValidClass($sClassName)) { + $oSearch = new DBObjectSearch($sClassName); + $oSearch->AddCondition('id', 0, '='); // Make sure we create an empty set + $oSet = new CMDBObjectSet($oSearch); + $sResult = cmdbAbstractObject::GetSetAsCSV($oSet, array('showMandatoryFields' => true)); + + $sClassDisplayName = MetaModel::GetName($sClassName); + $sDisposition = utils::ReadParam('disposition', 'inline'); + if ($sDisposition == 'attachment') { + switch ($sFormat) { + case 'xlsx': + $oPage = new AjaxPage(""); + $oPage->SetContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $oPage->SetContentDisposition('attachment', $sClassDisplayName.'.xlsx'); + require_once(APPROOT.'/application/excelexporter.class.inc.php'); + $writer = new XLSXWriter(); + $writer->setAuthor(UserRights::GetUserFriendlyName()); + $aHeaders = array(0 => explode(',', $sResult)); // comma is the default separator + $writer->writeSheet($aHeaders, $sClassDisplayName, array()); + $oPage->add($writer->writeToString()); + break; + + case 'csv': + default: + $oPage = new CSVPage(""); + $oPage->add_header("Content-type: text/csv; charset=utf-8"); + $oPage->add_header("Content-disposition: attachment; filename=\"{$sClassDisplayName}.csv\""); + $oPage->add($sResult); + } + } else { + $oPage = new AjaxPage(""); + $oButtonXls = ButtonUIBlockFactory::MakeIconLink('ibo-import-csv--download-file fas fa-file-csv', $sClassDisplayName.'.csv', utils::GetAbsoluteUrlAppRoot().'pages/ajax.csvimport.php?operation=get_csv_template&disposition=attachment&class_name='.$sClassName); + $oPage->AddSubBlock($oButtonXls); + $oButtonCsv = ButtonUIBlockFactory::MakeIconLink('ibo-import-csv--download-file fas fa-file-excel', $sClassDisplayName.'.xlsx', utils::GetAbsoluteUrlAppRoot().'pages/ajax.csvimport.php?operation=get_csv_template&disposition=attachment&format=xlsx&class_name='.$sClassName); + $oPage->AddSubBlock($oButtonCsv); + $oTextArea = new TextArea("", $sResult, "", 100, 5); } + } else { + $oPage = new AjaxPage("Class $sClassName is not a valid class !"); } - else - { - $oPage = new ajax_page(""); - $oPage->no_cache(); - $oPage->add('

'); - $oPage->add('


'.$sClassDisplayName.'.csv
'); - $oPage->add('

'.$sClassDisplayName.'.xlsx
'); - $oPage->add('

'); - $oPage->add('

'); - } - } - else - { - $oPage = new ajax_page("Class $sClassName is not a valid class !"); - } - break; + break; } $oPage->output(); } @@ -500,4 +441,3 @@ catch (Exception $e) IssueLog::Error($e->getMessage()); } -?> diff --git a/pages/csvimport.php b/pages/csvimport.php index 61699b8d6..2899d76af 100644 --- a/pages/csvimport.php +++ b/pages/csvimport.php @@ -1,26 +1,31 @@ SetBreadCrumbEntry('ui-tool-bulkimport', Dict::S('Menu:CSVImportMenu'), Dict::S('UI:Title:BulkImport+'), '', 'fas fa-file-import', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES); + /** + * Helper function to build a select from the list of valid classes for a given action + * + * @deprecated since 3.0.0 use GetClassesSelectUIBlock + * + * @param $sDefaultValue + * @param integer $iWidthPx The width (in pixels) of the drop-down list + * @param integer $iActionCode The ActionCode (from UserRights) to check for authorization for the classes + * + * @param string $sName The name of the select in the HTML form + * + * @return string The HTML fragment corresponding to the select tag + */ + function GetClassesSelect($sName, $sDefaultValue, $iWidthPx, $iActionCode = null) + { + $oSelectBlock = GetClassesSelectUIBlock($sName, $sDefaultValue, $iActionCode); + + return BlockRenderer::RenderBlockTemplates($oSelectBlock); + } + /** * Helper function to build a select from the list of valid classes for a given action * @@ -43,53 +68,51 @@ try * @param integer $iWidthPx The width (in pixels) of the drop-down list * @param integer $iActionCode The ActionCode (from UserRights) to check for authorization for the classes * - * @return string The HTML fragment corresponding to the select tag + * @return \Combodo\iTop\Application\UI\Base\Component\Input\Select\ */ - function GetClassesSelect($sName, $sDefaultValue, $iWidthPx, $iActionCode = null) + function GetClassesSelectUIBlock(string $sName, $sDefaultValue, int $iActionCode): Select { - $sHtml = ""; - return $sHtml; + foreach ($aValidClasses as $sValue => $oBlock) { + $oSelectBlock->AddSubBlock($oBlock); + } + + return $oSelectBlock; } - + /** * Helper to 'check' an input in an HTML form if the current value equals the value given + * * @param mixed $sCurrentValue The current value to be chacked against the value of the input * @param mixed $sProposedValue The value of the input * @param bool $bInverseCondition Set to true to perform the reversed comparison + * * @return string Either ' checked' or an empty string */ - function IsChecked($sCurrentValue, $sProposedValue, $bInverseCondition = false) + function IsChecked($sCurrentValue, $sProposedValue, $bInverseCondition = false) { $bCondition = ($sCurrentValue == $sProposedValue); - + return ($bCondition xor $bInverseCondition) ? ' checked' : ''; } - + /** * Returns the number of occurences of each char from the set in the specified string * @param string $sString The input data @@ -176,7 +199,7 @@ try */ function DisplaySynchroBanner(WebPage $oP, $sClass, $iCount) { - $oP->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:Title:BulkSynchro_nbItem_ofClass_class', $iCount, MetaModel::GetName($sClass))."

\n"); + $oP->AddSubBlock(AlertUIBlockFactory::MakeForInformation(MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:Title:BulkSynchro_nbItem_ofClass_class', $iCount, MetaModel::GetName($sClass)))); } /** @@ -223,7 +246,6 @@ try $oSet = new DBObjectSet($oSearch); $iCount = $oSet->Count(); DisplaySynchroBanner($oPage, $sClassName, $iCount); - $sClassesSelect = "'); + $oPage->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata_truncated", htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8'), "csvdata_truncated")); $aRes = $oBulk->Process($oMyChange); - $sHtml = ''; - $sHtml .= ''; - $sHtml .= ''; - $sHtml .= ''; - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - if (!empty($sAttCode) && ($sAttCode != ':none:') && ($sAttCode != 'finalclass')) - { - $sHtml .= ""; + $aColumns = []; + $aColumns ["line"] = ["label" => "Line"]; + $aColumns ["status"] = ["label" => "Status"]; + $aColumns ["object"] = ["label" => "Object"]; + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + if (!empty($sAttCode) && ($sAttCode != ':none:') && ($sAttCode != 'finalclass')) { + $aColumns[$sClassName.'/'.$sAttCode] = ["label" => MetaModel::GetLabel($sClassName, $sAttCode)]; } } - $sHtml .= ''; - $sHtml .= ''; - + $aColumns["message"] = ["label" => "Message"]; + $iErrors = 0; $iCreated = 0; $iModified = 0; $iUnchanged = 0; - - foreach($aRes as $iLine => $aResRow) - { + + $aTableData = []; + + foreach ($aRes as $iLine => $aResRow) { + $aTableRow = []; $oStatus = $aResRow['__STATUS__']; $sUrl = ''; $sMessage = ''; $sCSSRowClass = ''; $sCSSMessageClass = 'cell_ok'; - switch(get_class($oStatus)) - { + switch (get_class($oStatus)) { case 'RowStatus_NoChange': - $iUnchanged++; - $sFinalClass = $aResRow['finalclass']; - $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); - $sUrl = $oObj->GetHyperlink(); - $sStatus = ''; - $sCSSRowClass = 'row_unchanged'; - break; - - case 'RowStatus_Modify': - $iModified++; - $sFinalClass = $aResRow['finalclass']; - $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); - $sUrl = $oObj->GetHyperlink(); - $sStatus = ''; - $sCSSRowClass = 'row_modified'; - break; - - case 'RowStatus_Disappeared': - $iModified++; - $sFinalClass = $aResRow['finalclass']; - $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); - $sUrl = $oObj->GetHyperlink(); - $sStatus = ''; - $sCSSRowClass = 'row_modified'; - if ($bSimulate) - { - $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate'); - } - else - { - $sMessage = Dict::S('UI:CSVReport-Object-MissingUpdated'); - } - break; - - case 'RowStatus_NewObj': - $iCreated++; - $sFinalClass = $aResRow['finalclass']; - $sStatus = ''; - $sCSSRowClass = 'row_added'; - if ($bSimulate) - { - $sMessage = Dict::S('UI:CSVReport-Object-ToCreate'); - } - else - { + $iUnchanged++; $sFinalClass = $aResRow['finalclass']; $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $sUrl = $oObj->GetHyperlink(); - $sMessage = Dict::S('UI:CSVReport-Object-Created'); - } - break; - + $sStatus = ''; + $sCSSRowClass = 'row_unchanged'; + break; + + case 'RowStatus_Modify': + $iModified++; + $sFinalClass = $aResRow['finalclass']; + $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); + $sUrl = $oObj->GetHyperlink(); + $sStatus = ''; + $sCSSRowClass = 'row_modified'; + break; + + case 'RowStatus_Disappeared': + $iModified++; + $sFinalClass = $aResRow['finalclass']; + $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); + $sUrl = $oObj->GetHyperlink(); + $sStatus = ''; + $sCSSRowClass = 'row_modified'; + if ($bSimulate) { + $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate'); + } else { + $sMessage = Dict::S('UI:CSVReport-Object-MissingUpdated'); + } + break; + + case 'RowStatus_NewObj': + $iCreated++; + $sFinalClass = $aResRow['finalclass']; + $sStatus = ''; + $sCSSRowClass = 'row_added'; + if ($bSimulate) { + $sMessage = Dict::S('UI:CSVReport-Object-ToCreate'); + } else { + $sFinalClass = $aResRow['finalclass']; + $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); + $sUrl = $oObj->GetHyperlink(); + $sMessage = Dict::S('UI:CSVReport-Object-Created'); + } + break; + case 'RowStatus_Issue': - $iErrors++; - $sMessage .= $oPage->GetP($oStatus->GetDescription()); - $sStatus = '';//translate - $sCSSMessageClass = 'cell_error'; - $sCSSRowClass = 'row_error'; - if (array_key_exists($iLine, $aData)) - { - $aRow = $aData[$iLine]; - $aResult[] = $sTextQualifier.implode($sTextQualifier.$sSeparator.$sTextQualifier,$aRow).$sTextQualifier; // Remove the first line and store it in case of error - } - break; + $iErrors++; + $sMessage .= $oPage->GetP($oStatus->GetDescription()); + $sStatus = '';//translate + $sCSSMessageClass = 'cell_error'; + $sCSSRowClass = 'row_error'; + if (array_key_exists($iLine, $aData)) { + $aRow = $aData[$iLine]; + $aResult[] = $sTextQualifier.implode($sTextQualifier.$sSeparator.$sTextQualifier, $aRow).$sTextQualifier; // Remove the first line and store it in case of error + } + break; } - $sHtml .= ''; - $sHtml .= ""; - $sHtml .= ""; - $sHtml .= ""; - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - if (!empty($sAttCode) && ($sAttCode != ':none:') && ($sAttCode != 'finalclass')) - { - $oCellStatus = $aResRow[$iNumber -1]; + $aTableRow['CSSClass'] = $sCSSRowClass; + $aTableRow['line'] = sprintf("%0{$sMaxLen}d", 1 + $iLine + $iRealSkippedLines); + $aTableRow['status'] = $sStatus; + $aTableRow['object'] = $sUrl; + + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + if (!empty($sAttCode) && ($sAttCode != ':none:') && ($sAttCode != 'finalclass')) { + $oCellStatus = $aResRow[$iNumber - 1]; $sCellMessage = ''; - if (isset($aExternalKeysByColumn[$iNumber -1])) - { - $sExtKeyName = $aExternalKeysByColumn[$iNumber -1]; + if (isset($aExternalKeysByColumn[$iNumber - 1])) { + $sExtKeyName = $aExternalKeysByColumn[$iNumber - 1]; $oExtKeyCellStatus = $aResRow[$sExtKeyName]; - switch(get_class($oExtKeyCellStatus)) - { + switch (get_class($oExtKeyCellStatus)) { case 'CellStatus_Issue': case 'CellStatus_SearchIssue': case 'CellStatus_NullIssue': case 'CellStatus_Ambiguous': - $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription()); - break; - + $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription()); + break; + default: - // Do nothing + // Do nothing } } $sHtmlValue = $oCellStatus->GetDisplayableValue(); - switch(get_class($oCellStatus)) - { + switch (get_class($oCellStatus)) { case 'CellStatus_Issue': - $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); - $sHtml .= ''; - break; - + $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); + $aTableRow[$sClassName.'/'.$sAttCode] = '
'.Dict::Format('UI:CSVReport-Object-Error', $sHtmlValue).$sCellMessage.'
'; + break; + case 'CellStatus_SearchIssue': - $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); - $sHtml .= ''; - break; - + $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); + $aTableRow[$sClassName.'/'.$sAttCode] = '
ERROR: '.$sHtmlValue.$sCellMessage.'
'; + break; + case 'CellStatus_Ambiguous': - $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); - $sHtml .= ''; - break; - + $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); + $aTableRow[$sClassName.'/'.$sAttCode] = '
'.Dict::Format('UI:CSVReport-Object-Ambiguous', $sHtmlValue).$sCellMessage.'
'; + break; + case 'CellStatus_Modify': - $sHtml .= ''; - break; - + $aTableRow[$sClassName.'/'.$sAttCode] = '
'.$sHtmlValue.'
'; + break; + default: - $sHtml .= ''; + $aTableRow[$sClassName.'/'.$sAttCode] = $sHtmlValue.$sCellMessage; } } } - $sHtml .= ""; - $sHtml .= ''; + $aTableRow['message'] = "
$sMessage
"; + + $aTableData[] = $aTableRow; } - + $iUnchanged = count($aRes) - $iErrors - $iModified - $iCreated; - $sHtml .= '
LineStatusObject".MetaModel::GetLabel($sClassName, $sAttCode)."Message
".sprintf("%0{$sMaxLen}d", 1+$iLine+$iRealSkippedLines)."$sStatus$sUrl'.Dict::Format('UI:CSVReport-Object-Error', $sHtmlValue).$sCellMessage.'ERROR: '.$sHtmlValue.$sCellMessage.''.Dict::Format('UI:CSVReport-Object-Ambiguous', $sHtmlValue).$sCellMessage.''.$sHtmlValue.''.$sHtmlValue.$sCellMessage.'$sMessage
'; - $oPage->add('
'); - $oPage->add('
'); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - if (!empty($sSynchroScope)) - { - foreach($aSynchroUpdate as $sKey => $value) - { - $oPage->add(''); + $oTable = DataTableUIBlockFactory::MakeForForm("csvImport", $aColumns, $aTableData); + + $oContainer = UIContentBlockUIBlockFactory::MakeStandard(); + $oContainer->AddCSSClass("wizContainer"); + $oPage->AddSubBlock($oContainer); + + $oForm = FormUIBlockFactory::MakeStandard('wizForm'); + $oContainer->AddSubBlock($oForm); + + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", ($iCurrentStep + 1))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("separator", htmlentities($sSeparator, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("text_qualifier", htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("header_line", $bHeaderLine)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("nb_skipped_lines", utils::ReadParam('nb_skipped_lines', '0'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("box_skiplines", utils::ReadParam('box_skiplines', '0'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata_truncated", htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8'), "csvdata_truncated")); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata", htmlentities($sCSVData, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("encoding", $sEncoding)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("class_name", $sClassName)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("advanced", $bAdvanced)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("date_time_format", htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("custom_date_time_format", htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + + if (!empty($sSynchroScope)) { + foreach ($aSynchroUpdate as $sKey => $value) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_update[$sKey]", $value)); } } - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - $oPage->add(''); + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("field[$iNumber]", $sAttCode)); } - foreach($aSearchFields as $index => $sDummy) - { - $oPage->add(''); + foreach ($aSearchFields as $index => $sDummy) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("search_field[$index]", "1")); } $aDisplayFilters = array(); - if ($bSimulate) - { + if ($bSimulate) { $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsWillStayUnchanged'); $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWillBeModified'); $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWillBeAdded'); $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsWillHaveErrors'); - } - else - { + } else { $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsRemainedUnchanged'); $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWereModified'); $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWereAdded'); $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsHadErrors'); } - $oPage->add('

  '.sprintf($aDisplayFilters['unchanged'], $iUnchanged).'  '); - $oPage->add('  '.sprintf($aDisplayFilters['modified'], $iModified).'  '); - $oPage->add('  '.sprintf($aDisplayFilters['added'], $iCreated).'  '); - $oPage->add('  '.sprintf($aDisplayFilters['errors'], $iErrors).'

'); - $oPage->add('
'); - $oPage->add($sHtml); - $oPage->add('
'); - $oPage->add('

'); - if($bSimulate) - { - $oPage->add('  '); + + $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel(' '.sprintf($aDisplayFilters['unchanged'], $iUnchanged), '', "1", "show_unchanged", "checkbox"); + $oCheckBoxUnchanged->GetInput()->SetIsChecked(true); + $oCheckBoxUnchanged->SetBeforeInput(false); + $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oForm->AddSubBlock($oCheckBoxUnchanged); + $oPage->add_ready_script("$('#show_unchanged').on('click', function(){ToggleRows('row_unchanged')})"); + + $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel(' '.sprintf($aDisplayFilters['modified'], $iModified), '', "1", "show_modified", "checkbox"); + $oCheckBoxUnchanged->GetInput()->SetIsChecked(true); + $oCheckBoxUnchanged->SetBeforeInput(false); + $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oForm->AddSubBlock($oCheckBoxUnchanged); + $oPage->add_ready_script("$('#show_modified').on('click', function(){ToggleRows('row_modified')})"); + + $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel(' '.sprintf($aDisplayFilters['added'], $iCreated), '', "1", "show_created", "checkbox"); + $oCheckBoxUnchanged->GetInput()->SetIsChecked(true); + $oCheckBoxUnchanged->SetBeforeInput(false); + $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oForm->AddSubBlock($oCheckBoxUnchanged); + $oPage->add_ready_script("$('#show_created').on('click', function(){ToggleRows('row_added')})"); + + $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel(' '.sprintf($aDisplayFilters['errors'], $iErrors), '', "1", "show_errors", "checkbox"); + $oCheckBoxUnchanged->GetInput()->SetIsChecked(true); + $oCheckBoxUnchanged->SetBeforeInput(false); + $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oForm->AddSubBlock($oCheckBoxUnchanged); + $oPage->add_ready_script("$('#show_errors').on('click', function(){ToggleRows('row_error')})"); + $oForm->AddSubBlock($oTable); + + if ($bSimulate) { + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Restart'))->SetOnClickJsCode("CSVRestart()")); } - $oPage->add('  '); + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForDestructiveAction(Dict::S('UI:Button:Back'))->SetOnClickJsCode("CSVGoBack()")); $bShouldConfirm = false; - if ($bSimulate) - { + if ($bSimulate) { // if there are *too many* changes, we should ask the user for a confirmation - if (count($aRes) >= MetaModel::GetConfig()->Get('csv_import_min_object_confirmation')) - { - $fErrorsPercentage = (100.0*$iErrors)/count($aRes); - if ($fErrorsPercentage >= MetaModel::GetConfig()->Get('csv_import_errors_percentage')) - { + if (count($aRes) >= MetaModel::GetConfig()->Get('csv_import_min_object_confirmation')) { + $fErrorsPercentage = (100.0 * $iErrors) / count($aRes); + if ($fErrorsPercentage >= MetaModel::GetConfig()->Get('csv_import_errors_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Errors', $fErrorsPercentage); $bShouldConfirm = true; } - $fCreatedPercentage = (100.0*$iCreated)/count($aRes); - if ($fCreatedPercentage >= MetaModel::GetConfig()->Get('csv_import_creations_percentage')) - { + $fCreatedPercentage = (100.0 * $iCreated) / count($aRes); + if ($fCreatedPercentage >= MetaModel::GetConfig()->Get('csv_import_creations_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Created', $fCreatedPercentage); $bShouldConfirm = true; } - $fModifiedPercentage = (100.0*$iModified)/count($aRes); - if ($fModifiedPercentage >= MetaModel::GetConfig()->Get('csv_import_modifications_percentage')) - { + $fModifiedPercentage = (100.0 * $iModified) / count($aRes); + if ($fModifiedPercentage >= MetaModel::GetConfig()->Get('csv_import_modifications_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Modified', $fModifiedPercentage); $bShouldConfirm = true; } - + } - $iCount = count($aRes); - //$oPage->add('

'); $sConfirm = $bShouldConfirm ? 'true' : 'false'; - $oPage->add('

"); + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:DoImport'))->SetOnClickJsCode("return DoSubmit({$sConfirm})")); + + } else { + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Done'), "", "", true)); } - else - { - $oPage->add('

'); - } - $oPage->add('
'); - $oPage->add('
'); - - if ($bShouldConfirm) - { + + if ($bShouldConfirm) { $sYesButton = Dict::S('UI:Button:Ok'); $sNoButton = Dict::S('UI:Button:Cancel'); - $oPage->add('
'); - $oPage->add('

'.$sMessage.'

'); - $oPage->add('

'.htmlentities(Dict::S('UI:CSVImportConfirmMessage'), ENT_QUOTES, 'UTF-8').'

'); - $oPage->add('
'); - $oPage->add('
'); + $oDlg = UIContentBlockUIBlockFactory::MakeStandard("dlg_confirmation"); + $oPage->AddSubBlock($oDlg); + $oDlg->AddSubBlock(new Html($sMessage)); + $oDlg->AddSubBlock(new Html(htmlentities(Dict::S('UI:CSVImportConfirmMessage'), ENT_QUOTES, 'UTF-8'))); + + $oDlgConfirm = UIContentBlockUIBlockFactory::MakeStandard("confirmation_chart")->AddCSSClass('ibo-hidden'); + $oPage->AddSubBlock($oDlgConfirm); + + $sDlgTitle = htmlentities(Dict::S('UI:CSVImportConfirmTitle'), ENT_QUOTES, 'UTF-8'); $oPage->add_ready_script( -<<add('

'.Dict::S('UI:Title:CSVImportStep5').'

'); + $oTitle = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:CSVImportStep5')); + $oPage->AddSubBlock($oTitle); + $aResult = ProcessCSVData($oPage, false /* simulate = false */); - if (is_array($aResult)) - { - $oPage->StartCollapsibleSection(Dict::S('UI:CSVImport:LinesNotImported'), false); - $oPage->p(Dict::S('UI:CSVImport:LinesNotImported+')); - $oPage->add(''); - $oPage->EndCollapsibleSection(); + if (is_array($aResult)) { + $oCollapsibleSection = CollapsibleSectionUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:LinesNotImported')); + $oPage->AddSubBlock($oCollapsibleSection); + + $oField = FieldUIBlockFactory::MakeLarge(Dict::S('UI:CSVImport:LinesNotImported+')); + $oCollapsibleSection->AddSubBlock($oField); + + $oText = new TextArea("", htmlentities(implode("\n", $aResult), ENT_QUOTES, 'UTF-8'), "", 150, 50); + $oField->AddSubBlock($oText); } } @@ -731,7 +759,8 @@ EOF */ function Preview(WebPage $oPage) { - $oPage->add('

'.Dict::S('UI:Title:CSVImportStep4').'

'); + $oPanel = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:CSVImportStep4')); + $oPage->AddSubBlock($oPanel); ProcessCSVData($oPage, true /* simulate */); } @@ -761,64 +790,80 @@ EOF $sEncoding = utils::ReadParam('encoding', 'UTF-8'); $sDateTimeFormat = utils::ReadParam('date_time_format', 'default'); $sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', (string)AttributeDateTime::GetFormat(), false, 'raw_data'); - + $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data'); - if (!empty($sSynchroScope)) - { + if (!empty($sSynchroScope)) { $oSearch = DBObjectSearch::FromOQL($sSynchroScope); $sClassName = $oSearch->GetClass(); // If a synchronization scope is set, then the class is fixed ! $oSet = new DBObjectSet($oSearch); $iCount = $oSet->Count(); DisplaySynchroBanner($oPage, $sClassName, $iCount); - $sClassesSelect = " '.Dict::S('UI:CSVImport:AdvancedMode').''); - $oPage->add(''); - $oPage->add('

'.Dict::S('UI:CSVImport:SelectAClassFirst').'

'); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - if (!empty($sSynchroScope)) - { - foreach($aSynchroUpdate as $sKey => $value) - { - $oPage->add(''); + $oContainer = UIContentBlockUIBlockFactory::MakeStandard(); + $oContainer->AddCSSClass("wizContainer"); + $oPage->AddSubBlock($oContainer); + + $oForm = FormUIBlockFactory::MakeStandard('wizForm'); + $oForm->SetOnSubmitJsCode("return CheckValues()"); + $oContainer->AddSubBlock($oForm); + + $oFieldSelectClass = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:SelectClass'), $oClassesSelect); + $oForm->AddSubBlock($oFieldSelectClass); + + $oAdvancedMode = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('UI:CSVImport:AdvancedMode'), "advanced", 1, '', 'checkbox'); + $oAdvancedMode->GetInput()->SetIsChecked(($bAdvanced == 1)); + $oAdvancedMode->SetBeforeInput(false); + $oAdvancedMode->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oForm->AddSubBlock($oAdvancedMode); + + $oDivAdvancedHelp = UIContentBlockUIBlockFactory::MakeStandard("advanced_help")->AddCSSClass('ibo-is-hidden'); + $oForm->AddSubBlock($oDivAdvancedHelp); + + $oDivMapping = UIContentBlockUIBlockFactory::MakeStandard("mapping")->AddCSSClass('ibo-is-visible'); + $oDivMapping->AddSubBlock(new Html(Dict::S('UI:CSVImport:SelectAClassFirst'))); + $oForm->AddSubBlock($oDivMapping); + + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", "4")); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("separator", htmlentities($sSeparator, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("text_qualifier", htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("header_line", $bHeaderLine)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("nb_skipped_lines", utils::ReadParam('nb_skipped_lines', '0'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("box_skiplines", utils::ReadParam('box_skiplines', '0'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata_truncated", htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8'), "csvdata_truncated")); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata", htmlentities($sCSVData, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("encoding", $sEncoding)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("date_time_format", htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("custom_date_time_format", htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + + if (!empty($sSynchroScope)) { + foreach ($aSynchroUpdate as $sKey => $value) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_update[$sKey]", $value)); } } - $oPage->add('

  '); - $oPage->add('  '); - $oPage->add('

'); - $oPage->add(''); - $oPage->add(''); - + + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Restart'))->SetOnClickJsCode("CSVRestart()")); + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForDestructiveAction(Dict::S('UI:Button:Back'))->SetOnClickJsCode("CSVGoBack()")); + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:SimulateImport'), '', '', true)); + $sAlertIncompleteMapping = addslashes(Dict::S('UI:CSVImport:AlertIncompleteMapping')); $sAlertMultipleMapping = addslashes(Dict::S('UI:CSVImport:AlertMultipleMapping')); $sAlertNoSearchCriteria = addslashes(Dict::S('UI:CSVImport:AlertNoSearchCriteria')); - + $oPage->add_ready_script( -<< 1) && (sRefValue != ':none:')) { @@ -1088,15 +1133,8 @@ EOF $aGuesses = GuessParameters($sUTF8Data); // Try to predict the parameters, based on the input data - $sSeparator = utils::ReadParam('separator', '', false, 'raw_data'); - if ($sSeparator == '') // May be set to an empty value by the previous page - { - $sSeparator = $aGuesses['separator']; - } $iSkippedLines = utils::ReadParam('nb_skipped_lines', ''); $bBoxSkipLines = utils::ReadParam('box_skiplines', 0); - if ($sSeparator == 'tab') $sSeparator = "\t"; - $sOtherSeparator = in_array($sSeparator, array(',', ';', "\t")) ? '' : $sSeparator; $sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data'); if ($sTextQualifier == '') // May be set to an empty value by the previous page { @@ -1108,40 +1146,30 @@ EOF $bAdvanced = utils::ReadParam('advanced', 0); $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data'); $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name'); - $sDateTimeFormat = utils::ReadParam('date_time_format', 'default'); - $sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', (string)AttributeDateTime::GetFormat(), false, 'raw_data'); - + // Create a truncated version of the data used for the fast preview // Take about 20 lines of data... knowing that some lines may contain carriage returns $iMaxLen = strlen($sUTF8Data); - if ($iMaxLen > 0) - { + if ($iMaxLen > 0) { $iMaxLines = 20; $iCurPos = true; - while ( ($iCurPos > 0) && ($iMaxLines > 0)) - { + while (($iCurPos > 0) && ($iMaxLines > 0)) { $pos = strpos($sUTF8Data, "\n", $iCurPos); - if ($pos !== false) - { - $iCurPos = 1+$pos; - } - else - { + if ($pos !== false) { + $iCurPos = 1 + $pos; + } else { $iCurPos = strlen($sUTF8Data); $iMaxLines = 1; } $iMaxLines--; } $sCSVDataTruncated = substr($sUTF8Data, 0, $iCurPos); - } - else - { + } else { $sCSVDataTruncated = ''; } $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data'); - if (!empty($sSynchroScope)) - { + if (!empty($sSynchroScope)) { $oSearch = DBObjectSearch::FromOQL($sSynchroScope); $sClassName = $oSearch->GetClass(); $oSet = new DBObjectSet($oSearch); @@ -1149,70 +1177,154 @@ EOF DisplaySynchroBanner($oPage, $sClassName, $iCount); $aSynchroUpdate = utils::ReadParam('synchro_update', array()); } - - $oPage->add('

'.Dict::S('UI:Title:CSVImportStep2').'

'); - $oPage->add('
'); - $oPage->add('
'); - $oPage->add('
'); - $oPage->add('

'.Dict::S('UI:CSVImport:SeparatorCharacter').'

'); - $oPage->add('

'.Dict::S('UI:CSVImport:SeparatorComma+').'
'); - $oPage->add(' '.Dict::S('UI:CSVImport:SeparatorSemicolon+').'
'); - $oPage->add(' '.Dict::S('UI:CSVImport:SeparatorTab+').'
'); - $oPage->add(' '.Dict::S('UI:CSVImport:SeparatorOther').' '); - $oPage->add('

'); - $oPage->add('
'); - $oPage->add('

'.Dict::S('UI:CSVImport:TextQualifierCharacter').'

'); - $oPage->add('

'.Dict::S('UI:CSVImport:QualifierDoubleQuote+').'
'); - $oPage->add(' '.Dict::S('UI:CSVImport:QualifierSimpleQuote+').'
'); - $oPage->add(' '.Dict::S('UI:CSVImport:QualifierOther').' '); - $oPage->add('

'); - $oPage->add('
'); - $oPage->add('

'.Dict::S('UI:CSVImport:CommentsAndHeader').'

'); - $oPage->add('

'.Dict::S('UI:CSVImport:TreatFirstLineAsHeader').'

'); - $oPage->add('

'.Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', '').'

'); - $oPage->add('

'); - $oPage->add('

'.Dict::S('UI:CSVImport:DateAndTimeFormats').'

'); - $oPage->add('

'); - $oPage->add('

'); - $oPage->add('

'); - $oPage->add(''); - $oPage->add(''); + $oPanel = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:CSVImportStep2')); + $oPage->AddSubBlock($oPanel); + + $oForm = FormUIBlockFactory::MakeStandard('wizForm'); + $oPage->AddSubBlock($oForm); + + $oContainer = UIContentBlockUIBlockFactory::MakeStandard(); + $oContainer->AddCSSClass("wizContainer"); + $oForm->AddSubBlock($oContainer); + + $oMulticolumn = UIContentBlockUIBlockFactory::MakeStandard(); + $oMulticolumn->AddCSSClass('ibo-multi-column'); + $oForm->AddSubBlock($oMulticolumn); + + //SeparatorCharacter + $oFieldSetSeparator = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:SeparatorCharacter')); + $oFieldSetSeparator->AddCSSClass('ibo-column'); + $oMulticolumn->AddSubBlock($oFieldSetSeparator); + + $aSep = array( + ';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'), + ',' => Dict::S('UI:CSVImport:SeparatorComma+'), + 'tab' => Dict::S('UI:CSVImport:SeparatorTab+'), + ); + $sSeparator = utils::ReadParam('separator', '', false, 'raw_data'); + if ($sSeparator == '') // May be set to an empty value by the previous page + { + $sSeparator = $aGuesses['separator']; + } + if ($sSeparator == 'tab') { + $sSeparator = "\t"; + } + $sOtherSeparator = in_array($sSeparator, array(',', ';', "\t")) ? '' : $sSeparator; + $aSep['other'] = Dict::S('UI:CSVImport:SeparatorOther').' '; + + foreach ($aSep as $sVal => $sLabel) { + $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "separator", htmlentities($sVal, ENT_QUOTES, 'UTF-8'), $sLabel, "radio"); + $oRadio->GetInput()->SetIsChecked(($sVal == $sSeparator)); + $oRadio->SetBeforeInput(false); + $oRadio->GetInput()->AddCSSClass('ibo-input--label-right'); + $oRadio->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oFieldSetSeparator->AddSubBlock($oRadio); + $oFieldSetSeparator->AddSubBlock(new Html('
')); + } + $oPage->add_ready_script("$('[name=\"separator\"]').on('click', function() { DoPreview(); });"); + + //TextQualifierCharacter + $oFieldSetTextQualifier = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:TextQualifierCharacter')); + $oFieldSetTextQualifier->AddCSSClass('ibo-column'); + $oMulticolumn->AddSubBlock($oFieldSetTextQualifier); + + $aQualifiers = array( + '"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'), + '\'' => Dict::S('UI:CSVImport:QualifierSimpleQuote+'), + ); + $aQualifiers['other'] = Dict::S('UI:CSVImport:QualifierOther').' '; + + foreach ($aQualifiers as $sVal => $sLabel) { + $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "text_qualifier", htmlentities($sVal, ENT_QUOTES, 'UTF-8'), $sLabel, "radio"); + $oRadio->GetInput()->SetIsChecked(($sVal == $sTextQualifier)); + $oRadio->SetBeforeInput(false); + $oRadio->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oFieldSetTextQualifier->AddSubBlock($oRadio); + $oFieldSetTextQualifier->AddSubBlock(new Html('
')); + } + $oPage->add_ready_script("$('[name=\"text_qualifier\"]').on('click', function() { DoPreview(); });"); + + //CommentsAndHeader + $oFieldSetCommentsAndHeader = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:CommentsAndHeader')); + $oFieldSetCommentsAndHeader->AddCSSClass('ibo-column'); + $oMulticolumn->AddSubBlock($oFieldSetCommentsAndHeader); + + $oCheckBoxHeader = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('UI:CSVImport:TreatFirstLineAsHeader'), "header_line", "1", "box_header", "checkbox"); + $oCheckBoxHeader->GetInput()->SetIsChecked(($bHeaderLine == 1)); + $oCheckBoxHeader->SetBeforeInput(false); + $oCheckBoxHeader->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oFieldSetCommentsAndHeader->AddSubBlock($oCheckBoxHeader); + $oFieldSetCommentsAndHeader->AddSubBlock(new Html('
')); + + $oCheckBoxSkip = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', ''), "box_skiplines", "1", "box_skiplines", + "checkbox"); + $oCheckBoxSkip->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oCheckBoxSkip->GetInput()->SetIsChecked(($bBoxSkipLines == 1)); + $oCheckBoxSkip->SetBeforeInput(false); + $oFieldSetCommentsAndHeader->AddSubBlock($oCheckBoxSkip); + + $oPage->add_ready_script("$('#box_header').on('click', function() { DoPreview(); });"); + $oPage->add_ready_script("$('#box_skiplines').on('click', function() { DoPreview(); });"); + + //date format + $oFieldSetDate = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:DateAndTimeFormats')); + $oFieldSetDate->AddCSSClass('ibo-column'); + $oMulticolumn->AddSubBlock($oFieldSetDate); + + $sDateTimeFormat = utils::ReadParam('date_time_format', 'default'); + $sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', (string)AttributeDateTime::GetFormat(), false, 'raw_data'); + + $sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8'); + $sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8'); + $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "date_time_format", "default", "radio_date_time_std", "radio"); + $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); + $oRadioDefault->SetBeforeInput(false); + $oRadioDefault->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oFieldSetDate->AddSubBlock($oRadioDefault); + $oFieldSetDate->AddSubBlock(new Html('
')); + + $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sDateTimeFormat), "date_time_format", "custom", "radio_date_time_custom", "radio"); + $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); + $oRadioCustom->SetBeforeInput(false); + $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); + $oFieldSetDate->AddSubBlock($oRadioCustom); + + $oPage->add_ready_script("$('#custom_date_time_format').on('click', function() { DoPreview(); });"); + $oPage->add_ready_script("$('#radio_date_time_std').on('click', function() { DoPreview(); });"); + + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata_truncated", htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8'), "csvdata_truncated")); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("csvdata", htmlentities($sUTF8Data, ENT_QUOTES, 'UTF-8'), 'csvdata')); // The encoding has changed, keep that information within the wizard - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - $oPage->add(''); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("encoding", "UTF-8")); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("class_name", $sClassName)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("advanced", $bAdvanced)); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope)); + + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("field[$iNumber]", $sAttCode)); } - foreach($aSearchFields as $index => $sDummy) - { - $oPage->add(''); + foreach ($aSearchFields as $index => $sDummy) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("search_field[$index]", "1")); } - $oPage->add(''); - if (!empty($sSynchroScope)) - { - foreach($aSynchroUpdate as $sKey => $value) - { - $oPage->add(''); + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", "3")); + if (!empty($sSynchroScope)) { + foreach ($aSynchroUpdate as $sKey => $value) { + $oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_update[$sKey]", $value)); } } - $oPage->add('
'); - $oPage->add('

'.Dict::S('UI:CSVImport:CSVDataPreview').'

'); - $oPage->add('
'); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add('
'); - + $oFieldSetSeparator = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:CSVImport:CSVDataPreview'), "preview"); + $oForm->AddSubBlock($oFieldSetSeparator); + $oFieldSetSeparator->AddSubBlock(new Html("")); + + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForDestructiveAction(Dict::S('UI:Button:Back'))->SetOnClickJsCode("GoBack()")); + $oForm->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), '', "", true)); + $oPage->add_script( -<<add("

".Dict::S('UI:Title:BulkImport+')."

\n"); - $oPage->AddTabContainer('tabs1'); + $oPanel = TitleUIBlockFactory::MakeForPage(Dict::S('UI:Title:BulkImport+')); + $oPage->AddSubBlock($oPanel); + + $oTabContainer = new TabContainer('tabs1', 'import'); + $oPage->AddSubBlock($oTabContainer); + + //** Tab:LoadFromFile */ + $oTabFile = $oTabContainer->AddTab('LoadFromFile', Dict::S('UI:CSVImport:Tab:LoadFromFile')); + $oFormFile = FormUIBlockFactory::MakeStandard(); + $oTabFile->AddSubBlock($oFormFile); + + $oSelectFile = FileSelectUIBlockFactory::MakeStandard("csvdata"); + $oFieldFile = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:SelectFile'), $oSelectFile); + $oFormFile->AddSubBlock($oFieldFile); + + $oSelectEncodingFile = SelectUIBlockFactory::MakeForSelect("encoding"); + $oFieldEncodingFile = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:Encoding'), $oSelectEncodingFile); + $oFormFile->AddSubBlock($oFieldEncodingFile); $sSeparator = utils::ReadParam('separator', '', false, 'raw_data'); $sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data'); @@ -1302,108 +1430,90 @@ EOF $sEncoding = utils::ReadParam('encoding', ''); $sDateTimeFormat = utils::ReadParam('date_time_format', 'default'); $sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', (string)AttributeDateTime::GetFormat(), false, 'raw_data'); - - if ($sEncoding == '') - { + if ($sEncoding == '') { $sEncoding = MetaModel::GetConfig()->Get('csv_file_default_charset'); } $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data'); $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name'); - - $sFileLoadHtml = '

'.Dict::S('UI:CSVImport:SelectFile').'

'. - '

'; - - $sFileLoadHtml .= '

'.Dict::S('UI:CSVImport:Encoding').': '; - $sFileLoadHtml .= '

'; - $sFileLoadHtml .= '

'. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''; - if (!empty($sSynchroScope)) - { - foreach($aSynchroUpdate as $sKey => $value) - { - $sFileLoadHtml .= ''; + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", '2')); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("operation", "file_upload")); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("header_line", $bHeaderLine)); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("nb_skipped_lines", utils::ReadParam('nb_skipped_lines', '0'))); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("box_skiplines", utils::ReadParam('box_skiplines', '0'))); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("class_name", $sClassName)); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("advanced", $bAdvanced)); + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope)); + + if (!empty($sSynchroScope)) { + foreach ($aSynchroUpdate as $sKey => $value) { + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_update['.$sKey.']", $value)); } } - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - $oPage->add(''); + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("['field$iNumber]", $sAttCode)); } - foreach($aSearchFields as $index => $sDummy) - { - $oPage->add(''); + foreach ($aSearchFields as $index => $sDummy) { + $oFormFile->AddSubBlock(InputUIBlockFactory::MakeForHidden("search_field[$index]", "1")); + } + $oToolbarFile = ToolbarUIBlockFactory::MakeForButton(); + $oToolbarFile->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), '', '', true)); + $oFormFile->AddSubBlock($oToolbarFile); + + //** Tab:PasteData */ + $oTabPaste = $oTabContainer->AddTab('UI:CSVImport:Tab:PasteData', Dict::S('UI:CSVImport:Tab:CopyPaste')); + $oFormPaste = FormUIBlockFactory::MakeStandard(); + $oTabPaste->AddSubBlock($oFormPaste); + + + $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data'); + $oTextarea = new TextArea('csvdata', $sCSVData, '', 120, 30); + $oFieldPaste = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:PasteData'), $oTextarea); + $oFormPaste->AddSubBlock($oFieldPaste); + + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("encoding", 'UTF-8')); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", '2')); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("separator", htmlentities($sSeparator, ENT_QUOTES, 'UTF-8'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("text_qualifier", htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("date_time_format", htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("custom_date_time_format", htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("header_line", $bHeaderLine)); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("nb_skipped_lines", utils::ReadParam('nb_skipped_lines', '0'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("box_skiplines", utils::ReadParam('box_skiplines', '0'))); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("class_name", $sClassName)); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("advanced", $bAdvanced)); + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_scope", $sSynchroScope)); + $oFormPaste->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), '', "", true)); + + if (!empty($sSynchroScope)) { + foreach ($aSynchroUpdate as $sKey => $value) { + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("synchro_update[$sKey]", $value)); + } + } + foreach ($aFieldsMapping as $iNumber => $sAttCode) { + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("field[$iNumber]", $sAttCode)); + } + foreach ($aSearchFields as $index => $sDummy) { + $oFormPaste->AddSubBlock(InputUIBlockFactory::MakeForHidden("search_field[$index]", "1")); } - $sFileLoadHtml .= '
'; - - $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:LoadFromFile'), $sFileLoadHtml); - $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data'); - $sPasteDataHtml = '

'.Dict::S('UI:CSVImport:PasteData').'

'. - '

'; - $sPasteDataHtml .= ''; - $sPasteDataHtml .= - '

'. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''; - if (!empty($sSynchroScope)) - { - foreach($aSynchroUpdate as $sKey => $value) - { - $sPasteDataHtml .= ''; - } - } - foreach($aFieldsMapping as $iNumber => $sAttCode) - { - $sPasteDataHtml .= ''; - } - foreach($aSearchFields as $index => $sDummy) - { - $sPasteDataHtml .= ''; - } - $sPasteDataHtml .= '
'; - - $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:CopyPaste'), $sPasteDataHtml); - if (!empty($sCSVData)) - { - // When there are some data, activate the 'copy & paste' tab by default - $oPage->SelectTab('tabs1', Dict::S('UI:CSVImport:Tab:CopyPaste')); - } - $sTemplateHtml = '

'.Dict::S('UI:CSVImport:PickClassForTemplate').' '; - $sTemplateHtml .= GetClassesSelect('template_class', '', 300, UR_ACTION_BULK_MODIFY); - $sTemplateHtml .= '

'; - $sTemplateHtml .= '
'; - $sTemplateHtml .= '
'; - - $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:Templates'), $sTemplateHtml); + /* if (!empty($sCSVData)) { + // When there are some data, activate the 'copy & paste' tab by default + $oPage->SelectTab('tabs1', Dict::S('UI:CSVImport:Tab:CopyPaste')); + }*/ + //Tab:Template + $oTabTemplate = $oTabContainer->AddTab('tabsTemplate', Dict::S('UI:CSVImport:Tab:Templates')); + $oFieldTemplate = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:CSVImport:PickClassForTemplate'), GetClassesSelectUIBlock('template_class', '', UR_ACTION_BULK_MODIFY)); + $oTabTemplate->AddSubBlock($oFieldTemplate); + $oDivTemplate = UIContentBlockUIBlockFactory::MakeStandard("template")->AddCSSClass("ibo-is-visible"); + $oTabTemplate->AddSubBlock($oDivTemplate); + $oPage->add_script( -<<getMessage()); } -} -?> +} \ No newline at end of file diff --git a/sources/application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php b/sources/application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php index 91012d824..4d786d209 100644 --- a/sources/application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php +++ b/sources/application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php @@ -1,5 +1,5 @@ GetDecorationClasses(); - if (!is_null($sDecorationClasses)) { + if (!is_null($sDecorationClasses) && !empty($sDecorationClasses)) { $oBadge->AddHtml(" "); } $oBadge->AddHtml("$sValue"); diff --git a/templates/base/components/datatable/static/formtable/layout.ready.js.twig b/templates/base/components/datatable/static/formtable/layout.ready.js.twig index 749d505a5..133f179ca 100644 --- a/templates/base/components/datatable/static/formtable/layout.ready.js.twig +++ b/templates/base/components/datatable/static/formtable/layout.ready.js.twig @@ -8,6 +8,7 @@ var table{{ oUIBlock.GetId()|sanitize(constant('utils::ENUM_SANITIZATION_FILTER_ filter: false, search: false, dom: "t", + "order": [], }); if ($('#{{ oUIBlock.GetId() }}').find('thead').is(':visible')) { diff --git a/templates/base/components/datatable/static/formtablerow/layout.html.twig b/templates/base/components/datatable/static/formtablerow/layout.html.twig index a4c0d91b3..81826c141 100644 --- a/templates/base/components/datatable/static/formtablerow/layout.html.twig +++ b/templates/base/components/datatable/static/formtablerow/layout.html.twig @@ -1,7 +1,7 @@ {# @copyright Copyright (C) 2010-2021 Combodo SARL #} {# @license http://opensource.org/licenses/AGPL-3.0 #} - + {% for colName,column in oUIBlock.GetColumns() %} {% set cellValueHtml = '' %} @@ -17,3 +17,4 @@ {% endfor %} +