cronofy-elements 1.44.1 → 1.47.0
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/build/CronofyElements.v1.47.0.js +2 -0
- package/build/{CronofyElements.v1.44.1.js.LICENSE.txt → CronofyElements.v1.47.0.js.LICENSE.txt} +0 -0
- package/build/npm/CronofyElements.js +2 -2
- package/demo/date-time-picker.ejs +5 -32
- package/demo/rules.ejs +7 -1
- package/package.json +1 -1
- package/src/js/components/AvailabilityRules/AvailabilityRules.js +15 -1
- package/src/js/components/AvailabilityRules/CalendarSelector.js +1 -1
- package/src/js/components/AvailabilityRules/Calendars.js +1 -1
- package/src/js/components/AvailabilityRules/TimeZoneDisplay.js +13 -2
- package/src/js/components/AvailabilityRules/Wrapper.js +45 -34
- package/src/js/components/AvailabilityRules/scss/_base.buttons.scss +58 -0
- package/src/js/components/AvailabilityRules/scss/_base.theme.scss +4 -0
- package/src/js/components/AvailabilityRules/scss/_components.timezoneselector.scss +74 -0
- package/src/js/components/AvailabilityRules/scss/_generic.reset.scss +13 -0
- package/src/js/components/AvailabilityRules/scss/_settings.colours.scss +12 -0
- package/src/js/components/AvailabilityRules/scss/availabilityrules.scss +5 -0
- package/src/js/components/AvailabilityRules/utils/tz-utils.js +44 -0
- package/src/js/components/DateTimePicker/Calendar.js +1 -1
- package/src/js/components/DateTimePicker/CalendarHeader.js +1 -1
- package/src/js/components/DateTimePicker/Confirm.js +38 -2
- package/src/js/components/DateTimePicker/DateTimePicker.js +1 -4
- package/src/js/components/DateTimePicker/DayButton.js +1 -1
- package/src/js/components/DateTimePicker/Details.js +5 -2
- package/src/js/components/DateTimePicker/SequencedSlotButton.js +1 -1
- package/src/js/components/DateTimePicker/SlotButton.js +1 -1
- package/src/js/components/DateTimePicker/Wrapper.js +115 -38
- package/src/js/components/DateTimePicker/contexts/status-reducer.js +29 -8
- package/src/js/components/DateTimePicker/scss/_components.confirm.scss +10 -0
- package/src/js/components/DateTimePicker/utils/slots.js +23 -78
- package/src/js/components/{DateTimePicker → generic}/TimeZoneSelector.js +10 -16
- package/src/js/{components/DateTimePicker/contexts → contexts}/tz-context.js +0 -0
- package/src/js/helpers/init.DateTimePicker.js +17 -0
- package/src/js/{components/DateTimePicker/utils → helpers}/tz-list.js +0 -0
- package/tests/AvailabilityRules/__snapshots__/AvailabilityRules.test.js.snap +37 -6
- package/tests/DateTimePicker/SequencedSlotButton.test.js +1 -1
- package/tests/DateTimePicker/SlotButton.test.js +1 -1
- package/tests/DateTimePicker/contexts/status-reducer.test.js +180 -24
- package/tests/DateTimePicker/dummy-data.js +186 -1
- package/tests/DateTimePicker/utils.test.js +32 -3
- package/tests/components/TimezoneSelector.test.js +124 -0
- package/build/CronofyElements.v1.44.1.js +0 -2
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
sequence: [
|
|
50
50
|
{
|
|
51
51
|
sequence_id: "test",
|
|
52
|
+
sequence_title: "Test Event One",
|
|
52
53
|
ordinal: 1,
|
|
53
54
|
participants: [
|
|
54
55
|
{
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
},
|
|
67
68
|
{
|
|
68
69
|
sequence_id: "test-1",
|
|
70
|
+
sequence_title: "Test Event Two",
|
|
69
71
|
ordinal: 2,
|
|
70
72
|
participants: [
|
|
71
73
|
{
|
|
@@ -86,31 +88,7 @@
|
|
|
86
88
|
minimum: { minutes: 15 }
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
sequence_id: "test-2",
|
|
92
|
-
ordinal: 3,
|
|
93
|
-
participants: [
|
|
94
|
-
{
|
|
95
|
-
required: "all",
|
|
96
|
-
members: [
|
|
97
|
-
{
|
|
98
|
-
sub: "<%= sub %>",
|
|
99
|
-
// managed_availability: true,
|
|
100
|
-
// availability_rule_ids: ["weekly_work_hours"]
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
],
|
|
105
|
-
required_duration: { minutes: 30 },
|
|
106
|
-
start_interval: { minutes: 10 },
|
|
107
|
-
buffer: {
|
|
108
|
-
before: {
|
|
109
|
-
minimum: { minutes: 15 }
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
|
|
91
|
+
},
|
|
114
92
|
],
|
|
115
93
|
query_periods: [
|
|
116
94
|
{ start: slotTimes(01,"08:00"), end: slotTimes(31,"17:00") }
|
|
@@ -136,15 +114,10 @@
|
|
|
136
114
|
]
|
|
137
115
|
}
|
|
138
116
|
],
|
|
139
|
-
required_duration: { minutes:
|
|
117
|
+
required_duration: { minutes: 15 },
|
|
140
118
|
//start_interval: { minutes: 15 },
|
|
141
119
|
query_periods: [
|
|
142
|
-
{ start: slotTimes(31,"03:00"), end: slotTimes(
|
|
143
|
-
{ start: slotTimes(32,"09:00"), end: slotTimes(32,"13:00") },
|
|
144
|
-
{ start: slotTimes(32,"14:00"), end: slotTimes(32,"17:00") },
|
|
145
|
-
{ start: slotTimes(35,"09:00"), end: slotTimes(35,"13:00") },
|
|
146
|
-
{ start: slotTimes(36,"14:00"), end: slotTimes(36,"17:00") },
|
|
147
|
-
{ start: slotTimes(38,"09:00"), end: slotTimes(65,"22:00") }
|
|
120
|
+
{ start: slotTimes(31,"03:00"), end: slotTimes(150,"12:00") },
|
|
148
121
|
]
|
|
149
122
|
},
|
|
150
123
|
// tzid: "America/Mexico_City",
|
package/demo/rules.ejs
CHANGED
|
@@ -77,7 +77,13 @@
|
|
|
77
77
|
// start_time: "09:00",
|
|
78
78
|
// end_time: "13:00"
|
|
79
79
|
// }],
|
|
80
|
-
// auto_create_rules: true
|
|
80
|
+
// auto_create_rules: true,
|
|
81
|
+
// tz_list: [
|
|
82
|
+
// "America/Sao_Paulo",
|
|
83
|
+
// "Etc/UTC",
|
|
84
|
+
// "Pacific/Fakaofo",
|
|
85
|
+
// "Europe/London",
|
|
86
|
+
// ],
|
|
81
87
|
},
|
|
82
88
|
callback: cb => console.log('rules callback',cb),
|
|
83
89
|
styles: {
|
package/package.json
CHANGED
|
@@ -2,9 +2,14 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
import { I18nProvider } from "../../contexts/i18n-context";
|
|
4
4
|
import { LogProvider } from "../../contexts/log-context";
|
|
5
|
+
import { TzProvider } from "../../contexts/tz-context";
|
|
6
|
+
|
|
7
|
+
import { parseTzList, getInitialSelectedTzid } from "./utils/tz-utils";
|
|
5
8
|
|
|
6
9
|
import Wrapper from "./Wrapper";
|
|
7
10
|
|
|
11
|
+
import "./scss/availabilityrules.scss";
|
|
12
|
+
|
|
8
13
|
const AvailabilityRules = ({ options }) => {
|
|
9
14
|
const logOptions = {
|
|
10
15
|
mode: options.config.logs,
|
|
@@ -19,10 +24,19 @@ const AvailabilityRules = ({ options }) => {
|
|
|
19
24
|
tzid: options.tzid,
|
|
20
25
|
};
|
|
21
26
|
|
|
27
|
+
const tzList = parseTzList(options.config.tz_list, options.tzid);
|
|
28
|
+
const selectedTzid = getInitialSelectedTzid(tzList, options.tzid);
|
|
29
|
+
const tzOptions = {
|
|
30
|
+
selectedTzid: selectedTzid,
|
|
31
|
+
list: tzList,
|
|
32
|
+
};
|
|
33
|
+
|
|
22
34
|
return (
|
|
23
35
|
<LogProvider options={logOptions}>
|
|
24
36
|
<I18nProvider options={i18nOptions}>
|
|
25
|
-
<
|
|
37
|
+
<TzProvider options={tzOptions}>
|
|
38
|
+
<Wrapper options={options} />
|
|
39
|
+
</TzProvider>
|
|
26
40
|
</I18nProvider>
|
|
27
41
|
</LogProvider>
|
|
28
42
|
);
|
|
@@ -2,27 +2,38 @@ import React, { useContext } from "react";
|
|
|
2
2
|
import { css } from "@emotion/core";
|
|
3
3
|
|
|
4
4
|
import { ExtrasContext, StatusContext, ThemeContext } from "./Wrapper";
|
|
5
|
+
import { useTz } from "../../contexts/tz-context";
|
|
5
6
|
import { useI18n } from "../../contexts/i18n-context";
|
|
6
|
-
import
|
|
7
|
+
import TimeZoneSelector from "../generic/TimeZoneSelector";
|
|
7
8
|
|
|
8
9
|
const TimeZoneDisplay = () => {
|
|
9
10
|
const [extras, setExtras] = useContext(ExtrasContext);
|
|
10
11
|
const [status, setStatus] = useContext(StatusContext);
|
|
11
12
|
const i18n = useI18n();
|
|
12
13
|
const [theme, setTheme] = useContext(ThemeContext);
|
|
14
|
+
const [tz, setTz] = useTz();
|
|
13
15
|
return (
|
|
14
16
|
<div
|
|
15
17
|
css={css`
|
|
16
18
|
flex-grow: 1;
|
|
17
19
|
display: flex;
|
|
18
20
|
width: 100%;
|
|
21
|
+
padding-right: 1em;
|
|
19
22
|
@media (max-width: ${theme.sizes.breakpoints.small}px) {
|
|
20
23
|
margin-bottom: 16px;
|
|
21
24
|
}
|
|
22
25
|
`}
|
|
23
26
|
className={`${theme.prefix}__timezone`}
|
|
24
27
|
>
|
|
25
|
-
|
|
28
|
+
<p
|
|
29
|
+
css={css`
|
|
30
|
+
padding: 0.3em 0.6em 0 0;
|
|
31
|
+
margin: 0;
|
|
32
|
+
`}
|
|
33
|
+
>
|
|
34
|
+
{i18n.t("time_zone")}
|
|
35
|
+
</p>
|
|
36
|
+
<TimeZoneSelector locale={status.locale} theme={theme} tz={tz} setTz={setTz} />
|
|
26
37
|
</div>
|
|
27
38
|
);
|
|
28
39
|
};
|
|
@@ -14,10 +14,12 @@ import {
|
|
|
14
14
|
parseAccountOptions,
|
|
15
15
|
buildRuleTemplate,
|
|
16
16
|
} from "../../helpers/utils.AvailabilityRules";
|
|
17
|
-
import {
|
|
17
|
+
import { getInitialSelectedTzid } from "./utils/tz-utils";
|
|
18
|
+
import { parseStyleOptions, classBuilder } from "../../helpers/theming";
|
|
18
19
|
import { globals } from "../../styles/utils";
|
|
19
20
|
import { useI18n } from "../../contexts/i18n-context";
|
|
20
21
|
import { useLog } from "../../contexts/log-context";
|
|
22
|
+
import { useTz } from "../../contexts/tz-context";
|
|
21
23
|
|
|
22
24
|
import Calendars from "./Calendars";
|
|
23
25
|
import Container from "../generic/Container";
|
|
@@ -37,6 +39,7 @@ export const ThemeContext = React.createContext();
|
|
|
37
39
|
const Wrapper = ({ options }) => {
|
|
38
40
|
const i18n = useI18n();
|
|
39
41
|
const log = useLog();
|
|
42
|
+
const [tz, setTz] = useTz();
|
|
40
43
|
|
|
41
44
|
const [account, setAccount] = useState(() => parseAccountOptions(options));
|
|
42
45
|
const [calendars, setCalendars] = useState(() => ({
|
|
@@ -52,7 +55,7 @@ const Wrapper = ({ options }) => {
|
|
|
52
55
|
saved: false,
|
|
53
56
|
savedSuccess: false,
|
|
54
57
|
locale: options.locale,
|
|
55
|
-
tzid:
|
|
58
|
+
tzid: tz.selectedTzid.tzid,
|
|
56
59
|
callback: options.callback ? options.callback : cb => {},
|
|
57
60
|
startDay: options.config.startDay,
|
|
58
61
|
defaultWeeklyPeriods: options.config.defaultWeeklyPeriods,
|
|
@@ -83,19 +86,23 @@ const Wrapper = ({ options }) => {
|
|
|
83
86
|
)
|
|
84
87
|
);
|
|
85
88
|
|
|
86
|
-
const [theme, setTheme] = useState(() =>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
const [theme, setTheme] = useState(() => {
|
|
90
|
+
const styles = parseStyleOptions(options.styles, "AvailabilityViewer");
|
|
91
|
+
return {
|
|
92
|
+
...styles,
|
|
93
|
+
classBuilder: classBuilder(styles.prefix, "AR"),
|
|
94
|
+
sizes: {
|
|
95
|
+
breakpoints: {
|
|
96
|
+
small: 650,
|
|
97
|
+
},
|
|
98
|
+
labelWidth: 60,
|
|
99
|
+
labelWidthSmall: 24,
|
|
100
|
+
columnWidth: 100,
|
|
101
|
+
wrapperWidth: false,
|
|
102
|
+
wrapperUnderflow: 0,
|
|
91
103
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
columnWidth: 100,
|
|
95
|
-
wrapperWidth: false,
|
|
96
|
-
wrapperUnderflow: 0,
|
|
97
|
-
},
|
|
98
|
-
}));
|
|
104
|
+
};
|
|
105
|
+
});
|
|
99
106
|
|
|
100
107
|
const handleRuleChange = (IDs, toggleStatus) => {
|
|
101
108
|
const availability = toggleStatus === "available";
|
|
@@ -108,17 +115,7 @@ const Wrapper = ({ options }) => {
|
|
|
108
115
|
const allSlots = { ...slots, ...newSlots };
|
|
109
116
|
setSlots(allSlots);
|
|
110
117
|
const newRules = buildNewRules(allSlots);
|
|
111
|
-
|
|
112
|
-
notification: {
|
|
113
|
-
type: "availability_rule_edited",
|
|
114
|
-
},
|
|
115
|
-
availability_rule: {
|
|
116
|
-
...account,
|
|
117
|
-
calendar_ids: calendars.active,
|
|
118
|
-
weekly_periods: newRules,
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
status.callback(callbackContent);
|
|
118
|
+
setRules(newRules);
|
|
122
119
|
};
|
|
123
120
|
|
|
124
121
|
useEffect(() => {
|
|
@@ -141,7 +138,6 @@ const Wrapper = ({ options }) => {
|
|
|
141
138
|
|
|
142
139
|
useEffect(() => {
|
|
143
140
|
if (!status.loading && !status.error) {
|
|
144
|
-
const newRules = buildNewRules(slots);
|
|
145
141
|
const callbackContent = {
|
|
146
142
|
notification: {
|
|
147
143
|
type: "availability_rule_edited",
|
|
@@ -149,12 +145,12 @@ const Wrapper = ({ options }) => {
|
|
|
149
145
|
availability_rule: {
|
|
150
146
|
...account,
|
|
151
147
|
calendar_ids: calendars.active,
|
|
152
|
-
weekly_periods:
|
|
148
|
+
weekly_periods: rules,
|
|
153
149
|
},
|
|
154
150
|
};
|
|
155
151
|
status.callback(callbackContent);
|
|
156
152
|
}
|
|
157
|
-
}, [calendars]);
|
|
153
|
+
}, [calendars, account, rules]);
|
|
158
154
|
|
|
159
155
|
useEffect(() => {
|
|
160
156
|
// Query the API for rules and calendars, but don't do anything until
|
|
@@ -173,7 +169,7 @@ const Wrapper = ({ options }) => {
|
|
|
173
169
|
.then(res => {
|
|
174
170
|
const isNewRule = res[0].type === 404;
|
|
175
171
|
const rulesResponse = isNewRule
|
|
176
|
-
? buildRuleTemplate(options.config.defaultWeeklyPeriods,
|
|
172
|
+
? buildRuleTemplate(options.config.defaultWeeklyPeriods, tz.selectedTzid.tzid)
|
|
177
173
|
: res[0];
|
|
178
174
|
|
|
179
175
|
if (isNewRule) {
|
|
@@ -198,6 +194,15 @@ const Wrapper = ({ options }) => {
|
|
|
198
194
|
tzid: rulesResponse.availability_rule.tzid,
|
|
199
195
|
}));
|
|
200
196
|
|
|
197
|
+
const selectedTzid = getInitialSelectedTzid(
|
|
198
|
+
tz.list,
|
|
199
|
+
rulesResponse.availability_rule.tzid
|
|
200
|
+
);
|
|
201
|
+
setTz({
|
|
202
|
+
list: tz.list,
|
|
203
|
+
selectedTzid: selectedTzid,
|
|
204
|
+
});
|
|
205
|
+
|
|
201
206
|
setSlots(slots => {
|
|
202
207
|
const hydratedSlots = checkSlotAvailability(
|
|
203
208
|
rulesResponse.availability_rule.weekly_periods,
|
|
@@ -269,11 +274,17 @@ const Wrapper = ({ options }) => {
|
|
|
269
274
|
}
|
|
270
275
|
}, [status]);
|
|
271
276
|
|
|
272
|
-
|
|
273
|
-
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
if (tz.selectedTzid.tzid) {
|
|
279
|
+
setAccount(account => ({
|
|
280
|
+
...account,
|
|
281
|
+
tzid: tz.selectedTzid.tzid,
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
}, [tz.selectedTzid.tzid]);
|
|
274
285
|
|
|
275
|
-
|
|
276
|
-
const rulesRequest = { ...account, weekly_periods:
|
|
286
|
+
const generateRules = () => {
|
|
287
|
+
const rulesRequest = { ...account, weekly_periods: rules };
|
|
277
288
|
|
|
278
289
|
let tempStatus = status;
|
|
279
290
|
|
|
@@ -373,7 +384,7 @@ const Wrapper = ({ options }) => {
|
|
|
373
384
|
overflow: hidden;
|
|
374
385
|
}
|
|
375
386
|
`}
|
|
376
|
-
className={
|
|
387
|
+
className={theme.classBuilder()}
|
|
377
388
|
>
|
|
378
389
|
<ThemeContext.Provider value={[theme, setTheme]}>
|
|
379
390
|
<StatusContext.Provider value={[status, setStatus]}>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.AR__button {
|
|
2
|
+
appearance: none;
|
|
3
|
+
background: none;
|
|
4
|
+
border: none;
|
|
5
|
+
border-radius: 0;
|
|
6
|
+
font-family: inherit;
|
|
7
|
+
position: relative;
|
|
8
|
+
display: block;
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
font-size: 1em;
|
|
11
|
+
border: 0.1em solid var(--greyMid);
|
|
12
|
+
background-color: var(--white);
|
|
13
|
+
|
|
14
|
+
&:focus {
|
|
15
|
+
border-color: var(--availableActive);
|
|
16
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
17
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
18
|
+
outline: none;
|
|
19
|
+
}
|
|
20
|
+
&:hover {
|
|
21
|
+
border-color: var(--availableActive);
|
|
22
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
23
|
+
background-color: var(--availableHover);
|
|
24
|
+
color: var(--black);
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:active {
|
|
29
|
+
background-color: var(--availableActive);
|
|
30
|
+
color: var(--black);
|
|
31
|
+
outline: none;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.AR__disabled-button {
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
border: unset;
|
|
38
|
+
background-color: unset;
|
|
39
|
+
|
|
40
|
+
&:focus {
|
|
41
|
+
border-color: unset;
|
|
42
|
+
box-shadow: unset;
|
|
43
|
+
outline: none;
|
|
44
|
+
background-color: unset;
|
|
45
|
+
}
|
|
46
|
+
&:hover {
|
|
47
|
+
border-color: unset;
|
|
48
|
+
box-shadow: unset;
|
|
49
|
+
outline: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&:active {
|
|
53
|
+
border-color: unset;
|
|
54
|
+
box-shadow: unset;
|
|
55
|
+
outline: none;
|
|
56
|
+
background-color: unset;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
.AR__timezone-selector {
|
|
2
|
+
position: relative;
|
|
3
|
+
flex-grow: 1;
|
|
4
|
+
max-width: 16rem;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.AR__timezone-selector--button {
|
|
8
|
+
@extend .AR__button;
|
|
9
|
+
display: inline-block;
|
|
10
|
+
border: 0.1em solid var(--greyMid);
|
|
11
|
+
background: var(--white);
|
|
12
|
+
padding: 0.3em 1em;
|
|
13
|
+
text-align: left;
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-radius: 0.4em;
|
|
16
|
+
z-index: 4;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.AR__timezone-selector--icon {
|
|
20
|
+
width: 1em;
|
|
21
|
+
height: 1em;
|
|
22
|
+
margin-top: 0.2em;
|
|
23
|
+
fill: var(--grey);
|
|
24
|
+
float: right;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.AR__timezone-selector--icon-open {
|
|
28
|
+
transform: scaleY(-1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.AR__timezone-selector--listbox-wrapper {
|
|
32
|
+
@extend %unset;
|
|
33
|
+
position: absolute;
|
|
34
|
+
width: 100%;
|
|
35
|
+
border: 0.1em solid var(--greyMid);
|
|
36
|
+
background-color: var(--white);
|
|
37
|
+
border-top: 0;
|
|
38
|
+
padding-top: 1.15em;
|
|
39
|
+
top: 1em;
|
|
40
|
+
z-index: 3;
|
|
41
|
+
border-radius: 0 0 0.4em 0.4em;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.AR__timezone-selector--listbox {
|
|
45
|
+
@extend %unset;
|
|
46
|
+
width: 100%;
|
|
47
|
+
max-height: 15em;
|
|
48
|
+
overflow-y: auto;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.AR__timezone-selector--option {
|
|
52
|
+
@extend %unset;
|
|
53
|
+
display: block;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
padding: 0.5em 1em;
|
|
56
|
+
position: relative;
|
|
57
|
+
line-height: 1.8em;
|
|
58
|
+
|
|
59
|
+
&:hover {
|
|
60
|
+
background-color: var(--availableHover);
|
|
61
|
+
color: var(--black);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.AR__timezone-selector--focused {
|
|
66
|
+
border-color: var(--availableActive);
|
|
67
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
68
|
+
outline: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.AR__timezone-selector--selected {
|
|
72
|
+
background-color: var(--availableHover);
|
|
73
|
+
color: var(--black);
|
|
74
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//Unsetting styles to avoid clashes with styles outside the component
|
|
2
|
+
%unset {
|
|
3
|
+
padding: unset;
|
|
4
|
+
margin-top: unset;
|
|
5
|
+
margin-bottom: unset;
|
|
6
|
+
margin-left: unset;
|
|
7
|
+
margin-right: unset;
|
|
8
|
+
border: unset;
|
|
9
|
+
background: unset;
|
|
10
|
+
border-spacing: 0;
|
|
11
|
+
font-style: unset;
|
|
12
|
+
list-style: unset;
|
|
13
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import moment from "moment-timezone";
|
|
2
|
+
import { humanizeTzName } from "../../../helpers/utils";
|
|
3
|
+
import { defaultTimeZones } from "../../../helpers/tz-list";
|
|
4
|
+
|
|
5
|
+
export const createTzObject = tzid => {
|
|
6
|
+
const name = humanizeTzName(tzid);
|
|
7
|
+
|
|
8
|
+
const zone = moment.tz(tzid);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
tzid: tzid,
|
|
12
|
+
offset: zone.format("Z"),
|
|
13
|
+
offsetMins: zone.utcOffset(),
|
|
14
|
+
name: name,
|
|
15
|
+
abbr: zone.zoneAbbr(),
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const parseTzList = (timezones, tzid) => {
|
|
20
|
+
const tzList = timezones ? timezones : moment.tz.names();
|
|
21
|
+
const filtered = timezones ? timezones : tzList.filter(item => defaultTimeZones.includes(item));
|
|
22
|
+
|
|
23
|
+
const result = [];
|
|
24
|
+
|
|
25
|
+
filtered.map(tz => {
|
|
26
|
+
const item = createTzObject(tz);
|
|
27
|
+
result.push(item);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const isInList = result.findIndex(item => tzid === item.tzid);
|
|
31
|
+
|
|
32
|
+
if (isInList <= -1) {
|
|
33
|
+
const item = createTzObject(tzid);
|
|
34
|
+
result.push(item);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
result.sort((tzA, tzB) => tzA.offsetMins - tzB.offsetMins);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const getInitialSelectedTzid = (tzList, tzid) => {
|
|
42
|
+
const result = tzList.find(tz => tzid === tz.tzid);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
@@ -14,7 +14,7 @@ import DayHeadings from "./DayHeadings";
|
|
|
14
14
|
|
|
15
15
|
import { useStatus } from "./contexts/status-context";
|
|
16
16
|
import { useTheme } from "./contexts/theme-context";
|
|
17
|
-
import { useTz } from "
|
|
17
|
+
import { useTz } from "../../contexts/tz-context";
|
|
18
18
|
|
|
19
19
|
const Calendar = () => {
|
|
20
20
|
const [status, dispatchStatus] = useStatus();
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const CalendarHeader = () => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import moment from "moment-timezone";
|
|
3
3
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const Confirm = ({ confirmButtonRef }) => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -12,6 +12,12 @@ const Confirm = ({ confirmButtonRef }) => {
|
|
|
12
12
|
const theme = useTheme();
|
|
13
13
|
const [tz] = useTz();
|
|
14
14
|
|
|
15
|
+
const [sequenceTitlePresent, setSequenceTitlePresent] = useState(
|
|
16
|
+
() =>
|
|
17
|
+
status.selected.sequence &&
|
|
18
|
+
status.selected.sequence.every(obj => Object.keys(obj).includes("sequence_title"))
|
|
19
|
+
);
|
|
20
|
+
|
|
15
21
|
const handleCancel = () => {
|
|
16
22
|
dispatchStatus({ type: "CANCEL_SLOT_SELECTION" });
|
|
17
23
|
};
|
|
@@ -52,6 +58,36 @@ const Confirm = ({ confirmButtonRef }) => {
|
|
|
52
58
|
)}{" "}
|
|
53
59
|
{`(${moment.tz(tz.selectedTzid.tzid).format("z")})`}
|
|
54
60
|
</p>
|
|
61
|
+
{status.selected.sequence && sequenceTitlePresent && (
|
|
62
|
+
<dl className={theme.classBuilder("confirm-details--sequence")}>
|
|
63
|
+
{status.selected.sequence.map((slot, k) => (
|
|
64
|
+
<div key={k}>
|
|
65
|
+
<dt
|
|
66
|
+
className={theme.classBuilder(
|
|
67
|
+
"confirm-details--sequence-title"
|
|
68
|
+
)}
|
|
69
|
+
>
|
|
70
|
+
{slot.sequence_title}
|
|
71
|
+
</dt>
|
|
72
|
+
<dd
|
|
73
|
+
className={theme.classBuilder("confirm-details--sequence-time")}
|
|
74
|
+
>
|
|
75
|
+
{i18n.customFormatedTimeZone(
|
|
76
|
+
moment(slot.start, "YYYY-MM-DDTHH:mm:00Z"),
|
|
77
|
+
tz.selectedTzid.tzid,
|
|
78
|
+
"LT"
|
|
79
|
+
)}
|
|
80
|
+
{" - "}
|
|
81
|
+
{i18n.customFormatedTimeZone(
|
|
82
|
+
moment(slot.end, "YYYY-MM-DDTHH:mm:00Z"),
|
|
83
|
+
tz.selectedTzid.tzid,
|
|
84
|
+
"LT"
|
|
85
|
+
)}
|
|
86
|
+
</dd>
|
|
87
|
+
</div>
|
|
88
|
+
))}
|
|
89
|
+
</dl>
|
|
90
|
+
)}
|
|
55
91
|
</div>
|
|
56
92
|
<button
|
|
57
93
|
className={theme.classBuilder("confirm-button")}
|