@ember-eui/core 5.8.5 → 5.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/components/eui-field-text/index.hbs +1 -0
- package/addon/components/eui-global-toast-list/index.ts +1 -1
- package/addon/components/eui-i18n/index.ts +9 -41
- package/addon/components/eui-super-date-picker/date-popover/absolute-tab.hbs +42 -0
- package/addon/components/eui-super-date-picker/date-popover/absolute-tab.ts +79 -0
- package/addon/components/eui-super-date-picker/date-popover/datetime-picker.hbs +125 -0
- package/addon/components/eui-super-date-picker/date-popover/datetime-picker.ts +258 -0
- package/addon/components/eui-super-date-picker/date-popover/eui-date-popover-button.hbs +49 -0
- package/addon/components/eui-super-date-picker/date-popover/eui-date-popover-button.ts +49 -0
- package/addon/components/eui-super-date-picker/date-popover/eui-date-popover-content.hbs +42 -0
- package/addon/components/eui-super-date-picker/date-popover/eui-date-popover-content.ts +73 -0
- package/addon/components/eui-super-date-picker/date-popover/now-tab.hbs +45 -0
- package/addon/components/eui-super-date-picker/date-popover/relative-tab.hbs +47 -0
- package/addon/components/eui-super-date-picker/date-popover/relative-tab.ts +89 -0
- package/addon/components/eui-super-date-picker/eui-date-picker-range.hbs +22 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/eui-commonly-used-time-ranges.hbs +42 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/eui-quick-select.hbs +154 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/eui-quick-select.ts +103 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/eui-recently-used.hbs +48 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/index.hbs +60 -0
- package/addon/components/eui-super-date-picker/eui-quick-select-popover/index.ts +34 -0
- package/addon/components/eui-super-date-picker/eui-super-update-button.hbs +43 -0
- package/addon/components/eui-super-date-picker/index.hbs +123 -0
- package/addon/components/eui-super-date-picker/index.ts +220 -0
- package/addon/components/eui-super-date-picker/types/global.d.ts +52 -0
- package/addon/components/eui-super-date-picker/utils/date-utils.ts +59 -0
- package/addon/components/eui-super-date-picker/utils/index.ts +181 -0
- package/addon/components/eui-super-date-picker/utils/pretty-duration.ts +131 -0
- package/addon/components/eui-super-date-picker/utils/quick-select.ts +75 -0
- package/addon/components/eui-super-date-picker/utils/time-options.ts +216 -0
- package/addon/components/text-block/index.hbs +25 -21
- package/addon/{components/eui-i18n → i18n}/util.ts +1 -6
- package/addon/services/eui-i18n.ts +89 -0
- package/addon/utils/markdown/markdown-unified-plugins.d.ts +0 -14
- package/app/components/eui-super-date-picker/date-popover/absolute-tab.js +1 -0
- package/app/components/eui-super-date-picker/date-popover/datetime-picker.js +1 -0
- package/app/components/eui-super-date-picker/date-popover/eui-date-popover-button.js +1 -0
- package/app/components/eui-super-date-picker/date-popover/eui-date-popover-content.js +1 -0
- package/app/components/eui-super-date-picker/date-popover/now-tab.js +1 -0
- package/app/components/eui-super-date-picker/date-popover/relative-tab.js +1 -0
- package/app/components/eui-super-date-picker/eui-date-picker-range.js +1 -0
- package/app/components/eui-super-date-picker/eui-quick-select-popover/eui-commonly-used-time-ranges.js +1 -0
- package/app/components/eui-super-date-picker/eui-quick-select-popover/eui-quick-select.js +1 -0
- package/app/components/eui-super-date-picker/eui-quick-select-popover/eui-recently-used.js +1 -0
- package/app/components/eui-super-date-picker/eui-quick-select-popover/index.js +1 -0
- package/app/components/eui-super-date-picker/eui-super-update-button.js +1 -0
- package/app/components/eui-super-date-picker/index.js +1 -0
- package/app/services/eui-i18n.js +1 -0
- package/docs/forms/super-date-picker/demo/d01-picker.md +90 -0
- package/docs/forms/super-date-picker/index.md +16 -0
- package/package.json +6 -3
- package/tsconfig.json +1 -0
- package/addon/i18n/index.ts +0 -8
- package/app/i18n/index.js +0 -1
- package/docs/templates/super-date-picker/demo/d01-update-button.md +0 -10
- package/docs/templates/super-date-picker/demo/d02-quick-select-panels.md +0 -10
- package/docs/templates/super-date-picker/demo/d03-sizing.md +0 -10
- package/docs/templates/super-date-picker/demo/d04-auto-refresh.md +0 -11
- package/docs/templates/super-date-picker/demo/d05-elastic-pattern-with-kql.md +0 -10
- package/docs/templates/super-date-picker/index.md +0 -12
|
@@ -4,7 +4,7 @@ import { action } from '@ember/object';
|
|
|
4
4
|
import { inject as service } from '@ember/service';
|
|
5
5
|
import { sideMapping } from 'core/utils/css-mappings/eui-global-toast-list';
|
|
6
6
|
import Timer from '../../utils/timer';
|
|
7
|
-
import EuiToasterService, { EuiToastProps } from '
|
|
7
|
+
import EuiToasterService, { EuiToastProps } from '../../services/eui-toaster';
|
|
8
8
|
|
|
9
9
|
type EuiToastSide = keyof typeof sideMapping;
|
|
10
10
|
type ToastSide = EuiToastSide | string;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { i18n, I18nShape } from '@ember-eui/core/i18n';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import type EuiI18n from '../../services/eui-i18n';
|
|
5
4
|
|
|
6
5
|
interface Args {
|
|
7
6
|
tokens?: string[];
|
|
@@ -9,62 +8,31 @@ interface Args {
|
|
|
9
8
|
token?: string;
|
|
10
9
|
default?: string;
|
|
11
10
|
values?: { [key: string]: any };
|
|
12
|
-
i18n?:
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface lookupTokenOptions {
|
|
16
|
-
token: string;
|
|
17
|
-
i18nMapping: I18nShape['mapping'];
|
|
18
|
-
valueDefault: string;
|
|
19
|
-
i18nMappingFunc?: (token: string) => string;
|
|
20
|
-
values?: { [key: string]: any };
|
|
21
|
-
render?: I18nShape['render'];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function lookupToken(options: lookupTokenOptions) {
|
|
25
|
-
const {
|
|
26
|
-
token,
|
|
27
|
-
i18nMapping,
|
|
28
|
-
valueDefault,
|
|
29
|
-
i18nMappingFunc,
|
|
30
|
-
values = {}
|
|
31
|
-
} = options;
|
|
32
|
-
|
|
33
|
-
let renderable = (i18nMapping && i18nMapping[token]) || valueDefault;
|
|
34
|
-
|
|
35
|
-
const children = processStringToChildren(renderable, values, i18nMappingFunc);
|
|
36
|
-
if (typeof children === 'string') {
|
|
37
|
-
// likewise, `processStringToChildren` returns a string or ReactChild[] depending on
|
|
38
|
-
// the type of `values`, so we will make the assumption that the default value is correct.
|
|
39
|
-
return children;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// same reasons as above, we can't promise the transforms match the default's type
|
|
43
|
-
return children;
|
|
11
|
+
i18n?: { mapping: { [key: string]: any } };
|
|
44
12
|
}
|
|
45
13
|
|
|
46
14
|
export default class EuiI18nComponent extends Component<Args> {
|
|
15
|
+
@service declare euiI18n: EuiI18n;
|
|
16
|
+
|
|
47
17
|
get isI18nTokensShape() {
|
|
48
18
|
return this.args.tokens != null;
|
|
49
19
|
}
|
|
50
20
|
|
|
51
|
-
get i18n() {
|
|
52
|
-
return this.args.i18n || i18n;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
21
|
get lookupedTokens() {
|
|
22
|
+
const lookupToken = this.euiI18n._lookupToken;
|
|
23
|
+
|
|
56
24
|
if (this.isI18nTokensShape) {
|
|
57
25
|
return this.args.tokens?.map((token, idx) =>
|
|
58
26
|
lookupToken({
|
|
59
27
|
token,
|
|
60
|
-
i18nMapping: i18n
|
|
28
|
+
i18nMapping: this.args.i18n?.mapping,
|
|
61
29
|
valueDefault: this.args.defaults![idx]
|
|
62
30
|
})
|
|
63
31
|
);
|
|
64
32
|
} else {
|
|
65
33
|
return lookupToken({
|
|
66
34
|
token: this.args.token!,
|
|
67
|
-
i18nMapping: i18n
|
|
35
|
+
i18nMapping: this.args.i18n?.mapping,
|
|
68
36
|
valueDefault: this.args.default!,
|
|
69
37
|
values: this.args.values
|
|
70
38
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<EuiSuperDatePicker::DatePopover::DatetimePicker
|
|
3
|
+
@inline={{true}}
|
|
4
|
+
@showTimeSelect={{true}}
|
|
5
|
+
@shadow={{false}}
|
|
6
|
+
@onChange={{this.handleChange}}
|
|
7
|
+
@dateFormat={{@dateFormat}}
|
|
8
|
+
@timeFormat={{@timeFormat}}
|
|
9
|
+
@selected={{this.valueAsMoment}}
|
|
10
|
+
{{!--
|
|
11
|
+
locale={locale}
|
|
12
|
+
utcOffset={utcOffset} --}}
|
|
13
|
+
/>
|
|
14
|
+
<EuiI18n
|
|
15
|
+
@token="euiAbsoluteTab.dateFormatError"
|
|
16
|
+
@default="Expected format: {dateFormat}"
|
|
17
|
+
@values={{@dateFormat}}
|
|
18
|
+
as |Token|
|
|
19
|
+
>
|
|
20
|
+
<Token as |dateFormatError|>
|
|
21
|
+
<EuiFormRow
|
|
22
|
+
class="euiSuperDatePicker__absoluteDateFormRow"
|
|
23
|
+
@isInvalid={{this.isTextInvalid}}
|
|
24
|
+
@error={{if this.isTextInvalid dateFormatError}}
|
|
25
|
+
>
|
|
26
|
+
<EuiFieldText
|
|
27
|
+
@isInvalid={{this.isTextInvalid}}
|
|
28
|
+
@value={{this.textInputValue}}
|
|
29
|
+
@compressed={{true}}
|
|
30
|
+
{{on "input" this.triggerChange}}
|
|
31
|
+
{{on "change" this.handleTextChange}}
|
|
32
|
+
>
|
|
33
|
+
<:prepend as |classes|>
|
|
34
|
+
<EuiFormLabel class={{classes}}>
|
|
35
|
+
{{@labelPrefix}}
|
|
36
|
+
</EuiFormLabel>
|
|
37
|
+
</:prepend>
|
|
38
|
+
</EuiFieldText>
|
|
39
|
+
</EuiFormRow>
|
|
40
|
+
</Token>
|
|
41
|
+
</EuiI18n>
|
|
42
|
+
</div>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
|
+
import Component from '@glimmer/component';
|
|
3
|
+
import moment, { LocaleSpecifier, Moment } from 'moment';
|
|
4
|
+
import dateMath from '@elastic/datemath';
|
|
5
|
+
import { tracked } from '@glimmer/tracking';
|
|
6
|
+
|
|
7
|
+
interface AbsoluteTabArgs {
|
|
8
|
+
dateFormat: string;
|
|
9
|
+
timeFormat: string;
|
|
10
|
+
locale?: LocaleSpecifier;
|
|
11
|
+
value: string;
|
|
12
|
+
onChange: (value: any) => void;
|
|
13
|
+
roundUp: boolean;
|
|
14
|
+
position: 'start' | 'end';
|
|
15
|
+
labelPrefix: string;
|
|
16
|
+
utcOffset?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class AbsoluteTab extends Component<AbsoluteTabArgs> {
|
|
20
|
+
@tracked isTextInvalid: boolean;
|
|
21
|
+
@tracked textInputValue: string;
|
|
22
|
+
@tracked valueAsMoment: Moment | null;
|
|
23
|
+
|
|
24
|
+
constructor(owner: unknown, args: AbsoluteTabArgs) {
|
|
25
|
+
super(owner, args);
|
|
26
|
+
|
|
27
|
+
const parsedValue = dateMath.parse(this.args.value, {
|
|
28
|
+
roundUp: this.args.roundUp
|
|
29
|
+
});
|
|
30
|
+
const valueAsMoment =
|
|
31
|
+
parsedValue && parsedValue.isValid() ? parsedValue : moment();
|
|
32
|
+
|
|
33
|
+
const textInputValue = valueAsMoment
|
|
34
|
+
.locale(this.args.locale || 'en')
|
|
35
|
+
.format(this.args.dateFormat);
|
|
36
|
+
|
|
37
|
+
this.isTextInvalid = false;
|
|
38
|
+
this.textInputValue = textInputValue;
|
|
39
|
+
this.valueAsMoment = valueAsMoment;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@action handleChange(date: any) {
|
|
43
|
+
if (date === null) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.args.onChange(date.toISOString());
|
|
48
|
+
|
|
49
|
+
const valueAsMoment = moment(date);
|
|
50
|
+
this.valueAsMoment = valueAsMoment;
|
|
51
|
+
this.textInputValue = valueAsMoment.format(this.args.dateFormat);
|
|
52
|
+
this.isTextInvalid = false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@action handleTextChange(e: InputEvent) {
|
|
56
|
+
const valueAsMoment = moment(
|
|
57
|
+
(e.target as HTMLInputElement).value,
|
|
58
|
+
this.args.dateFormat,
|
|
59
|
+
true
|
|
60
|
+
);
|
|
61
|
+
const dateIsValid = valueAsMoment.isValid();
|
|
62
|
+
if (dateIsValid) {
|
|
63
|
+
this.args.onChange(valueAsMoment.toISOString());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.textInputValue = (e.target as HTMLInputElement).value;
|
|
67
|
+
this.isTextInvalid = !dateIsValid;
|
|
68
|
+
this.valueAsMoment = dateIsValid ? valueAsMoment : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// `change` event on an input gets called after a `blur`
|
|
72
|
+
// blur the input and focus again to trigger the change event
|
|
73
|
+
// and call `handleTextChange` with the updated value
|
|
74
|
+
// and keep the field focused
|
|
75
|
+
@action triggerChange(e: InputEvent) {
|
|
76
|
+
(e.target as HTMLInputElement).blur();
|
|
77
|
+
(e.target as HTMLInputElement).focus();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<div class="euiDatePicker euiDatePicker--inline">
|
|
2
|
+
<EuiFormControlLayout
|
|
3
|
+
{{!-- @icon={{optionalIcon}}
|
|
4
|
+
@fullWidth={{fullWidth}}
|
|
5
|
+
@clear={selected && onClear ? { onClick: onClear } : undefined}
|
|
6
|
+
@isLoading={isLoading} --}}
|
|
7
|
+
>
|
|
8
|
+
<div class="react-datepicker">
|
|
9
|
+
<button
|
|
10
|
+
type="button"
|
|
11
|
+
class="react-datepicker__navigation react-datepicker__navigation--previous"
|
|
12
|
+
aria-label="Previous month"
|
|
13
|
+
{{on "click" this.decreaseMonth}}
|
|
14
|
+
>
|
|
15
|
+
<EuiIcon
|
|
16
|
+
@iconClasses="euiButtonIcon__icon"
|
|
17
|
+
@type="arrowLeft"
|
|
18
|
+
/>
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
class="react-datepicker__navigation react-datepicker__navigation--next"
|
|
23
|
+
aria-label="Next month"
|
|
24
|
+
{{on "click" this.increaseMonth}}
|
|
25
|
+
>
|
|
26
|
+
<EuiIcon
|
|
27
|
+
@iconClasses="euiButtonIcon__icon {{@iconClasses}}"
|
|
28
|
+
@type="arrowRight"
|
|
29
|
+
/>
|
|
30
|
+
</button>
|
|
31
|
+
<div class="react-datepicker__month-container">
|
|
32
|
+
<div class="react-datepicker__header">
|
|
33
|
+
<div class="react-datepicker__header__dropdown react-datepicker__header__dropdown--scroll">
|
|
34
|
+
<div class="react-datepicker__month-dropdown-container react-datepicker__month-dropdown-container--scroll">
|
|
35
|
+
{{!template-lint-disable}}
|
|
36
|
+
<div class="react-datepicker__month-read-view" style="padding: 0;">
|
|
37
|
+
<EuiFlexItem @grow="1">
|
|
38
|
+
<EuiSelect
|
|
39
|
+
@compressed={{true}}
|
|
40
|
+
@value={{this.month}}
|
|
41
|
+
@options={{this.monthNames}}
|
|
42
|
+
{{on "change" (pick "target.value" this.setMonth)}}
|
|
43
|
+
/>
|
|
44
|
+
</EuiFlexItem>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="react-datepicker__year-dropdown-container react-datepicker__year-dropdown-container--scroll">
|
|
48
|
+
{{!template-lint-disable}}
|
|
49
|
+
<div class="react-datepicker__year-read-view" style="padding: 0;">
|
|
50
|
+
<EuiFlexItem @grow="1">
|
|
51
|
+
<EuiSelect
|
|
52
|
+
@compressed={{true}}
|
|
53
|
+
@value={{this.year}}
|
|
54
|
+
@options={{this.years}}
|
|
55
|
+
{{on "change" (pick "target.value" (set this "year"))}}
|
|
56
|
+
/>
|
|
57
|
+
</EuiFlexItem>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="react-datepicker__day-names">
|
|
62
|
+
<div class="react-datepicker__day-name">Su</div>
|
|
63
|
+
<div class="react-datepicker__day-name">Mo</div>
|
|
64
|
+
<div class="react-datepicker__day-name">Tu</div>
|
|
65
|
+
<div class="react-datepicker__day-name">We</div>
|
|
66
|
+
<div class="react-datepicker__day-name">Th</div>
|
|
67
|
+
<div class="react-datepicker__day-name">Fr</div>
|
|
68
|
+
<div class="react-datepicker__day-name">Sa</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class="react-datepicker__month react-datepicker__month--accessible">
|
|
73
|
+
{{#each this.days as |days|}}
|
|
74
|
+
<div class="react-datepicker__week">
|
|
75
|
+
{{#each days as |day|}}
|
|
76
|
+
<div
|
|
77
|
+
role="button"
|
|
78
|
+
class={{concat
|
|
79
|
+
"react-datepicker__day"
|
|
80
|
+
(if
|
|
81
|
+
(and
|
|
82
|
+
(not day.isOutside)
|
|
83
|
+
(this.isSameDayHelper this.year this.month day.day this.selectedDate)
|
|
84
|
+
)
|
|
85
|
+
" react-datepicker__day--selected"
|
|
86
|
+
)
|
|
87
|
+
(if
|
|
88
|
+
(this.isSameDayHelper this.year this.month day.day this.today)
|
|
89
|
+
" react-datepicker__day--today"
|
|
90
|
+
)
|
|
91
|
+
(if day.isOutside " react-datepicker__day--outside-month")
|
|
92
|
+
}}
|
|
93
|
+
{{on "click" (fn this.selectDate day)}}
|
|
94
|
+
>
|
|
95
|
+
<div class="react-datepicker__day-text">{{day.day}}</div>
|
|
96
|
+
</div>
|
|
97
|
+
{{/each}}
|
|
98
|
+
</div>
|
|
99
|
+
{{/each}}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div class="react-datepicker__time-container">
|
|
104
|
+
<div class="react-datepicker__time">
|
|
105
|
+
<div class="react-datepicker__time-box react-datepicker__time-box--accessible">
|
|
106
|
+
<ul class="react-datepicker__time-list">
|
|
107
|
+
{{#each this.times as |time|}}
|
|
108
|
+
<li
|
|
109
|
+
role="option"
|
|
110
|
+
class={{concat
|
|
111
|
+
"react-datepicker__time-list-item"
|
|
112
|
+
(if (eq time this.selectedTime) " react-datepicker__time-list-item--selected")
|
|
113
|
+
}}
|
|
114
|
+
{{on "click" (fn this.selectTime time)}}
|
|
115
|
+
>
|
|
116
|
+
{{time}}
|
|
117
|
+
</li>
|
|
118
|
+
{{/each}}
|
|
119
|
+
</ul>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</EuiFormControlLayout>
|
|
125
|
+
</div>
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
|
+
import Component from '@glimmer/component';
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { helper } from '@ember/component/helper';
|
|
5
|
+
import moment from 'moment';
|
|
6
|
+
// import { isDayDisabled, isOutOfBounds } from '../utils/date-utils';
|
|
7
|
+
|
|
8
|
+
const isSameDayHelper = helper(function ([year, month, day, selectedDate]: [
|
|
9
|
+
number,
|
|
10
|
+
number,
|
|
11
|
+
number,
|
|
12
|
+
moment.Moment
|
|
13
|
+
]) {
|
|
14
|
+
if (!selectedDate) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return (
|
|
18
|
+
selectedDate.year() === year &&
|
|
19
|
+
selectedDate.month() === month &&
|
|
20
|
+
selectedDate.date() === day
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
interface DatetimePickerArgs {
|
|
25
|
+
selected: moment.Moment;
|
|
26
|
+
onChange: (value: any) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface Day {
|
|
30
|
+
day: number;
|
|
31
|
+
month: number;
|
|
32
|
+
year: number;
|
|
33
|
+
isOutside: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default class DatetimePicker extends Component<DatetimePickerArgs> {
|
|
37
|
+
@tracked month: number = 0;
|
|
38
|
+
@tracked year: number = 0;
|
|
39
|
+
@tracked monthMoment: moment.Moment;
|
|
40
|
+
// Used to style the days outside of the current month
|
|
41
|
+
@tracked offset: number = 0;
|
|
42
|
+
@tracked selectedDate?: moment.Moment;
|
|
43
|
+
@tracked selectedTime?: string;
|
|
44
|
+
@tracked today: moment.Moment;
|
|
45
|
+
|
|
46
|
+
momentConfig: {
|
|
47
|
+
year: number;
|
|
48
|
+
month: number;
|
|
49
|
+
day: number;
|
|
50
|
+
hour: number;
|
|
51
|
+
minute: number;
|
|
52
|
+
second: number;
|
|
53
|
+
millisecond: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
isSameDayHelper = isSameDayHelper;
|
|
57
|
+
|
|
58
|
+
constructor(owner: unknown, args: DatetimePickerArgs) {
|
|
59
|
+
super(owner, args);
|
|
60
|
+
|
|
61
|
+
if (this.args.selected) {
|
|
62
|
+
this.monthMoment = this.args.selected;
|
|
63
|
+
this.selectedDate = this.args.selected;
|
|
64
|
+
} else {
|
|
65
|
+
this.monthMoment = moment([this.year, this.month]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.momentConfig = {
|
|
69
|
+
year: this.monthMoment.year(),
|
|
70
|
+
month: this.monthMoment.month(),
|
|
71
|
+
day: this.monthMoment.date(),
|
|
72
|
+
hour: this.monthMoment.hour(),
|
|
73
|
+
minute: this.monthMoment.minute(),
|
|
74
|
+
second: 0,
|
|
75
|
+
millisecond: 0
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.month = this.momentConfig.month;
|
|
79
|
+
this.year = this.momentConfig.year;
|
|
80
|
+
let hour = this.momentConfig.hour;
|
|
81
|
+
let minute = this.momentConfig.minute;
|
|
82
|
+
let hourStr = hour < 10 ? `0${hour}` : hour;
|
|
83
|
+
let minuteStr = minute < 10 ? `0${minute}` : minute;
|
|
84
|
+
this.selectedTime = `${hourStr}:${minuteStr}`;
|
|
85
|
+
|
|
86
|
+
this.offset = this.monthMoment.clone().startOf('month').day();
|
|
87
|
+
|
|
88
|
+
this.today = moment();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get monthNames() {
|
|
92
|
+
return moment.months().map((month, i) => {
|
|
93
|
+
return {
|
|
94
|
+
text: month,
|
|
95
|
+
value: i
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get years() {
|
|
101
|
+
return Array.from(Array(15).keys()).map((_, i) => {
|
|
102
|
+
// Create a list of years +/- 7 from the current year
|
|
103
|
+
let year = this.year - 7 + i;
|
|
104
|
+
return {
|
|
105
|
+
text: year,
|
|
106
|
+
value: year
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get times() {
|
|
112
|
+
const timesArray = [];
|
|
113
|
+
// Create entries every 30 minutes
|
|
114
|
+
for (let i = 0; i < 24; i++) {
|
|
115
|
+
let hour = i < 10 ? `0${i}` : i;
|
|
116
|
+
timesArray.push(`${hour}:00`, `${hour}:30`);
|
|
117
|
+
}
|
|
118
|
+
return timesArray;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
get days() {
|
|
122
|
+
// Used for showing days outside of the current month
|
|
123
|
+
// const prevMonth = moment([this.year, this.month - 1]);
|
|
124
|
+
const prevMonth = this.monthMoment.clone().subtract(1, 'month');
|
|
125
|
+
const nextMonth = this.monthMoment.clone().add(1, 'month');
|
|
126
|
+
const offset = this.offset;
|
|
127
|
+
let daysInMonth = this.monthMoment.daysInMonth();
|
|
128
|
+
let daysInPrevMonth = prevMonth.daysInMonth();
|
|
129
|
+
|
|
130
|
+
const daysArray = [];
|
|
131
|
+
for (let i = 0; i < daysInMonth; i++) {
|
|
132
|
+
daysArray[i] = {
|
|
133
|
+
day: i + 1
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Fill the previous and next month days
|
|
138
|
+
for (let i = 0, d = daysInPrevMonth; i < offset; i++, d--) {
|
|
139
|
+
daysArray.unshift({
|
|
140
|
+
day: d,
|
|
141
|
+
month: prevMonth.month(),
|
|
142
|
+
year: prevMonth.year(),
|
|
143
|
+
isOutside: true
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// All months fit within 6 weeks (42 days)
|
|
147
|
+
for (let d = 1, i = daysInMonth + offset; i < 42; d++, i++) {
|
|
148
|
+
daysArray.push({
|
|
149
|
+
day: d,
|
|
150
|
+
month: nextMonth.month(),
|
|
151
|
+
year: nextMonth.year(),
|
|
152
|
+
isOutside: true
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// All months fit within 6 weeks (42 days)
|
|
157
|
+
// but depending on the starting day, one week may not be needed
|
|
158
|
+
const daysMatrix = [];
|
|
159
|
+
const weeks = daysInMonth + offset > 35 ? 6 : 5;
|
|
160
|
+
for (let i = 0; i < weeks; i++) {
|
|
161
|
+
daysMatrix[i] = daysArray.slice(i * 7, i * 7 + 7);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return daysMatrix;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
updateDate() {
|
|
168
|
+
this.year = this.monthMoment.year();
|
|
169
|
+
this.month = this.monthMoment.month();
|
|
170
|
+
this.offset = this.monthMoment.clone().startOf('month').day();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@action selectTime(time: string) {
|
|
174
|
+
this.selectedTime = time;
|
|
175
|
+
const [hour, minute] = time.split(':');
|
|
176
|
+
this.momentConfig.hour = parseInt(hour);
|
|
177
|
+
this.momentConfig.minute = parseInt(minute);
|
|
178
|
+
this.momentConfig.second = 0;
|
|
179
|
+
this.momentConfig.millisecond = 0;
|
|
180
|
+
this.selectedDate = moment(this.momentConfig);
|
|
181
|
+
this.args.onChange(this.selectedDate);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@action selectDate(day: Day) {
|
|
185
|
+
// Only outside days will have year/month
|
|
186
|
+
this.momentConfig.year = day.year || this.year;
|
|
187
|
+
this.momentConfig.month = day.month || this.month;
|
|
188
|
+
this.momentConfig.day = day.day;
|
|
189
|
+
this.selectedDate = moment(this.momentConfig);
|
|
190
|
+
this.args.onChange(this.selectedDate);
|
|
191
|
+
|
|
192
|
+
// Update the state to show the selected month properly
|
|
193
|
+
if (day.isOutside) {
|
|
194
|
+
this.monthMoment.month(day.month);
|
|
195
|
+
this.monthMoment.year(day.year);
|
|
196
|
+
this.updateDate();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// @action setSelected(date, event, keepInput) {
|
|
201
|
+
// let changedDate = date;
|
|
202
|
+
|
|
203
|
+
// if (changedDate !== null && isDayDisabled(changedDate, this.props)) {
|
|
204
|
+
// if (isOutOfBounds(changedDate, this.props)) {
|
|
205
|
+
// this.props.onChange(date, event);
|
|
206
|
+
// this.props.onSelect(changedDate, event);
|
|
207
|
+
// }
|
|
208
|
+
|
|
209
|
+
// return;
|
|
210
|
+
// }
|
|
211
|
+
|
|
212
|
+
// if (changedDate !== null && this.props.selected) {
|
|
213
|
+
// let selected = this.props.selected;
|
|
214
|
+
// if (keepInput) selected = newDate(changedDate);
|
|
215
|
+
// changedDate = setTime(newDate(changedDate), {
|
|
216
|
+
// hour: getHour(selected),
|
|
217
|
+
// minute: getMinute(selected),
|
|
218
|
+
// second: getSecond(selected),
|
|
219
|
+
// millisecond: getMillisecond(selected),
|
|
220
|
+
// });
|
|
221
|
+
// }
|
|
222
|
+
|
|
223
|
+
// if (
|
|
224
|
+
// !isSameTime(this.props.selected, changedDate) ||
|
|
225
|
+
// this.props.allowSameDay
|
|
226
|
+
// ) {
|
|
227
|
+
// if (changedDate !== null) {
|
|
228
|
+
// if (!this.props.inline) {
|
|
229
|
+
// this.setState({
|
|
230
|
+
// preSelection: changedDate
|
|
231
|
+
// });
|
|
232
|
+
// }
|
|
233
|
+
// }
|
|
234
|
+
// this.props.onChange(changedDate, event);
|
|
235
|
+
// }
|
|
236
|
+
|
|
237
|
+
// this.props.onSelect(changedDate, event);
|
|
238
|
+
|
|
239
|
+
// if (!keepInput) {
|
|
240
|
+
// this.setState({ inputValue: null });
|
|
241
|
+
// }
|
|
242
|
+
// }
|
|
243
|
+
|
|
244
|
+
@action setMonth(month: string) {
|
|
245
|
+
this.monthMoment.month(parseInt(month));
|
|
246
|
+
this.updateDate();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@action increaseMonth() {
|
|
250
|
+
this.monthMoment.add(1, 'month');
|
|
251
|
+
this.updateDate();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@action decreaseMonth() {
|
|
255
|
+
this.monthMoment.subtract(1, 'month');
|
|
256
|
+
this.updateDate();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{{#let
|
|
2
|
+
(class-names
|
|
3
|
+
"euiDatePopoverButton"
|
|
4
|
+
(concat "euiDatePopoverButton--" @position)
|
|
5
|
+
(if @compressed "euiDatePopoverButton--compressed")
|
|
6
|
+
(if this.isOpen "euiDatePopoverButton-isSelected")
|
|
7
|
+
(if @isInvalid "euiDatePopoverButton-isInvalid")
|
|
8
|
+
(if @needsUpdating "euiDatePopoverButton-needsUpdating")
|
|
9
|
+
(if @isDisabled "euiDatePopoverButton-disabled")
|
|
10
|
+
)
|
|
11
|
+
as |classes|
|
|
12
|
+
}}
|
|
13
|
+
<EuiPopover
|
|
14
|
+
@className={{@className}}
|
|
15
|
+
@isOpen={{this.isOpen}}
|
|
16
|
+
@closePopover={{set this "isOpen" false}}
|
|
17
|
+
@anchorPosition={{this.anchorPosition}}
|
|
18
|
+
@panelPaddingSize="none"
|
|
19
|
+
@display="block"
|
|
20
|
+
>
|
|
21
|
+
<:button>
|
|
22
|
+
<button
|
|
23
|
+
type="button"
|
|
24
|
+
{{!-- onClick={onPopoverToggle} --}}
|
|
25
|
+
class={{classes}}
|
|
26
|
+
title={{this.formattedValue}}
|
|
27
|
+
disabled={{@isDisabled}}
|
|
28
|
+
...attributes
|
|
29
|
+
{{on "click" (set this "isOpen" (not this.isOpen))}}
|
|
30
|
+
>
|
|
31
|
+
{{this.formattedValue}}
|
|
32
|
+
</button>
|
|
33
|
+
</:button>
|
|
34
|
+
|
|
35
|
+
<:content>
|
|
36
|
+
<EuiSuperDatePicker::DatePopover::EuiDatePopoverContent
|
|
37
|
+
@position={{@position}}
|
|
38
|
+
@value={{@value}}
|
|
39
|
+
@roundUp={{@roundUp}}
|
|
40
|
+
@dateFormat={{@dateFormat}}
|
|
41
|
+
@timeFormat={{@timeFormat}}
|
|
42
|
+
@locale={{@locale}}
|
|
43
|
+
@utcOffset={{@utcOffset}}
|
|
44
|
+
@timeOptions={{@timeOptions}}
|
|
45
|
+
@onChange={{@onChange}}
|
|
46
|
+
/>
|
|
47
|
+
</:content>
|
|
48
|
+
</EuiPopover>
|
|
49
|
+
{{/let}}
|