Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/8.4' into 9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Mar 16, 2024
2 parents f9c9a23 + 83e9f22 commit cafcb71
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 61 deletions.
11 changes: 9 additions & 2 deletions esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,15 @@ const options = {
cssModules(
{
visitor: compileWithCssVariables(),
targets: {
chrome: 80 // aligns somewhat to es2020
targets: { // only support es2020 browser
// only supports browserList format
// https://lightningcss.dev/transpilation.html
// list of supported browser version per es version
// https://github.com/evanw/esbuild/issues/121#issuecomment-646956379
chrome: (80 << 16), // 80
safari: (13 << 16) | (1 << 8), // 13.1
firefox: (72 << 16), // 72
edge: (80 << 16) // 80
},
drafts: {
nesting: true
Expand Down
5 changes: 5 additions & 0 deletions packages/neos-ui-editors/src/Editors/DateTime/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,8 @@ export const hasDateFormat = format => /[yYFmMntdDjlNSw]/.test(format);
// Check if given format has a time formatting
//
export const hasTimeFormat = format => /[gGhHis]/.test(format);

//
// Check if the time is 24 hour or 12 hour format
//
export const has24HourFormat = format => /[GH]/.test(format);
4 changes: 2 additions & 2 deletions packages/neos-ui-editors/src/Editors/DateTime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import DateInput from '@neos-project/react-ui-components/src/DateInput/';
import moment from 'moment';
import {neos} from '@neos-project/neos-ui-decorators';
import convertPhpDateFormatToMoment, {hasDateFormat, hasTimeFormat} from './helpers';
import convertPhpDateFormatToMoment, {has24HourFormat, hasDateFormat, hasTimeFormat} from './helpers';
import {connect} from 'react-redux';

@neos(globalRegistry => ({
Expand Down Expand Up @@ -59,9 +59,9 @@ class DateTime extends PureComponent {
labelFormat={convertPhpDateFormatToMoment(options.format)}
dateOnly={!hasTimeFormat(options.format)}
timeOnly={!hasDateFormat(options.format)}
is24Hour={hasTimeFormat(options.format) && has24HourFormat(options.format)}
placeholder={i18nRegistry.translate(options?.placeholder || 'Neos.Neos:Main:content.inspector.editors.dateTimeEditor.noDateSet')}
todayLabel={i18nRegistry.translate('content.inspector.editors.dateTimeEditor.today', 'Today', {}, 'Neos.Neos', 'Main')}
applyLabel={i18nRegistry.translate('content.inspector.editors.dateTimeEditor.apply', 'Apply', {}, 'Neos.Neos', 'Main')}
locale={interfaceLanguage}
disabled={options.disabled}
timeConstraints={timeConstraints}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ export default class AspectRatioDropDown extends PureComponent {
PropTypes.instanceOf(AspectRatioOption)
),
placeholder: PropTypes.string,
allowCustomRatios: PropTypes.boolean,

onSelect: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired
};

render() {
const {options, current, placeholder, onSelect, onClear} = this.props;
const {options, current, placeholder, allowCustomRatios, onSelect, onClear} = this.props;

const dropDownHeaderClasses = mergeClassNames({
[style.dropDown__btn]: true,
Expand All @@ -58,7 +59,8 @@ export default class AspectRatioDropDown extends PureComponent {
<DropDown.Header className={dropDownHeaderClasses}>
{current.label}
</DropDown.Header>
<IconButton icon="times" onClick={onClear} className={style.dropDown__clear}/>
{allowCustomRatios && (
<IconButton icon="times" onClick={onClear} className={style.dropDown__clear}/>)}
</div>
) : (
<DropDown.Header className={dropDownHeaderClasses}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export default class ImageCropper extends PureComponent {
{!aspectRatioLocked && <AspectRatioDropDown
placeholder={`${i18nRegistry.translate('Neos.Neos:Main:imageCropper__aspect-ratio-placeholder')}`}
current={cropConfiguration.aspectRatioStrategy}
allowCustomRatios={allowCustomRatios}
options={cropConfiguration.aspectRatioOptions}
onSelect={this.handleSetAspectRatio}
onClear={this.handleClearAspectRatio}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<DateInput/> should render correctly. 1`] = `
exports[`<DateInput/> should format time in 24 hour format 1`] = `
<div
className="wrapperClassName"
>
Expand Down Expand Up @@ -85,7 +85,7 @@ exports[`<DateInput/> should render correctly. 1`] = `
},
}
}
timeFormat={true}
timeFormat="HH:m"
utc={false}
/>
<ThemedButton
Expand All @@ -108,6 +108,98 @@ exports[`<DateInput/> should render correctly. 1`] = `
</div>
`;

exports[`<DateInput/> should render correctly. 1`] = `
<div
className="wrapperClassName"
>
<div
className="calendarInputWrapperClassName"
>
<button
className="calendarIconBtnClassName"
onClick={[Function]}
>
<ThemedIcon
color="default"
composeTheme="deeply"
icon="far calendar-alt"
mapThemrProps={[Function]}
padded="none"
size="sm"
/>
</button>
<div
className="calendarFakeInputWrapperClassName"
>
<div
className="calendarFakeInputMirrorClassName"
onClick={[Function]}
role="presentation"
/>
<input
className="calendarFakeInputClassName"
onFocus={[Function]}
readOnly={true}
type="datetime"
value=""
/>
</div>
<button
className="closeCalendarIconBtnClassName"
onClick={[Function]}
>
<ThemedIcon
color="default"
composeTheme="deeply"
icon="times"
mapThemrProps={[Function]}
padded="none"
size="sm"
/>
</button>
</div>
<UnmountClosed
isOpened={false}
>
<button
className="selectTodayBtnClassName"
onClick={[Function]}
>
todayLabel
</button>
<DateTime
className=""
closeOnSelect={false}
closeOnTab={true}
dateFormat={true}
defaultValue=""
input={true}
inputProps={Object {}}
locale="en-US"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onNavigateBack={[Function]}
onNavigateForward={[Function]}
onViewModeChange={[Function]}
open={true}
strictParsing={true}
timeConstraints={
Object {
"minutes": Object {
"max": 59,
"min": 0,
"step": 5,
},
}
}
timeFormat="HH:m"
utc={false}
/>
</UnmountClosed>
</div>
`;

exports[`<DateInput/> should set "utc" on DatePickerComponent if "dateOnly" prop is set. 1`] = `
<div
className="wrapperClassName"
Expand Down Expand Up @@ -196,22 +288,6 @@ exports[`<DateInput/> should set "utc" on DatePickerComponent if "dateOnly" prop
timeFormat={false}
utc={true}
/>
<ThemedButton
_refHandler={[Function]}
className="applyBtnClassName"
composeTheme="deeply"
disabled={false}
hoverStyle="brand"
isActive={false}
isFocused={false}
mapThemrProps={[Function]}
onClick={[Function]}
size="regular"
style="brand"
type="button"
>
applyLabel
</ThemedButton>
</UnmountClosed>
</div>
`;
14 changes: 8 additions & 6 deletions packages/react-ui-components/src/DateInput/dateInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import toJson from 'enzyme-to-json';
import moment from 'moment';
import DatePicker from 'react-datetime';

import Button from '../Button';
import {DateInput} from './dateInput';

describe('<DateInput/>', () => {
const props: DateInput['props'] = {
onChange: jest.fn(),
locale: 'en-US',
applyLabel: 'applyLabel',
todayLabel: 'todayLabel',
theme: {
'wrapper': 'wrapperClassName',
Expand All @@ -29,7 +27,7 @@ describe('<DateInput/>', () => {
};

it('should render correctly.', () => {
const wrapper = shallow(<DateInput {...props}/>);
const wrapper = shallow(<DateInput {...props} is24Hour/>);

expect(toJson(wrapper)).toMatchSnapshot();
});
Expand Down Expand Up @@ -62,15 +60,13 @@ describe('<DateInput/>', () => {
expect(onChange.mock.calls[0][0]).toBe(null);
});

it('should call the "onChange" prop when triggering the change event on the "DatePicker" Component and clicking apply.', () => {
it('should call the "onChange" prop when triggering the change event on the "DatePicker".', () => {
const onChange = jest.fn();
const wrapper = shallow(<DateInput {...props} value={new Date()} onChange={onChange}/>);
const picker = wrapper.find(DatePicker);
const applyButton = wrapper.find(Button);
const newVal = moment();

picker.simulate('change', newVal);
applyButton.simulate('click');

expect(onChange.mock.calls.length).toBe(1);
expect(onChange.mock.calls[0][0].toTimeString()).toBe(newVal.toDate().toTimeString());
Expand Down Expand Up @@ -116,4 +112,10 @@ describe('<DateInput/>', () => {
expect(receivedDate.getUTCSeconds()).toBe(0);
expect(receivedDate.getUTCMilliseconds()).toBe(0);
});

it('should format time in 24 hour format', () => {
const wrapper = shallow(<DateInput {...props} is24Hour/>);

expect(toJson(wrapper)).toMatchSnapshot();
});
});
50 changes: 19 additions & 31 deletions packages/react-ui-components/src/DateInput/dateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Collapse from 'react-collapse';
import DatePicker, {TimeConstraints} from 'react-datetime';

import {PickDefaultProps} from '../utils-typescript';
import Button from '../Button';
import Icon from '../Icon';

// WHY: Because momentJs locales are not bundled automatically, we have to explicitly add them.
Expand Down Expand Up @@ -39,11 +38,6 @@ export interface DateInputProps {
*/
readonly todayLabel: string;

/**
* The label which will be displayed within the `Apply` btn.
*/
readonly applyLabel: string;

/**
* The moment format string to use to format the passed value.
*/
Expand All @@ -59,6 +53,11 @@ export interface DateInputProps {
*/
readonly timeOnly?: boolean;

/**
* Show the Time in 24 hours or 12 hours format
*/
readonly is24Hour?: boolean;

/**
* Add some constraints to the timepicker.
* It accepts an object with the format { hours: { min: 9, max: 15, step: 2 }},
Expand Down Expand Up @@ -104,7 +103,7 @@ interface DateInputTheme {
}

const defaultProps: PickDefaultProps<DateInputProps, 'labelFormat' | 'timeConstraints'> = {
labelFormat: 'DD-MM-YYYY hh:mm',
labelFormat: 'DD-MM-YYYY hh:mm A',
timeConstraints: {
minutes: {
min: 0,
Expand All @@ -115,13 +114,12 @@ const defaultProps: PickDefaultProps<DateInputProps, 'labelFormat' | 'timeConstr
};

interface DateInputState {
readonly isOpen: boolean;
readonly transientDate: Date | null; // TODO do we have a breaking change when we use 'undefined' in favor of 'null'?
readonly isOpen: boolean

}

const initialState: DateInputState = {
isOpen: false,
transientDate: null
isOpen: false
};

export class DateInput extends PureComponent<DateInputProps, DateInputState> {
Expand All @@ -137,7 +135,6 @@ export class DateInput extends PureComponent<DateInputProps, DateInputState> {
className,
id,
todayLabel,
applyLabel,
labelFormat,
dateOnly,
timeOnly,
Expand Down Expand Up @@ -221,17 +218,11 @@ export class DateInput extends PureComponent<DateInputProps, DateInputState> {
dateFormat={!timeOnly}
utc={dateOnly}
locale={locale}
timeFormat={!dateOnly}
timeFormat={this.timeFormat}
onChange={this.handleChange}

timeConstraints={this.props.timeConstraints}
/>
<Button
onClick={this.handleApply}
className={theme!.applyBtn}
style="brand"
>
{applyLabel}
</Button>
</Collapse>
</div>
);
Expand All @@ -257,19 +248,9 @@ export class DateInput extends PureComponent<DateInputProps, DateInputState> {
}
}

private readonly handleApply = () => {
this.setState({
isOpen: false
}, () => {
this.props.onChange(this.state.transientDate);
});
}

private readonly handleChange = (value: Moment | string) => {
const momentVal: Moment = isMoment(value) ? value : moment(value);
this.setState({
transientDate: momentVal.toDate()
});
this.props.onChange(momentVal.toDate());
}

private readonly handleSelectTodayBtnClick = () => {
Expand Down Expand Up @@ -303,6 +284,13 @@ export class DateInput extends PureComponent<DateInputProps, DateInputState> {
isOpen: false
});
}

private get timeFormat(): false | string {
if (this.props.dateOnly) {
return false;
}
return this.props.is24Hour ? 'HH:m' : 'hh:m A';
}
}

//
Expand Down
Loading

0 comments on commit cafcb71

Please sign in to comment.