diff --git a/application/utils.inc.php b/application/utils.inc.php index ab9b3d216..b1f2d2160 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -802,6 +802,7 @@ class utils // Bulk export actions $aResult[] = new JSPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), "ExportListDlg('$sOQL', '$sDataTableId', 'csv', ".json_encode(Dict::S('UI:Menu:CSVExport')).")"); $aResult[] = new JSPopupMenuItem('UI:Menu:ExportXLSX', Dict::S('ExcelExporter:ExportMenu'), "ExportListDlg('$sOQL', '$sDataTableId', 'xlsx', ".json_encode(Dict::S('ExcelExporter:ExportMenu')).")"); + $aResult[] = new JSPopupMenuItem('UI:Menu:ExportPDF', Dict::S('UI:Menu:ExportPDF'), "ExportListDlg('$sOQL', '$sDataTableId', 'pdf', ".json_encode(Dict::S('UI:Menu:ExportPDF')).")"); } $aResult[] = new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL')"); $aResult[] = new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')"); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 16f8ace95..428d7acc8 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -728,7 +728,42 @@ class AttributeLinkedSet extends AttributeDefinition public function GetAsXML($sValue, $oHostObject = null, $bLocalize = true) { - return "Sorry, no yet implemented"; + if (is_object($sValue) && ($sValue instanceof DBObjectSet)) + { + $sValue->Rewind(); + $sRes = "\n"; + while ($oObj = $sValue->Fetch()) + { + $sObjClass = get_class($oObj); + $sRes .= "<$sObjClass id=\"".$oObj->GetKey()."\">\n"; + // Show only relevant information (hide the external key to the current object) + $aAttributes = array(); + foreach(MetaModel::ListAttributeDefs($sObjClass) as $sAttCode => $oAttDef) + { + if ($sAttCode == 'finalclass') + { + if ($sObjClass == $this->GetLinkedClass()) + { + // Simplify the output if the exact class could be determined implicitely + continue; + } + } + if ($sAttCode == $this->GetExtKeyToMe()) continue; + if ($oAttDef->IsExternalField()) continue; + if (!$oAttDef->IsDirectField()) continue; + if (!$oAttDef->IsScalar()) continue; + $sAttValue = $oObj->GetAsXML($sAttCode, $bLocalize); + $sRes .= "<$sAttCode>$sAttValue\n"; + } + $sRes .= "\n"; + } + $sRes .= "\n"; + } + else + { + $sRes = ''; + } + return $sRes; } public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true) @@ -761,7 +796,7 @@ class AttributeLinkedSet extends AttributeDefinition if ($oAttDef->IsExternalField()) continue; if (!$oAttDef->IsDirectField()) continue; if (!$oAttDef->IsScalar()) continue; - $sAttValue = $oObj->GetAsCSV($sAttCode, $sSepValue, ''); + $sAttValue = $oObj->GetAsCSV($sAttCode, $sSepValue, '', $bLocalize); if (strlen($sAttValue) > 0) { $sAttributeData = str_replace($sAttributeQualifier, $sAttributeQualifier.$sAttributeQualifier, $sAttCode.$sSepValue.$sAttValue); @@ -897,7 +932,8 @@ class AttributeLinkedSet extends AttributeDefinition { throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sTargetClass, 'attcode' => $sAttCode)); } - $aValues[$sAttCode] = $sValue; + $oAttDef = MetaModel::GetAttributeDef($sTargetClass, $sAttCode); + $aValues[$sAttCode] = $oAttDef->MakeValueFromString($sValue, $bLocalizedValue, $sSepItem, $sSepAttribute, $sSepValue, $sAttributeQualifier); } } @@ -4530,6 +4566,10 @@ class AttributeStopWatch extends AttributeDefinition switch($sThresholdCode) { case 'deadline': + if ($value != '') + { + $sRet = $sTextQualifier.date(self::GetDateFormat(true /*full*/), $value).$sTextQualifier; + } break; case 'passed': diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index b236c1c80..bc9d7ad90 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -57,6 +57,26 @@ class CSVBulkExport extends TabularBulkExport $this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('character-set', 'UTF-8', true, 'raw_data')); } + + protected function SuggestField($aAliases, $sClass, $sAlias, $sAttCode) + { + switch($sAttCode) + { + case 'id': // replace 'id' by 'friendlyname' + $sAttCode = 'friendlyname'; + break; + + default: + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + if ($oAttDef instanceof AttributeExternalKey) + { + $sAttCode .= '_friendlyname'; + } + } + + return parent::SuggestField($aAliases, $sClass, $sAlias, $sAttCode); + } + public function EnumFormParts() { return array_merge(parent::EnumFormParts(), array('csv_options' => array('separator', 'character-set', 'text-qualifier', 'no_localize') ,'interactive_fields_csv' => array('interactive_fields_csv'))); @@ -153,6 +173,7 @@ class CSVBulkExport extends TabularBulkExport $aAuthorizedClasses[$sAlias] = $sClassName; } } + $aAliases = array_keys($aAuthorizedClasses); $aData = array(); foreach($this->aStatusInfo['fields'] as $sExtendedAttCode) { @@ -163,46 +184,47 @@ class CSVBulkExport extends TabularBulkExport } else { - $sAlias = reset($aAuthorizedClasses); + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aAuthorizedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aAuthorizedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } $sClass = $aAuthorizedClasses[$sAlias]; - if ($this->aStatusInfo['localize']) + switch($sAttCode) { - switch($sAttCode) + case 'id': + $sLabel = 'id'; + break; + + default: + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + if ($oAttDef instanceof AttributeExternalField) { - case 'id': - if (count($aAuthorizedClasses) > 1) - { - $aData[] = $sAlias.'.id'; - } - else - { - $aData[] = 'id'; - } - break; - - default: - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $sLabel = $this->aStatusInfo['localize'] ? $oAttDef->GetLabel() : $sAttCode; - if (count($aAuthorizedClasses) > 1) - { - $aData[] = $sAlias.'.'.$sLabel; - } - else - { - $aData[] = $sLabel; - } + if ($this->aStatusInfo['localize']) + { + $sStar = $oAttDef->IsNullAllowed() ? '' : '*'; + $sLabel = $oAttDef->GetKeyAttDef()->GetLabel().$sStar.'->'.$oAttDef->GetExtAttDef()->GetLabel(); + } + else + { + $sLabel = $oAttDef->GetKeyAttDef()->GetCode().'->'.$oAttDef->GetExtAttDef()->GetCode(); + } } + else + { + $sLabel = $this->aStatusInfo['localize'] ? $oAttDef->GetLabel() : $sAttCode; + } + } + if (count($aAuthorizedClasses) > 1) + { + $aData[] = $sAlias.'.'.$sLabel; } else { - $aData[] = $sExtendedAttCode; + $aData[] = $sLabel; } } $sFrom = array("\r\n", $this->aStatusInfo['text_qualifier']); @@ -239,6 +261,7 @@ class CSVBulkExport extends TabularBulkExport $aAuthorizedClasses[$sAlias] = $sClassName; } } + $aAliases = array_keys($aAuthorizedClasses); $oSet->SetLimit($this->iChunkSize, $this->aStatusInfo['position']); $aAliasByField = array(); @@ -254,13 +277,13 @@ class CSVBulkExport extends TabularBulkExport } else { - $sAlias = reset($aAuthorizedClasses); + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aAuthorizedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aAuthorizedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } if (!array_key_exists($sAlias, $aColumnsToLoad)) diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index 69743db5d..1d33bccd1 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -102,6 +102,14 @@ class ExcelBulkExport extends TabularBulkExport $this->aStatusInfo['total'] = $oSet->Count(); $aSelectedClasses = $this->oSearch->GetSelectedClasses(); + foreach($aSelectedClasses as $sAlias => $sClassName) + { + if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) + { + $aAuthorizedClasses[$sAlias] = $sClassName; + } + } + $aAliases = array_keys($aAuthorizedClasses); $aTableHeaders = array(); foreach($this->aStatusInfo['fields'] as $sExtendedAttCode) { @@ -112,12 +120,12 @@ class ExcelBulkExport extends TabularBulkExport } else { - $sAlias = reset($aSelectedClasses); + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aSelectedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aSelectedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } $sClass = $aSelectedClasses[$sAlias]; @@ -170,6 +178,7 @@ class ExcelBulkExport extends TabularBulkExport $hFile = fopen($this->aStatusInfo['tmp_file'], 'ab'); $oSet = new DBObjectSet($this->oSearch); $aSelectedClasses = $this->oSearch->GetSelectedClasses(); + $aAliases = array_keys($aSelectedClasses); $oSet->SetLimit($this->iChunkSize, $this->aStatusInfo['position']); $aAliasByField = array(); @@ -185,13 +194,13 @@ class ExcelBulkExport extends TabularBulkExport } else { - $sAlias = reset($aSelectedClasses); + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aSelectedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aSelectedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } if (!array_key_exists($sAlias, $aColumnsToLoad)) @@ -224,7 +233,22 @@ class ExcelBulkExport extends TabularBulkExport break; default: - $sField = $aRow[$aAttCode['alias']]->Get($aAttCode['attcode']); + $value = $aRow[$aAttCode['alias']]->Get($aAttCode['attcode']); + if ($value instanceOf ormCaseLog) + { + // Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it! + $sField = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText())); + } + else if ($value instanceOf DBObjectSet) + { + $oAttDef = MetaModel::GetAttributeDef(get_class($aRow[$aAttCode['alias']]), $aAttCode['attcode']); + $sField = $oAttDef->GetAsCSV($value, '', '', $aRow[$aAttCode['alias']]); + } + else + { + $oAttDef = MetaModel::GetAttributeDef(get_class($aRow[$aAttCode['alias']]), $aAttCode['attcode']); + $sField = $oAttDef->GetEditValue($value, $aRow[$aAttCode['alias']]); + } } $aData[] = $sField; } diff --git a/core/htmlbulkexport.class.inc.php b/core/htmlbulkexport.class.inc.php index be3ff36ad..fe27256fb 100644 --- a/core/htmlbulkexport.class.inc.php +++ b/core/htmlbulkexport.class.inc.php @@ -56,12 +56,22 @@ class HTMLBulkExport extends TabularBulkExport public function GetHeader() { + $sData = ''; + $oSet = new DBObjectSet($this->oSearch); $this->aStatusInfo['status'] = 'running'; $this->aStatusInfo['position'] = 0; $this->aStatusInfo['total'] = $oSet->Count(); $aSelectedClasses = $this->oSearch->GetSelectedClasses(); + foreach($aSelectedClasses as $sAlias => $sClassName) + { + if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) + { + $aAuthorizedClasses[$sAlias] = $sClassName; + } + } + $aAliases = array_keys($aAuthorizedClasses); $aData = array(); foreach($this->aStatusInfo['fields'] as $sExtendedAttCode) { @@ -72,12 +82,13 @@ class HTMLBulkExport extends TabularBulkExport } else { - $sAlias = reset($aSelectedClasses); + + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aSelectedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aSelectedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } $sClass = $aSelectedClasses[$sAlias]; @@ -106,7 +117,7 @@ class HTMLBulkExport extends TabularBulkExport } } } - $sData = "\n"; + $sData .= "
\n"; $sData .= "\n"; $sData .= "\n"; foreach($aData as $sLabel) @@ -126,6 +137,7 @@ class HTMLBulkExport extends TabularBulkExport $oSet = new DBObjectSet($this->oSearch); $aSelectedClasses = $this->oSearch->GetSelectedClasses(); + $aAliases = array_keys($aSelectedClasses); $oSet->SetLimit($this->iChunkSize, $this->aStatusInfo['position']); $aAliasByField = array(); @@ -141,13 +153,13 @@ class HTMLBulkExport extends TabularBulkExport } else { - $sAlias = reset($aSelectedClasses); + $sAlias = reset($aAliases); $sAttCode = $sExtendedAttCode; } - if (!array_key_exists($sAlias, $aSelectedClasses)) + if (!in_array($sAlias, $aAliases)) { - throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", array_keys($aSelectedClasses))."'"); + throw new Exception("Invalid alias '$sAlias' for the column '$sExtendedAttCode'. Availables aliases: '".implode("', '", $aAliases)."'"); } if (!array_key_exists($sAlias, $aColumnsToLoad)) @@ -170,7 +182,7 @@ class HTMLBulkExport extends TabularBulkExport while($aRow = $oSet->FetchAssoc()) { set_time_limit($iLoopTimeLimit); - $sFirstAlias = reset($aSelectedClasses); + $sFirstAlias = reset($aAliases); $sHilightClass = $aRow[$sFirstAlias]->GetHilightClass(); if ($sHilightClass != '') { @@ -222,7 +234,6 @@ class HTMLBulkExport extends TabularBulkExport { $sData = "\n"; $sData .= "
\n"; - return $sData; } diff --git a/core/tabularbulkexport.class.inc.php b/core/tabularbulkexport.class.inc.php index f1640c558..82b228c19 100644 --- a/core/tabularbulkexport.class.inc.php +++ b/core/tabularbulkexport.class.inc.php @@ -266,18 +266,6 @@ EOF return true; //$oAttDef->IsScalar(); } - /** - * Tells if the specified field is part of the "advanced" fields - * @param unknown $sClass - * @param unknown $sAttCode - * @param AttributeDefinition $oAttDef Can be null when $sAttCode == 'id' - * @return boolean - */ - protected function IsAdvancedValidField($sClass, $sAttCode, $oAttDef = null) - { - return (($sAttCode == 'id') || ($oAttDef instanceof AttributeExternalKey)); - } - protected function GetSampleData(DBObject $oObj, $sAttCode) { if ($oObj == null) return ''; @@ -306,10 +294,14 @@ EOF if ($oQueries->Count() > 0) { $oQuery = $oQueries->Fetch(); - $sFields = trim($oQuery->Get('fields')); - if ($sFields === '') + if (($sFields === null) || ($sFields === '')) { - throw new BulkExportMissingParameterException('fields'); + // No 'fields' parameter supplied, take the fields from the query phrasebook definition + $sFields = trim($oQuery->Get('fields')); + if ($sFields === '') + { + throw new BulkExportMissingParameterException('fields'); + } } } else @@ -318,6 +310,12 @@ EOF } } - $this->aStatusInfo['fields'] = explode(',', $sFields); + $aFields = explode(',', $sFields); + $this->aStatusInfo['fields'] = array(); + foreach($aFields as $sField) + { + // Trim the values since it's too temping to write: fields=name, first_name, org_name instead of fields=name,first_name,org_name + $this->aStatusInfo['fields'][] = trim($sField); + } } } diff --git a/core/xmlbulkexport.class.inc.php b/core/xmlbulkexport.class.inc.php index 022a8a16b..f6b28d40b 100644 --- a/core/xmlbulkexport.class.inc.php +++ b/core/xmlbulkexport.class.inc.php @@ -133,13 +133,10 @@ class XMLBulkExport extends BulkExport } else { - if ($oAttDef->IsWritable()) + if ($oAttDef->IsWritable() ) { - if (!$oAttDef->IsLinkSet()) - { - $sValue = $oObj->GetAsXML($sAttCode, $bLocalize); - $sData .= "<$sAttCode>$sValue\n"; - } + $sValue = $oObj->GetAsXML($sAttCode, $bLocalize); + $sData .= "<$sAttCode>$sValue\n"; } } } diff --git a/css/light-grey.css b/css/light-grey.css index e3aa0e624..b21edd240 100644 --- a/css/light-grey.css +++ b/css/light-grey.css @@ -1962,9 +1962,8 @@ table.export_parameters td { } -.table_preview .nodragtable-sortable li { - border: 1px #555555 solid; - font-size: 10pt; +.table_preview .drag-handle { + cursor: move; } diff --git a/css/light-grey.scss b/css/light-grey.scss index 4a53a929a..814cb531a 100644 --- a/css/light-grey.scss +++ b/css/light-grey.scss @@ -1450,7 +1450,6 @@ table.export_parameters td { padding-right: 0.25em; font-size: 10pt; } -.table_preview .nodragtable-sortable li { - border: 1px $grey-color solid; - font-size: 10pt; +.table_preview .drag-handle { + cursor: move; } \ No newline at end of file diff --git a/dictionaries/de.dictionary.itop.core.php b/dictionaries/de.dictionary.itop.core.php index 93017524f..1b31f9753 100644 --- a/dictionaries/de.dictionary.itop.core.php +++ b/dictionaries/de.dictionary.itop.core.php @@ -582,4 +582,7 @@ Operatoren:
'Core:BulkExportLabelPhrasebookEntry' => 'Query Phrasebook Entry:~~', 'Core:BulkExportMessageEmptyOQL' => 'Please enter a valid OQL query.~~', 'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Please select a valid phrasebook entry.~~', + 'Core:BulkExportQueryPlaceholder' => 'Type an OQL query here...~~', + 'Core:BulkExportCanRunNonInteractive' => 'Click here to run the export in non-interactive mode.~~', + 'Core:BulkExportLegacyExport' => 'Click here to access the legacy export.~~', )); diff --git a/dictionaries/de.dictionary.itop.ui.php b/dictionaries/de.dictionary.itop.ui.php index d5769d3fd..8aedeb59e 100644 --- a/dictionaries/de.dictionary.itop.ui.php +++ b/dictionaries/de.dictionary.itop.ui.php @@ -1020,5 +1020,7 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm 'UI:CurrentObjectLockExpired_Explanation' => 'The lock to prevent concurrent modifications of the object has expired. You can no longer submit your modification since other users are now allowed to modify this object.~~', 'UI:ConcurrentLockKilled' => 'The lock preventing modifications on the current object has been deleted.~~', 'UI:Menu:KillConcurrentLock' => 'Kill the Concurrent Modification Lock !~~', + + 'UI:Menu:ExportPDF' => 'Export as PDF...~~', )); ?> diff --git a/dictionaries/dictionary.itop.core.php b/dictionaries/dictionary.itop.core.php index e5a31b6e9..14ab263a5 100644 --- a/dictionaries/dictionary.itop.core.php +++ b/dictionaries/dictionary.itop.core.php @@ -831,5 +831,7 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:BulkExportLabelPhrasebookEntry' => 'Query Phrasebook Entry:', 'Core:BulkExportMessageEmptyOQL' => 'Please enter a valid OQL query.', 'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Please select a valid phrasebook entry.', - + 'Core:BulkExportQueryPlaceholder' => 'Type an OQL query here...', + 'Core:BulkExportCanRunNonInteractive' => 'Click here to run the export in non-interactive mode.', + 'Core:BulkExportLegacyExport' => 'Click here to access the legacy export.', )); diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index 08a94027f..226c90729 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -1286,5 +1286,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:CurrentObjectLockExpired_Explanation' => 'The lock to prevent concurrent modifications of the object has expired. You can no longer submit your modification since other users are now allowed to modify this object.', 'UI:ConcurrentLockKilled' => 'The lock preventing modifications on the current object has been deleted.', 'UI:Menu:KillConcurrentLock' => 'Kill the Concurrent Modification Lock !', + + 'UI:Menu:ExportPDF' => 'Export as PDF...', )); ?> diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index 106430408..5db781c81 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -689,7 +689,10 @@ Opérateurs :
'Core:BulkExport:OptionNoLocalize' => 'Ne pas traduire les valeurs (pour les champs de type "Enum")', 'Core:BulkExport:ScopeDefinition' => 'Définition des objets à exporter', 'Core:BulkExportLabelOQLExpression' => 'Requête OQL:', - 'Core:BulkExportLabelPhrasebookEntry' => 'Entrée dans le livre des requêtes:', + 'Core:BulkExportLabelPhrasebookEntry' => 'Entrée du livre des requêtes:', 'Core:BulkExportMessageEmptyOQL' => 'Veuillez saisir une requête OQL valide.', 'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Veuillez sélectionner une entrée dans le livre des requêtes.', + 'Core:BulkExportQueryPlaceholder' => 'Saisissez une requête OQL...', + 'Core:BulkExportCanRunNonInteractive' => 'Cliquez ici pour exécuter l\'export en mode non-interactif.', + 'Core:BulkExportLegacyExport' => 'Cliquez ici pour exécuter l\'ancienne version de l\'export.', )); diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 4b3e5d148..c8b16404c 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -1128,5 +1128,6 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'UI:CurrentObjectLockExpired_Explanation' => 'Le verrouillage interdisant les modifications concurrentes a expiré. Vos modifications ne peuvent pas être acceptées car d\'autres utilisateurs peuvent modifier cet objet.', 'UI:ConcurrentLockKilled' => 'Le verrouillage en édition de l\'objet courant a été supprimé.', 'UI:Menu:KillConcurrentLock' => 'Supprimer le verrouillage !', -)); -?> \ No newline at end of file + + 'UI:Menu:ExportPDF' => 'Exporter en PDF...', +)); \ No newline at end of file diff --git a/js/tabularfieldsselector.js b/js/tabularfieldsselector.js index f80b14962..f97d443ad 100644 --- a/js/tabularfieldsselector.js +++ b/js/tabularfieldsselector.js @@ -36,11 +36,10 @@ $(function() this.element.parent().bind('validate', function() { me.validate(); }); this.aSelected = []; - var sContent = ''; for(var i in this.options.fields) { - sContent += '
'+this._format(this.options.labels.columns_selection, i)+''; + var sContent = '
'+this._format(this.options.labels.columns_selection, i)+''; sContent += '
 
'; for(var j in this.options.fields[i]) { @@ -409,6 +408,7 @@ $(function() return sTooltipContent; }, items: '.tfs_advanced', + tooltipClass: 'tooltip-tfs', position: { my: "center bottom-10", at: "center top", @@ -458,6 +458,9 @@ $(function() var sDataId = $(this).attr('data-attcode'); $('#'+me.sId+' .tfs_advanced[data-attcode="'+sDataId+'"]').tooltip('close'); }); + this.element.parent().on("click", ":not(.tooltip-tfs *,.tooltip-tfs)", function(){ + me.close_all_tooltips(); + }); }, _get_tooltip_content: function(sDataAttCode) { @@ -505,9 +508,11 @@ $(function() } return sContent; }, - _close_all_tooltips: function() + close_all_tooltips: function() { - this.element.find('.tfs_item').tooltip('close'); + $('.tfs_advanced').each(function (i) { + $(this).tooltip("close"); + }); } }); }); \ No newline at end of file diff --git a/js/utils.js b/js/utils.js index 63b3167f7..fed4cb42f 100644 --- a/js/utils.js +++ b/js/utils.js @@ -483,6 +483,7 @@ function ExportStartExport() } } }); + $(':itop-tabularfieldsselector:visible').tabularfieldsselector('close_all_tooltips'); $('#export-form').hide(); $('#export-feedback').show(); oParams.operation = 'export_build'; diff --git a/webservices/export-v2.php b/webservices/export-v2.php index cc978126d..7031d84c1 100644 --- a/webservices/export-v2.php +++ b/webservices/export-v2.php @@ -123,7 +123,7 @@ function DisplayExpressionForm(WebPage $oP, $sAction, $sExpression = '', $sExcep $oP->add(''); $sExpressionHint = empty($sExceptionMessage) ? '' : ''; $oP->add(''); - $oP->add(''); + $oP->add(''); $oP->add($sExpressionHint); $oP->add(''); $oP->add('
'.htmlentities($sExceptionMessage, ENT_QUOTES, 'UTF-8').'
'); $oP->add(''); $oP->add('
'); + $oP->p(''.Dict::S('Core:BulkExportCanRunNonInteractive').''); + $oP->p(''.Dict::S('Core:BulkExportLegacyExport').''); $sJSEmptyOQL = json_encode(Dict::S('Core:BulkExportMessageEmptyOQL')); $sJSEmptyQueryId = json_encode(Dict::S('Core:BulkExportMessageEmptyPhrasebookEntry')); @@ -232,12 +234,14 @@ function DisplayForm(WebPage $oP, $sAction = '', $sExpression = '', $sQueryId = if ($sFormat == null) { // No specific format chosen + $sDefaultFormat = utils::ReadParam('format', 'xlsx'); $oP->add('

'.Dict::S('Core:BulkExport:ExportFormatPrompt').'