@pnp/spfx-controls-react
Version:
Reusable React controls for SharePoint Framework solutions
306 lines • 17.2 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import * as React from "react";
import { isEqual } from '@microsoft/sp-lodash-subset';
import { TimeConvention, DateConvention } from "./DateTimeConventions";
import { Calendar } from "@fluentui/react/lib/Calendar";
import { DatePicker } from "@fluentui/react/lib/DatePicker";
import { Label } from "@fluentui/react/lib/Label";
import { IconButton } from "@fluentui/react/lib/Button";
import ErrorMessage from "../errorMessage/ErrorMessage";
import styles from "./DateTimePicker.module.scss";
import HoursComponent from "./HoursComponent";
import MinutesComponent from "./MinutesComponent";
import SecondsComponent from "./SecondsComponent";
import * as telemetry from "../../common/telemetry";
import { Async, css } from '@fluentui/react/lib/Utilities';
import { DateTimePickerStrings } from "./DateTimePickerStrings";
import { TimeHelper } from "./TimeHelper";
import { TimeDisplayControlType } from "./TimeDisplayControlType";
/**
* Renders the controls for DateTimePicker component
*/
var DateTimePicker = /** @class */ (function (_super) {
__extends(DateTimePicker, _super);
/**
* Constructor
*/
function DateTimePicker(props) {
var _this = _super.call(this, props) || this;
_this._latestValidateValue = NaN;
/**
* Function called when the DatePicker Office UI Fabric component selected date changed
*/
_this.onSelectDate = function (date) {
if (!TimeHelper.isValidDate(date)) {
return;
}
// Get hours, minutes and seconds from state or default to zero
var _a = _this.state, _b = _a.hours, hours = _b === void 0 ? 0 : _b, _c = _a.minutes, minutes = _c === void 0 ? 0 : _c, _d = _a.seconds, seconds = _d === void 0 ? 0 : _d;
var day = TimeHelper.cloneDate(date);
day.setHours(hours);
day.setMinutes(minutes);
day.setSeconds(seconds);
_this.setState({ day: day }, function () { return _this.delayedValidate(_this.state.day); });
};
/**
* Function called when hours value have been changed
* @param element Hours dropdown value
*/
_this.dropdownHoursChanged = function (value) {
_this.setState(function (_a) {
var day = _a.day;
var hoursSplit = value.split(" ");
var hoursValue = hoursSplit[0].length > 2 ? hoursSplit[0].substring(0, 2) : hoursSplit[0];
var hours = parseInt(hoursValue);
if (isNaN(hours)) {
return;
}
if (_this.props.timeConvention !== TimeConvention.Hours24) {
if (hoursSplit[1] && hoursSplit[1].toLowerCase().indexOf("pm") !== -1) {
hours += 12;
if (hours === 24) {
//this is noon - set to 12 not 0
//hours = 0;
hours = 12;
}
}
else if (hours === 12) {
//am - if hours === 12, set hours to 0 here
hours = 0;
}
}
if (hours > 23) {
return;
}
var state = { hours: hours };
var date = TimeHelper.cloneDate(day);
if (date) {
date.setHours(hours);
state.day = date;
}
return state;
}, function () { return _this.delayedValidate(_this.state.day); });
};
/**
* Function called when minutes value have been changed
* @param element Minutes dropdown value
*/
_this.dropdownMinutesChanged = function (value) {
_this.setState(function (_a) {
var day = _a.day;
var minutes = parseInt(value.length > 2 ? value.substring(0, 2) : value);
var state = { minutes: minutes };
var date = TimeHelper.cloneDate(day);
if (date) {
date.setMinutes(minutes);
state.day = date;
}
return state;
}, function () { return _this.delayedValidate(_this.state.day); });
};
/**
* Function called when seconds value have been changed
* @param element Seconds dropdown value
*/
_this.dropdownSecondsChanged = function (value) {
_this.setState(function (_a) {
var day = _a.day;
var seconds = parseInt(value.length > 2 ? value.substring(0, 2) : value);
var state = { seconds: seconds };
var date = TimeHelper.cloneDate(day);
if (date) {
date.setSeconds(seconds);
state.day = date;
}
return state;
}, function () { return _this.delayedValidate(_this.state.day); });
};
/**
* Validates string input on date time field
*/
_this.handleTextChange = function (e, newValue, locString) {
if (!TimeHelper.isValidDate(newValue)) {
_this.setState({
errorMessage: locString,
});
return;
}
};
/**
* Validates the new custom field value
*/
_this.validate = function (dateVal) {
if (typeof _this.props.onGetErrorMessage === 'undefined' || _this.props.onGetErrorMessage === null) {
_this.notifyAfterValidate(_this.props.value, dateVal);
return;
}
var timestamp = dateVal.getTime();
if (_this._latestValidateValue === timestamp) {
return;
}
_this._latestValidateValue = timestamp;
var result = _this.props.onGetErrorMessage(dateVal);
if (typeof result !== 'undefined') {
if (typeof result === 'string') {
if (result === '') {
_this.notifyAfterValidate(_this.props.value, dateVal);
}
_this.setState({
errorMessage: result
});
}
else {
result.then(function (errorMessage) {
if (typeof errorMessage === 'undefined' || errorMessage === '') {
_this.notifyAfterValidate(_this.props.value, dateVal);
}
_this.setState({
errorMessage: errorMessage
});
})
.catch(function () { });
}
}
else {
_this.notifyAfterValidate(_this.props.value, dateVal);
}
};
/**
* Notifies the parent Web Part of a property value change
*/
_this.notifyAfterValidate = function (oldValue, newValue) {
if (typeof _this.props.onChange !== 'undefined' && _this.props.onChange !== null && newValue !== null) {
_this.props.onChange(newValue);
}
};
telemetry.track('ReactDateTimePicker', {
dateConvention: props.dateConvention ? DateConvention[props.dateConvention] : '',
formatDate: !!props.formatDate,
timeConvention: props.timeConvention ? TimeConvention[props.timeConvention] : '',
disabled: props.disabled
});
// Get the current date/time values
var _a = _this.props.value, value = _a === void 0 ? null : _a;
var _b = DateTimePicker.getDateComponents(value, props.dateConvention), day = _b.day, hours = _b.hours, minutes = _b.minutes, seconds = _b.seconds;
// Set the current state
_this.state = {
day: day,
hours: hours,
minutes: minutes,
seconds: seconds,
errorMessage: ''
};
_this.async = new Async(_this);
_this.delayedValidate = _this.async.debounce(_this.validate, props.deferredValidationTime);
return _this;
}
/**
* Called when the component will unmount
*/
DateTimePicker.prototype.componentWillUnmount = function () {
this.async.dispose();
};
/**
* Called before the component receives new props, used for matching state with new props.
*/
DateTimePicker.prototype.UNSAFE_componentWillReceiveProps = function (nextProps) {
if (!isEqual(nextProps.value, this.props.value)) {
var _a = DateTimePicker.getDateComponents(nextProps.value, this.props.dateConvention), day = _a.day, hours = _a.hours, minutes = _a.minutes, seconds = _a.seconds;
this.setState({ day: day, hours: hours, minutes: minutes, seconds: seconds });
}
};
/**
* Get the components of a Date object matching the DateConvention settings
* @param date Date to extract components from
* @param dateConvention DateConvention to follow when extracting date components
*/
DateTimePicker.getDateComponents = function (date, dateConvention) {
var day = TimeHelper.cloneDate(date);
var hours = dateConvention !== DateConvention.Date && day !== null ? day.getHours() : 0;
var minutes = dateConvention !== DateConvention.Date && day !== null ? day.getMinutes() : 0;
var seconds = dateConvention !== DateConvention.Date && day !== null ? day.getSeconds() : 0;
if (day !== null) {
day.setHours(hours);
day.setMinutes(minutes);
day.setSeconds(seconds);
}
return { day: day, hours: hours, minutes: minutes, seconds: seconds };
};
/**
* Function called from the clearDate iconbutton
*/
DateTimePicker.prototype.clearDate = function () {
this.setState({
day: null
});
if (this.props.onChange) {
this.props.onChange(null);
}
};
/**
* Renders the control
*/
DateTimePicker.prototype.render = function () {
var _this = this;
// use date value from props if it exists, otherwise use internal state
// if no dateConvention is set, default is DateConvention.DateTime
var _a = this.props, label = _a.label, disabled = _a.disabled, timeConvention = _a.timeConvention, _b = _a.dateConvention, dateConvention = _b === void 0 ? DateConvention.DateTime : _b, firstDayOfWeek = _a.firstDayOfWeek, firstWeekOfYear = _a.firstWeekOfYear, _c = _a.isMonthPickerVisible, isMonthPickerVisible = _c === void 0 ? true : _c, showGoToToday = _a.showGoToToday, _d = _a.allowTextInput, allowTextInput = _d === void 0 ? true : _d, _e = _a.showMonthPickerAsOverlay, showMonthPickerAsOverlay = _e === void 0 ? false : _e, _f = _a.showWeekNumbers, showWeekNumbers = _f === void 0 ? false : _f, _g = _a.showSeconds, showSeconds = _g === void 0 ? false : _g, formatDate = _a.formatDate, parseDateFromString = _a.parseDateFromString, _h = _a.value, value = _h === void 0 ? this.state.day : _h, _j = _a.strings, dateStrings = _j === void 0 ? new DateTimePickerStrings() : _j, // Defines the DatePicker control labels
timeDisplayControlType = _a.timeDisplayControlType, placeholder = _a.placeholder, showLabels = _a.showLabels, initialPickerDate = _a.initialPickerDate, minDate = _a.minDate, maxDate = _a.maxDate, minutesIncrementStep = _a.minutesIncrementStep, _k = _a.showClearDate, showClearDate = _k === void 0 ? false : _k, _l = _a.showClearDateIcon, showClearDateIcon = _l === void 0 ? 'RemoveEvent' : _l, _m = _a.restrictedDates, restrictedDates = _m === void 0 ? [] : _m;
var textErrorMessage = dateStrings.textErrorMessage;
var hours = value !== null ? value.getHours() : this.state.hours;
var minutes = value !== null ? value.getMinutes() : this.state.minutes;
var seconds = value !== null ? value.getSeconds() : this.state.seconds;
var CalendarView = function () {
return (React.createElement(Calendar, { value: initialPickerDate, strings: dateStrings, isMonthPickerVisible: isMonthPickerVisible, onSelectDate: _this.onSelectDate, firstDayOfWeek: firstDayOfWeek, firstWeekOfYear: firstWeekOfYear, showGoToToday: showGoToToday, showMonthPickerAsOverlay: showMonthPickerAsOverlay, showWeekNumbers: showWeekNumbers, minDate: minDate, maxDate: maxDate, restrictedDates: restrictedDates }));
};
// Check if the time element needs to be rendered
var timeElm = React.createElement("div", { className: "hidden" });
if (dateConvention === DateConvention.DateTime) {
timeElm = (React.createElement("div", { className: css(styles.row, styles.timeRow) },
showLabels !== false && React.createElement("div", { className: styles.labelCell },
React.createElement(Label, { className: styles.fieldLabel }, dateStrings.timeLabel)),
React.createElement("div", { className: styles.time },
React.createElement("div", { className: styles.picker },
React.createElement(HoursComponent, { disabled: disabled, timeConvention: timeConvention, value: hours, onChange: this.dropdownHoursChanged, timeDisplayControlType: timeDisplayControlType || TimeDisplayControlType.Text })),
React.createElement("div", { className: styles.separator },
React.createElement(Label, null, dateStrings.timeSeparator)),
React.createElement("div", { className: styles.picker },
React.createElement(MinutesComponent, { disabled: disabled, value: minutes, minutesIncrementStep: minutesIncrementStep, onChange: this.dropdownMinutesChanged, timeDisplayControlType: timeDisplayControlType || TimeDisplayControlType.Text })),
showSeconds && (React.createElement("div", { className: styles.separator },
React.createElement(Label, null, dateStrings.timeSeparator))),
showSeconds && (React.createElement("div", { className: styles.picker },
React.createElement(SecondsComponent, { disabled: disabled, value: seconds, onChange: this.dropdownSecondsChanged, timeDisplayControlType: timeDisplayControlType || TimeDisplayControlType.Text }))))));
}
// Renders content
return (React.createElement("div", { className: styles.dateTimePicker },
label && React.createElement(Label, null, label),
React.createElement("div", { className: styles.container },
React.createElement("div", { className: styles.row },
showLabels !== false && (React.createElement("div", { className: styles.labelCell },
React.createElement(Label, { className: styles.fieldLabel }, dateStrings.dateLabel))),
React.createElement("div", { className: styles.picker },
React.createElement(DatePicker, { formatDate: formatDate, parseDateFromString: parseDateFromString, disabled: disabled, value: value, strings: dateStrings, isMonthPickerVisible: isMonthPickerVisible, onSelectDate: this.onSelectDate, allowTextInput: allowTextInput, firstDayOfWeek: firstDayOfWeek, firstWeekOfYear: firstWeekOfYear, showGoToToday: showGoToToday, showMonthPickerAsOverlay: showMonthPickerAsOverlay, showWeekNumbers: showWeekNumbers, placeholder: placeholder, initialPickerDate: initialPickerDate, minDate: minDate, maxDate: maxDate, calendarAs: restrictedDates.length ? CalendarView : undefined, textField: {
onChange: function (e, newValue) { return _this.handleTextChange(e, newValue, textErrorMessage); }
} })),
showClearDate === true && this.state.day !== null && React.createElement(IconButton, { iconProps: { iconName: showClearDateIcon }, onClick: function () { return _this.clearDate(); } })),
timeElm),
React.createElement(ErrorMessage, { errorMessage: this.state.errorMessage })));
};
return DateTimePicker;
}(React.Component));
export { DateTimePicker };
//# sourceMappingURL=DateTimePicker.js.map