* Seperate properties for input ng-model and datepicker. Since flatpickr can't handle custom formatting. * Set picker format to default.
This commit is contained in:
@@ -1,209 +1,211 @@
|
||||
function dateTimePickerController($scope, angularHelper, dateHelper, validationMessageService) {
|
||||
|
||||
let flatPickr = null;
|
||||
let flatPickr = null;
|
||||
|
||||
function onInit() {
|
||||
function onInit() {
|
||||
|
||||
$scope.hasDatetimePickerValue = $scope.model.value ? true : false;
|
||||
$scope.model.datetimePickerValue = null;
|
||||
$scope.serverTime = null;
|
||||
$scope.serverTimeNeedsOffsetting = false;
|
||||
$scope.hasDatetimePickerValue = $scope.model.value ? true : false;
|
||||
$scope.model.datetimePickerValue = null;
|
||||
$scope.serverTime = null;
|
||||
$scope.serverTimeNeedsOffsetting = false;
|
||||
|
||||
// setup the default config
|
||||
var config = {
|
||||
pickTime: true,
|
||||
useSeconds: true,
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
icons: {
|
||||
time: "icon-time",
|
||||
date: "icon-calendar",
|
||||
up: "icon-chevron-up",
|
||||
down: "icon-chevron-down"
|
||||
}
|
||||
};
|
||||
|
||||
// map the user config
|
||||
$scope.model.config = Utilities.extend(config, $scope.model.config);;
|
||||
|
||||
// ensure the format doesn't get overwritten with an empty string
|
||||
if ($scope.model.config.format === "" || $scope.model.config.format === undefined || $scope.model.config.format === null) {
|
||||
$scope.model.config.format = $scope.model.config.pickTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
|
||||
}
|
||||
|
||||
// check whether a server time offset is needed
|
||||
if (Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) {
|
||||
// Will return something like 120
|
||||
var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset;
|
||||
|
||||
// Will return something like -120
|
||||
var localOffset = new Date().getTimezoneOffset();
|
||||
|
||||
// If these aren't equal then offsetting is needed
|
||||
// note the minus in front of serverOffset needed
|
||||
// because C# and javascript return the inverse offset
|
||||
$scope.serverTimeNeedsOffsetting = (-serverOffset !== localOffset);
|
||||
}
|
||||
|
||||
const dateFormat = $scope.model.config.pickTime ? "Y-m-d H:i:S" : "Y-m-d";
|
||||
|
||||
// date picker config
|
||||
$scope.datePickerConfig = {
|
||||
enableTime: $scope.model.config.pickTime,
|
||||
dateFormat: dateFormat,
|
||||
time_24hr: true,
|
||||
clickOpens: !$scope.readonly
|
||||
};
|
||||
|
||||
// Don't show calendar if date format has been set to only time
|
||||
const timeFormat = $scope.model.config.format.toLowerCase();
|
||||
const timeFormatPattern = /^h{1,2}:m{1,2}(:s{1,2})?\s?a?$/gmi;
|
||||
if (timeFormat.match(timeFormatPattern)) {
|
||||
$scope.datePickerConfig.enableTime = true;
|
||||
$scope.datePickerConfig.noCalendar = true;
|
||||
}
|
||||
|
||||
setDatePickerVal();
|
||||
|
||||
// Set the message to use for when a mandatory field isn't completed.
|
||||
// Will either use the one provided on the property type or a localised default.
|
||||
validationMessageService.getMandatoryMessage($scope.model.validation).then(function (value) {
|
||||
$scope.mandatoryMessage = value;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.clearDate = function() {
|
||||
$scope.hasDatetimePickerValue = false;
|
||||
if($scope.model) {
|
||||
$scope.model.datetimePickerValue = null;
|
||||
$scope.model.value = null;
|
||||
}
|
||||
if($scope.datePickerForm && $scope.datePickerForm.datepicker) {
|
||||
$scope.datePickerForm.datepicker.$setValidity("pickerError", true);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.datePickerSetup = function(instance) {
|
||||
flatPickr = instance;
|
||||
// setup the default config
|
||||
var config = {
|
||||
pickTime: true,
|
||||
useSeconds: true,
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
icons: {
|
||||
time: "icon-time",
|
||||
date: "icon-calendar",
|
||||
up: "icon-chevron-up",
|
||||
down: "icon-chevron-down"
|
||||
}
|
||||
};
|
||||
|
||||
$scope.datePickerChange = function(date) {
|
||||
const momentDate = moment(date);
|
||||
// map the user config
|
||||
$scope.model.config = Utilities.extend(config, $scope.model.config);;
|
||||
|
||||
// ensure the format doesn't get overwritten with an empty string
|
||||
if ($scope.model.config.format === "" || $scope.model.config.format === undefined || $scope.model.config.format === null) {
|
||||
$scope.model.config.format = $scope.model.config.pickTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
|
||||
}
|
||||
|
||||
// check whether a server time offset is needed
|
||||
if (Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) {
|
||||
// Will return something like 120
|
||||
var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset;
|
||||
|
||||
// Will return something like -120
|
||||
var localOffset = new Date().getTimezoneOffset();
|
||||
|
||||
// If these aren't equal then offsetting is needed
|
||||
// note the minus in front of serverOffset needed
|
||||
// because C# and javascript return the inverse offset
|
||||
$scope.serverTimeNeedsOffsetting = (-serverOffset !== localOffset);
|
||||
}
|
||||
|
||||
const dateFormat = $scope.model.config.pickTime ? "Y-m-d H:i:S" : "Y-m-d";
|
||||
|
||||
// date picker config
|
||||
$scope.datePickerConfig = {
|
||||
enableTime: $scope.model.config.pickTime,
|
||||
dateFormat: dateFormat,
|
||||
time_24hr: true,
|
||||
clickOpens: !$scope.readonly
|
||||
};
|
||||
|
||||
// Don't show calendar if date format has been set to only time
|
||||
const timeFormat = $scope.model.config.format.toLowerCase();
|
||||
const timeFormatPattern = /^h{1,2}:m{1,2}(:s{1,2})?\s?a?$/gmi;
|
||||
if (timeFormat.match(timeFormatPattern)) {
|
||||
$scope.datePickerConfig.enableTime = true;
|
||||
$scope.datePickerConfig.noCalendar = true;
|
||||
}
|
||||
|
||||
setDatePickerVal();
|
||||
|
||||
// Set the message to use for when a mandatory field isn't completed.
|
||||
// Will either use the one provided on the property type or a localised default.
|
||||
validationMessageService.getMandatoryMessage($scope.model.validation).then(function (value) {
|
||||
$scope.mandatoryMessage = value;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.clearDate = function () {
|
||||
$scope.hasDatetimePickerValue = false;
|
||||
if ($scope.model) {
|
||||
$scope.model.datetimePickerValue = null;
|
||||
$scope.model.value = null;
|
||||
}
|
||||
if ($scope.datePickerForm && $scope.datePickerForm.datepicker) {
|
||||
$scope.datePickerForm.datepicker.$setValidity("pickerError", true);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.datePickerSetup = function (instance) {
|
||||
flatPickr = instance;
|
||||
};
|
||||
|
||||
$scope.datePickerChange = function (date) {
|
||||
const momentDate = moment(date);
|
||||
setDate(momentDate);
|
||||
setDatePickerVal();
|
||||
};
|
||||
|
||||
$scope.inputChanged = function () {
|
||||
if ($scope.model.datetimePickerValue === "" && $scope.hasDatetimePickerValue) {
|
||||
// $scope.hasDatetimePickerValue indicates that we had a value before the input was changed,
|
||||
// but now the input is empty.
|
||||
$scope.clearDate();
|
||||
} else if ($scope.model.datetimePickerValue) {
|
||||
var momentDate = moment($scope.model.datetimePickerInputValue, $scope.model.config.format, true);
|
||||
if (!momentDate || !momentDate.isValid()) {
|
||||
momentDate = moment(new Date($scope.model.datetimePickerInputValue));
|
||||
}
|
||||
if (momentDate && momentDate.isValid()) {
|
||||
setDate(momentDate);
|
||||
setDatePickerVal();
|
||||
};
|
||||
|
||||
$scope.inputChanged = function () {
|
||||
if ($scope.model.datetimePickerValue === "" && $scope.hasDatetimePickerValue) {
|
||||
// $scope.hasDatetimePickerValue indicates that we had a value before the input was changed,
|
||||
// but now the input is empty.
|
||||
$scope.clearDate();
|
||||
} else if ($scope.model.datetimePickerValue) {
|
||||
var momentDate = moment($scope.model.datetimePickerValue, $scope.model.config.format, true);
|
||||
if (!momentDate || !momentDate.isValid()) {
|
||||
momentDate = moment(new Date($scope.model.datetimePickerValue));
|
||||
}
|
||||
if (momentDate && momentDate.isValid()) {
|
||||
setDate(momentDate);
|
||||
}
|
||||
setDatePickerVal();
|
||||
flatPickr.setDate($scope.model.datetimePickerValue, false);
|
||||
}
|
||||
}
|
||||
setDatePickerVal();
|
||||
flatPickr.setDate($scope.model.datetimePickerValue, false);
|
||||
}
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
if (newVal != oldVal) {
|
||||
//check for c# System.DateTime.MinValue being passed as the clear indicator
|
||||
var minDate = moment('0001-01-01');
|
||||
var newDate = moment(newVal);
|
||||
}
|
||||
|
||||
if (newDate.isAfter(minDate)) {
|
||||
setDate(newDate);
|
||||
} else {
|
||||
$scope.clearDate();
|
||||
}
|
||||
}
|
||||
};
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
if (newVal != oldVal) {
|
||||
//check for c# System.DateTime.MinValue being passed as the clear indicator
|
||||
var minDate = moment('0001-01-01');
|
||||
var newDate = moment(newVal);
|
||||
|
||||
function setDate(momentDate) {
|
||||
angularHelper.safeApply($scope, function() {
|
||||
// when a date is changed, update the model
|
||||
if (momentDate && momentDate.isValid()) {
|
||||
$scope.datePickerForm.datepicker.$setValidity("pickerError", true);
|
||||
$scope.hasDatetimePickerValue = true;
|
||||
$scope.model.datetimePickerValue = momentDate.format($scope.model.config.format);
|
||||
}
|
||||
else {
|
||||
$scope.hasDatetimePickerValue = false;
|
||||
$scope.model.datetimePickerValue = null;
|
||||
}
|
||||
updateModelValue(momentDate);
|
||||
});
|
||||
if (newDate.isAfter(minDate)) {
|
||||
setDate(newDate);
|
||||
} else {
|
||||
$scope.clearDate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function updateModelValue(momentDate) {
|
||||
var curMoment = moment($scope.model.value);
|
||||
if ($scope.hasDatetimePickerValue) {
|
||||
if ($scope.model.config.pickTime) {
|
||||
//check if we are supposed to offset the time
|
||||
if ($scope.model.value && Object.toBoolean($scope.model.config.offsetTime) && Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) {
|
||||
$scope.model.value = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset);
|
||||
$scope.serverTime = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z");
|
||||
}
|
||||
else {
|
||||
$scope.model.value = momentDate.format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
function setDate(momentDate) {
|
||||
angularHelper.safeApply($scope, function () {
|
||||
// when a date is changed, update the model
|
||||
if (momentDate && momentDate.isValid()) {
|
||||
$scope.datePickerForm.datepicker.$setValidity("pickerError", true);
|
||||
$scope.hasDatetimePickerValue = true;
|
||||
$scope.model.datetimePickerValue = momentDate.format($scope.model.config.format);
|
||||
}
|
||||
else {
|
||||
$scope.hasDatetimePickerValue = false;
|
||||
$scope.model.datetimePickerValue = null;
|
||||
}
|
||||
updateModelValue(momentDate);
|
||||
});
|
||||
}
|
||||
|
||||
function updateModelValue(momentDate) {
|
||||
var curMoment = moment($scope.model.value);
|
||||
if ($scope.hasDatetimePickerValue) {
|
||||
if ($scope.model.config.pickTime) {
|
||||
//check if we are supposed to offset the time
|
||||
if ($scope.model.value && Object.toBoolean($scope.model.config.offsetTime) && Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) {
|
||||
$scope.model.value = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset);
|
||||
$scope.serverTime = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z");
|
||||
}
|
||||
else {
|
||||
$scope.model.value = momentDate.format("YYYY-MM-DD");
|
||||
$scope.model.value = momentDate.format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$scope.model.value = null;
|
||||
}
|
||||
|
||||
if (!curMoment.isSame(momentDate)) {
|
||||
setDirty();
|
||||
$scope.model.value = momentDate.format("YYYY-MM-DD");
|
||||
}
|
||||
}
|
||||
|
||||
function setDirty() {
|
||||
if ($scope.datePickerForm) {
|
||||
$scope.datePickerForm.datepicker.$setDirty();
|
||||
}
|
||||
else {
|
||||
$scope.model.value = null;
|
||||
}
|
||||
|
||||
/** Sets the value of the date picker control adn associated viewModel objects based on the model value */
|
||||
function setDatePickerVal() {
|
||||
if ($scope.model.value) {
|
||||
var dateVal;
|
||||
//check if we are supposed to offset the time
|
||||
if ($scope.model.value && Object.toBoolean($scope.model.config.offsetTime) && $scope.serverTimeNeedsOffsetting) {
|
||||
//get the local time offset from the server
|
||||
dateVal = dateHelper.convertToLocalMomentTime($scope.model.value, Umbraco.Sys.ServerVariables.application.serverTimeOffset);
|
||||
$scope.serverTime = dateHelper.convertToServerStringTime(dateVal, Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z");
|
||||
}
|
||||
else {
|
||||
//create a normal moment , no offset required
|
||||
dateVal = $scope.model.value ? moment($scope.model.value, "YYYY-MM-DD HH:mm:ss") : moment();
|
||||
}
|
||||
$scope.model.datetimePickerValue = dateVal.format($scope.model.config.format);
|
||||
}
|
||||
else {
|
||||
$scope.clearDate();
|
||||
}
|
||||
if (!curMoment.isSame(momentDate)) {
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$watch("model.value", function(newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
$scope.hasDatetimePickerValue = newVal ? true : false;
|
||||
setDatePickerVal();
|
||||
}
|
||||
});
|
||||
function setDirty() {
|
||||
if ($scope.datePickerForm) {
|
||||
$scope.datePickerForm.datepicker.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the value of the date picker control adn associated viewModel objects based on the model value */
|
||||
function setDatePickerVal() {
|
||||
if ($scope.model.value) {
|
||||
var dateVal;
|
||||
//check if we are supposed to offset the time
|
||||
if ($scope.model.value && Object.toBoolean($scope.model.config.offsetTime) && $scope.serverTimeNeedsOffsetting) {
|
||||
//get the local time offset from the server
|
||||
dateVal = dateHelper.convertToLocalMomentTime($scope.model.value, Umbraco.Sys.ServerVariables.application.serverTimeOffset);
|
||||
$scope.serverTime = dateHelper.convertToServerStringTime(dateVal, Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z");
|
||||
}
|
||||
else {
|
||||
//create a normal moment , no offset required
|
||||
dateVal = $scope.model.value ? moment($scope.model.value, "YYYY-MM-DD HH:mm:ss") : moment();
|
||||
}
|
||||
$scope.model.datetimePickerValue = dateVal.format("YYYY-MM-DD HH:mm:ss");
|
||||
$scope.model.datetimePickerInputValue = dateVal.format($scope.model.config.format);
|
||||
|
||||
}
|
||||
else {
|
||||
$scope.clearDate();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$watch("model.value", function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
$scope.hasDatetimePickerValue = newVal ? true : false;
|
||||
setDatePickerVal();
|
||||
}
|
||||
});
|
||||
|
||||
onInit();
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.DatepickerController", dateTimePickerController);
|
||||
|
||||
@@ -1,48 +1,76 @@
|
||||
<div class="umb-property-editor umb-datepicker" ng-controller="Umbraco.PropertyEditors.DatepickerController">
|
||||
|
||||
<ng-form name="datePickerForm">
|
||||
|
||||
<div id="datepicker{{model.alias}}">
|
||||
|
||||
<umb-date-time-picker
|
||||
ng-model="model.datetimePickerValue"
|
||||
options="datePickerConfig"
|
||||
on-setup="datePickerSetup(fpItem)"
|
||||
on-change="datePickerChange(dateStr)">
|
||||
|
||||
<div class="input-append">
|
||||
<input type="text"
|
||||
name="datepicker"
|
||||
id="{{model.alias}}"
|
||||
ng-model="model.datetimePickerValue"
|
||||
ng-blur="inputChanged()"
|
||||
ng-required="model.validation.mandatory"
|
||||
val-server="value"
|
||||
class="datepickerinput"
|
||||
ng-readonly="readonly" />
|
||||
<button ng-if="!readonly" type="button" class="btn-clear" ng-click="clearDate()" ng-show="hasDatetimePickerValue === true || datePickerForm.datepicker.$error.pickerError === true">
|
||||
<umb-icon icon="icon-delete"></umb-icon>
|
||||
<span class="sr-only"><localize key="content_removeDate">Clear date</localize></span>
|
||||
</button>
|
||||
<span ng-if="!readonly" class="add-on">
|
||||
<umb-icon icon="icon-{{ datePickerConfig.noCalendar ? 'time' : 'calendar' }}"></umb-icon>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</umb-date-time-picker>
|
||||
|
||||
<div
|
||||
class="umb-property-editor umb-datepicker"
|
||||
ng-controller="Umbraco.PropertyEditors.DatepickerController"
|
||||
>
|
||||
<ng-form name="datePickerForm">
|
||||
<div id="datepicker{{model.alias}}">
|
||||
<umb-date-time-picker
|
||||
ng-model="model.datetimePickerValue"
|
||||
options="datePickerConfig"
|
||||
on-setup="datePickerSetup(fpItem)"
|
||||
on-change="datePickerChange(dateStr)"
|
||||
>
|
||||
<div class="input-append">
|
||||
<input
|
||||
type="text"
|
||||
name="datepicker"
|
||||
id="{{model.alias}}"
|
||||
ng-model="model.datetimePickerInputValue"
|
||||
ng-blur="inputChanged()"
|
||||
ng-required="model.validation.mandatory"
|
||||
val-server="value"
|
||||
class="datepickerinput"
|
||||
ng-readonly="readonly"
|
||||
/>
|
||||
<button
|
||||
ng-if="!readonly"
|
||||
type="button"
|
||||
class="btn-clear"
|
||||
ng-click="clearDate()"
|
||||
ng-show="hasDatetimePickerValue === true || datePickerForm.datepicker.$error.pickerError === true"
|
||||
>
|
||||
<umb-icon icon="icon-delete"></umb-icon>
|
||||
<span class="sr-only">
|
||||
<localize key="content_removeDate">Clear date</localize>
|
||||
</span>
|
||||
</button>
|
||||
<span ng-if="!readonly" class="add-on">
|
||||
<umb-icon
|
||||
icon="icon-{{ datePickerConfig.noCalendar ? 'time' : 'calendar' }}"
|
||||
></umb-icon>
|
||||
</span>
|
||||
</div>
|
||||
</umb-date-time-picker>
|
||||
</div>
|
||||
|
||||
<div ng-messages="datePickerForm.datepicker.$error" show-validation-on-submit>
|
||||
<p class="help-inline" ng-message="required">{{mandatoryMessage}}</p>
|
||||
<p class="help-inline" ng-message="valServer">{{datePickerForm.datepicker.errorMsg}}</p>
|
||||
<p class="help-inline" ng-message="pickerError"><localize key="validation_invalidDate">Invalid date</localize></p>
|
||||
</div>
|
||||
<div
|
||||
ng-messages="datePickerForm.datepicker.$error"
|
||||
show-validation-on-submit
|
||||
>
|
||||
<p class="help-inline" ng-message="required">{{mandatoryMessage}}</p>
|
||||
<p class="help-inline" ng-message="valServer">
|
||||
{{datePickerForm.datepicker.errorMsg}}
|
||||
</p>
|
||||
<p class="help-inline" ng-message="pickerError">
|
||||
<localize key="validation_invalidDate">Invalid date</localize>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p ng-if="model.config.offsetTime === '1' && serverTimeNeedsOffsetting && model.value" class="muted">
|
||||
<small><localize key="content_scheduledPublishServerTime">This translates to the following time on the server:</localize> {{serverTime}}</small><br />
|
||||
<small><localize key="content_scheduledPublishDocumentation">What does this mean?</localize></small>
|
||||
</p>
|
||||
|
||||
</ng-form>
|
||||
<p
|
||||
ng-if="model.config.offsetTime === '1' && serverTimeNeedsOffsetting && model.value"
|
||||
class="muted"
|
||||
>
|
||||
<small>
|
||||
<localize key="content_scheduledPublishServerTime"
|
||||
>This translates to the following time on the server:
|
||||
</localize>
|
||||
{{serverTime}} </small
|
||||
><br />
|
||||
<small>
|
||||
<localize key="content_scheduledPublishDocumentation"
|
||||
>What does this mean?</localize
|
||||
>
|
||||
</small>
|
||||
</p>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user