diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 21c644697..4a78cd3cb 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -4025,6 +4025,20 @@ class AttributeDate extends AttributeDateTime public function GetEditClass() {return "Date";} protected function GetSQLCol($bFullSpec = false) {return "DATE";} + + /** + * Override to specify Field class + * + * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the $oFormField is passed, MakeFormField behave more like a Prepare. + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + $oFormField = parent::MakeFormField($oObject, $oFormField); + $oFormField->SetDateOnly(true); + + return $oFormField; + } + } /** diff --git a/core/datetimeformat.class.inc.php b/core/datetimeformat.class.inc.php index 5dfa4d22f..65ce3151f 100644 --- a/core/datetimeformat.class.inc.php +++ b/core/datetimeformat.class.inc.php @@ -214,30 +214,27 @@ class DateTimeFormat /** * Get a date or datetime format string in the Excel format - * @param string $sFormat * @return string The format string using the Excel convention */ - public function ToExcel($sFormat = null) + public function ToExcel() { return $this->Transform('datepicker', "%s"); } /** * Get a date or datetime format string in the moment.js format - * @param string $sFormat * @return string The format string using the moment.js convention */ - public function ToMomentJS($sFormat = null) + public function ToMomentJS() { return $this->Transform('moment', "[%s]", true /* escape all */); } /** * Get a placeholder text for a date or datetime format string - * @param string $sFormat * @return string The placeholder text (localized) */ - public function ToPlaceholder($sFormat = null) + public function ToPlaceholder() { $aMappings = static::GetFormatMapping(); $sResult = ''; diff --git a/dictionaries/de.dictionary.itop.core.php b/dictionaries/de.dictionary.itop.core.php index 8714519c8..8351f9a3a 100644 --- a/dictionaries/de.dictionary.itop.core.php +++ b/dictionaries/de.dictionary.itop.core.php @@ -610,4 +610,18 @@ Operatoren:
'Core:ExplainWTC:ElapsedTime' => 'Abgelaufene Zeit (gespeichert als \"%1$s\")~~', 'Core:ExplainWTC:StopWatch-TimeSpent' => 'Zeitaufwand für \"%1$s\"~~', 'Core:ExplainWTC:StopWatch-Deadline' => 'Deadline für \"%1$s\" um %2$d%%~~', + 'Core:DateTime:Placeholder_d' => 'TT', // Day of the month: 2 digits (with leading zero) + 'Core:DateTime:Placeholder_j' => 'T', // Day of the month: 1 or 2 digits (without leading zero) + 'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12 + 'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12 + 'Core:DateTime:Placeholder_Y' => 'JJJJ', // Year on 4 digits + 'Core:DateTime:Placeholder_y' => 'JJ', // Year on 2 digits + 'Core:DateTime:Placeholder_H' => 'hh', // Hour 00..23 + 'Core:DateTime:Placeholder_h' => 'h', // Hour 01..12 + 'Core:DateTime:Placeholder_G' => 'hh', // Hour 0..23 + 'Core:DateTime:Placeholder_g' => 'h', // Hour 1..12 + 'Core:DateTime:Placeholder_a' => 'am/pm', // am/pm (lowercase) + 'Core:DateTime:Placeholder_A' => 'AM/PM', // AM/PM (uppercase) + 'Core:DateTime:Placeholder_i' => 'mm', // minutes, 2 digits: 00..59 + 'Core:DateTime:Placeholder_s' => 'ss', // seconds, 2 digits 00..59 )); diff --git a/dictionaries/it.dictionary.itop.core.php b/dictionaries/it.dictionary.itop.core.php index 17523e8bb..a0ddbb43d 100644 --- a/dictionaries/it.dictionary.itop.core.php +++ b/dictionaries/it.dictionary.itop.core.php @@ -836,6 +836,20 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array( 'Core:BulkExportLegacyExport' => 'Click here to access the legacy export.~~', 'Core:BulkExport:XLSXOptions' => 'Excel Options~~', 'Core:BulkExport:TextFormat' => 'Text fields containing some HTML markup~~', + 'Core:DateTime:Placeholder_d' => 'GG', // Day of the month: 2 digits (with leading zero) + 'Core:DateTime:Placeholder_j' => 'G', // Day of the month: 1 or 2 digits (without leading zero) + 'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12 + 'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12 + 'Core:DateTime:Placeholder_Y' => 'AAAA', // Year on 4 digits + 'Core:DateTime:Placeholder_y' => 'AA', // Year on 2 digits + 'Core:DateTime:Placeholder_H' => 'hh', // Hour 00..23 + 'Core:DateTime:Placeholder_h' => 'h', // Hour 01..12 + 'Core:DateTime:Placeholder_G' => 'hh', // Hour 0..23 + 'Core:DateTime:Placeholder_g' => 'h', // Hour 1..12 + 'Core:DateTime:Placeholder_a' => 'am/pm', // am/pm (lowercase) + 'Core:DateTime:Placeholder_A' => 'AM/PM', // AM/PM (uppercase) + 'Core:DateTime:Placeholder_i' => 'mm', // minutes, 2 digits: 00..59 + 'Core:DateTime:Placeholder_s' => 'ss', // seconds, 2 digits 00..59 )); ?> diff --git a/dictionaries/ru.dictionary.itop.core.php b/dictionaries/ru.dictionary.itop.core.php index c6e0693cf..6a35f1163 100644 --- a/dictionaries/ru.dictionary.itop.core.php +++ b/dictionaries/ru.dictionary.itop.core.php @@ -844,6 +844,20 @@ Dict::Add('RU RU', 'Russian', 'Русский', array( 'Core:BulkExportLegacyExport' => 'Click here to access the legacy export.~~', 'Core:BulkExport:XLSXOptions' => 'Excel Options~~', 'Core:BulkExport:TextFormat' => 'Text fields containing some HTML markup~~', + 'Core:DateTime:Placeholder_d' => 'дд', // Day of the month: 2 digits (with leading zero) + 'Core:DateTime:Placeholder_j' => 'д', // Day of the month: 1 or 2 digits (without leading zero) + 'Core:DateTime:Placeholder_m' => 'мм', // Month on 2 digits i.e. 01-12 + 'Core:DateTime:Placeholder_n' => 'м', // Month on 1 or 2 digits 1-12 + 'Core:DateTime:Placeholder_Y' => 'гггг', // Year on 4 digits + 'Core:DateTime:Placeholder_y' => 'гг', // Year on 2 digits + 'Core:DateTime:Placeholder_H' => 'чч', // Hour 00..23 + 'Core:DateTime:Placeholder_h' => 'чч', // Hour 01..12 + 'Core:DateTime:Placeholder_G' => 'ч', // Hour 0..23 + 'Core:DateTime:Placeholder_g' => 'ч', // Hour 1..12 + 'Core:DateTime:Placeholder_a' => 'am/pm', // am/pm (lowercase) + 'Core:DateTime:Placeholder_A' => 'AM/PM', // AM/PM (uppercase) + 'Core:DateTime:Placeholder_i' => 'мм', // minutes, 2 digits: 00..59 + 'Core:DateTime:Placeholder_s' => 'сс', // seconds, 2 digits 00..59 )); ?> diff --git a/sources/form/field/datetimefield.class.inc.php b/sources/form/field/datetimefield.class.inc.php index b10730170..3917c50a4 100644 --- a/sources/form/field/datetimefield.class.inc.php +++ b/sources/form/field/datetimefield.class.inc.php @@ -29,9 +29,22 @@ class DateTimeField extends StringField { protected $sJSDateTimeFormat; protected $sPHPDateTimeFormat; - + protected $bDateOnly; + /** + * Overloaded constructor * + * @param string $sId + * @param Closure $onFinalizeCallback (Used in the $oForm->AddField($sId, ..., function() use ($oManager, $oForm, '...') { ... } ); ) + */ + public function __construct($sId, Closure $onFinalizeCallback = null) + { + parent::__construct($sId, $onFinalizeCallback); + $this->bDateOnly = false; + } + + /** + * Get the PHP format string * @return string */ public function GetPHPDateTimeFormat() @@ -51,7 +64,6 @@ class DateTimeField extends StringField } /** - * * @return string */ public function GetJSDateTimeFormat() @@ -74,4 +86,21 @@ class DateTimeField extends StringField { return AttributeDatetime::GetFormat()->Format($this->currentValue); } + + /** + * Set the DateOnly flag + * @return \Combodo\iTop\Form\Field\DateTimeField + */ + public function SetDateOnly($bDateOnly) + { + return $this->bDateOnly = $bDateOnly; + return $this; + } + /** + * @return bool + */ + public function IsDateOnly() + { + return $this->bDateOnly; + } } diff --git a/sources/renderer/console/consoleformrenderer.class.inc.php b/sources/renderer/console/consoleformrenderer.class.inc.php index 624da50b7..fa59c4c23 100644 --- a/sources/renderer/console/consoleformrenderer.class.inc.php +++ b/sources/renderer/console/consoleformrenderer.class.inc.php @@ -41,5 +41,6 @@ class ConsoleFormRenderer extends FormRenderer $this->AddSupportedField('DurationField', 'ConsoleSimpleFieldRenderer'); $this->AddSupportedField('SelectObjectField', 'ConsoleSelectObjectFieldRenderer'); $this->AddSupportedField('SubFormField', 'ConsoleSubFormFieldRenderer'); + $this->AddSupportedField('DateTimeField', 'ConsoleSimpleFieldRenderer'); } } \ No newline at end of file diff --git a/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php b/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php index 90229aecb..b41ab6c31 100644 --- a/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php +++ b/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php @@ -25,6 +25,9 @@ use Combodo\iTop\Form\Field\TextAreaField; use \InlineImage; use \UserRights; use \AttributeDuration; +use \DateTimeFormat; +use \AttributeDateTime; +use \AttributeDate; class ConsoleSimpleFieldRenderer extends FieldRenderer { @@ -47,6 +50,24 @@ class ConsoleSimpleFieldRenderer extends FieldRenderer } switch ($sFieldClass) { + case 'Combodo\\iTop\\Form\\Field\\DateTimeField': + $sDateTimeFormat = $this->oField->GetPHPDateTimeFormat(); + $oFormat = new DateTimeFormat($sDateTimeFormat); + $sPlaceHolder = $oFormat->ToPlaceholder(); + $oOutput->AddHtml(''); + if ($this->oField->GetReadOnly()) + { + $oOutput->AddHtml(''); + $oOutput->AddHtml(''.htmlentities($this->oField->GetCurrentValue(), ENT_QUOTES, 'UTF-8').''); + } + else + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml(''); + $oOutput->AddHtml(''); + break; + case 'Combodo\\iTop\\Form\\Field\\StringField': $oOutput->AddHtml(''); if ($this->oField->GetReadOnly()) @@ -78,7 +99,7 @@ class ConsoleSimpleFieldRenderer extends FieldRenderer { $sEditorLanguage = strtolower(trim(UserRights::GetUserLanguage())); $oOutput->AddJs( - <<oField->GetGlobalId()}').addClass('htmlEditor'); $('#{$this->oField->GetGlobalId()}').ckeditor(function(){}, {language: '$sEditorLanguage', contentsLanguage: '$sEditorLanguage'}); EOF @@ -196,6 +217,82 @@ EOF switch ($sFieldClass) { + case 'Combodo\\iTop\Form\\Field\\DateTimeField': + case 'Combodo\\iTop\\Form\\Field\\DateTimeField': + $sDateTimeFormat = $this->oField->GetPHPDateTimeFormat(); + $oFormat = new DateTimeFormat($sDateTimeFormat); + $sDatePickerFormat = $oFormat->ToDatePicker(); + $sJSDaysMin = json_encode(array(Dict::S('DayOfWeek-Sunday-Min'), Dict::S('DayOfWeek-Monday-Min'), Dict::S('DayOfWeek-Tuesday-Min'), Dict::S('DayOfWeek-Wednesday-Min'), + Dict::S('DayOfWeek-Thursday-Min'), Dict::S('DayOfWeek-Friday-Min'), Dict::S('DayOfWeek-Saturday-Min'))); + $sJSMonthsShort = json_encode(array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'), + Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short'))); + $iFirstDayOfWeek = (int) Dict::S('Calendar-FirstDayOfWeek'); + $sJSDateFormat = json_encode(AttributeDate::GetFormat()->ToDatePicker()); + $sTimeFormat = AttributeDateTime::GetFormat()->ToTimeFormat(); + $oTimeFormat = new DateTimeFormat($sTimeFormat); + $sJSTimeFormat = json_encode($oTimeFormat->ToDatePicker()); + $sJSLangShort = json_encode(strtolower(substr(Dict::GetUserLanguage(), 0, 2))); + $sJSOk = json_encode(Dict::S('UI:Button:Ok')); + if ($this->oField->IsDateOnly()) + { + $oOutput->AddJs( +<<oField->GetGlobalId()}").datepicker({ + showOn: 'button', + buttonImage: '../images/calendar.png', + buttonImageOnly: true, + dateFormat: $sJSDateFormat, + constrainInput: false, + changeMonth: true, + changeYear: true, + dayNamesMin: $sJSDaysMin, + monthNamesShort: $sJSMonthsShort, + firstDay: $iFirstDayOfWeek + }); +EOF + ); + } + else + { + $oOutput->AddJs( +<<oField->GetGlobalId()}").datetimepicker({ + showOn: 'button', + buttonImage: '../images/calendar.png', + buttonImageOnly: true, + dateFormat: $sJSDateFormat, + constrainInput: false, + changeMonth: true, + changeYear: true, + dayNamesMin: $sJSDaysMin, + monthNamesShort: $sJSMonthsShort, + firstDay: $iFirstDayOfWeek, + // time picker options + timeFormat: $sJSTimeFormat, + controlType: 'select', + closeText: $sJSOk + }); +EOF + ); + } + + $oOutput->AddJs( +<<oField->GetGlobalId()}").off("change keyup").on("change keyup", function(){ + var me = this; + + $(this).closest(".field_set").trigger("field_change", { + id: $(me).attr("id"), + name: $(me).closest(".form_field").attr("data-field-id"), + value: $(me).val() + }) + .closest('.form_handler').trigger('value_change'); + }); +EOF + ); + break; + break; + case 'Combodo\\iTop\\Form\\Field\\StringField': case 'Combodo\\iTop\\Form\\Field\\TextAreaField': $oOutput->AddJs(