Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cronofy-elements

Package Overview
Dependencies
Maintainers
3
Versions
172
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cronofy-elements - npm Package Compare versions

Comparing version 1.40.2 to 1.41.0

build/CronofyElements.v1.41.0.js

2

package.json
{
"name": "cronofy-elements",
"version": "1.40.2",
"version": "1.41.0",
"description": "Fast track scheduling with Cronofy's embeddable UI Elements",

@@ -5,0 +5,0 @@ "main": "build/npm/CronofyElements.js",

@@ -1,5 +0,4 @@

import React, { useEffect, useState } from "react";
import React from "react";
import moment from "moment-timezone";
import { calculateMonthNav } from "./utils/calendar";
import { useI18n } from "../../contexts/i18n-context";

@@ -16,8 +15,10 @@ import { useStatus } from "./contexts/status-context";

const [monthState, setMonthState] = useState(() => calculateMonthNav(status.months));
const handlePrevMonth = () => {
const month = moment(status.monthlyView.month, "YYYY-MM")
.subtract(1, "month")
.format("YYYY-MM");
const handleMonthNav = target => {
dispatchStatus({
type: "SELECT_MONTH",
month: target,
month,
tzid: tz.selectedTzid.tzid,

@@ -27,6 +28,12 @@ });

useEffect(() => {
setMonthState(() => calculateMonthNav(status.months));
}, [status.months]);
const handleNextMonth = () => {
const month = moment(status.monthlyView.month, "YYYY-MM").add(1, "month").format("YYYY-MM");
dispatchStatus({
type: "SELECT_MONTH",
month,
tzid: tz.selectedTzid.tzid,
});
};
return (

@@ -38,4 +45,4 @@ <div className={theme.classBuilder("calendar-header")}>

aria-label={i18n.t("nav_previous_month")}
disabled={!monthState.prev ? true : false}
onClick={() => handleMonthNav(monthState.prev)}
disabled={!status.monthlyView.hasPrev}
onClick={handlePrevMonth}
>

@@ -53,3 +60,3 @@ <svg

<h2 className={theme.classBuilder("calendar-header--title")} id="calendar-title">
{i18n.f(monthState.current, "MMMM YYYY")}
{i18n.f(moment(status.monthlyView.month, "YYYY-MM"), "MMMM YYYY")}
</h2>

@@ -60,4 +67,4 @@ <button

aria-label={i18n.t("nav_next_month")}
disabled={!monthState.next ? true : false}
onClick={() => handleMonthNav(monthState.next)}
disabled={!status.monthlyView.hasNext}
onClick={handleNextMonth}
>

@@ -64,0 +71,0 @@ <svg

@@ -0,4 +1,5 @@

import moment from "moment-timezone";
import {
addSlotsToObject,
getFirstAvailableDay,
getSlotsByDay,

@@ -57,2 +58,4 @@ getAvailableDays,

month: state.monthlyView.month,
hasNext: state.monthlyView.hasNext,
hasPrev: state.monthlyView.hasPrev,
days: parseTimeSlots({

@@ -78,27 +81,8 @@ slots: state.slots,

const slotsObject = addSlotsToObject(state.slots, action.slots);
let daySlots = state.daySlots;
let columnView = state.columnView;
let focusedDay = state.focusedDay;
let selectedDay = state.selectedDay;
let availableDays = getAvailableDays(addSlotsToObject({}, action.slots), action.tzid);
const availableDays = getAvailableDays(addSlotsToObject({}, action.slots), action.tzid);
const availableDaysSet = new Set([...state.availableDays, ...availableDays]);
availableDays = [...availableDaysSet].sort();
if (!state.selectedDay) {
columnView = "slots";
focusedDay = availableDays[0];
selectedDay = availableDays[0];
daySlots = getSlotsByDay(slotsObject, selectedDay, action.tzid);
}
return {
...state,
daySlots,
columnView,
focusedDay,
selectedDay,
availableDays,
availableDays: [...availableDaysSet].sort(),
slots: slotsObject,

@@ -119,2 +103,4 @@ slotFetchCount: state.slotFetchCount + 1,

const daySlots = getSlotsByDay(state.slots, action.day, action.tzid);
const focusedSlot = daySlots[0];
return {

@@ -124,3 +110,3 @@ ...state,

focusedDay: action.day,
focusedSlot: daySlots[0].start,
focusedSlot: focusedSlot?.start,
columnView: "slots",

@@ -132,2 +118,15 @@ daySlots,

case "SELECT_MONTH": {
const actionMonthObject = moment(action.month, "YYYY-MM");
if (
!actionMonthObject.isBetween(
state.startDateObject,
state.endDateObject,
"month",
"[]"
)
) {
return state;
}
const months = state.months.map(month => ({

@@ -138,6 +137,6 @@ ...month,

let focusedDay = action.focusedDay ?? false;
const monthlyView = {
month: action.month,
hasNext: actionMonthObject.isBefore(state.endDateObject, "month"),
hasPrev: actionMonthObject.isAfter(state.startDateObject, "month"),
days: parseTimeSlots({

@@ -151,2 +150,4 @@ tzid: action.tzid,

let focusedDay = action.focusedDay ?? false;
return {

@@ -180,2 +181,4 @@ ...state,

month: state.monthlyView.month,
hasNext: state.monthlyView.hasNext,
hasPrev: state.monthlyView.hasPrev,
days: parseTimeSlots({

@@ -182,0 +185,0 @@ slots: state.slots,

@@ -1,12 +0,6 @@

import React, { useState } from "react";
import React, { useMemo } from "react";
import moment from "moment-timezone";
import {
getMonthObjectsFromQuery,
parseQuery,
parseTzList,
getInitialSelectedTzid,
} from "./utils/slots";
import { getMonthObjectsFromQuery, parseTzList, getInitialSelectedTzid } from "./utils/slots";
import { parseTimeSlots } from "./utils/calendar";
import { queryForDateTimePicker } from "../../helpers/mocks";

@@ -24,9 +18,21 @@ import Wrapper from "./Wrapper";

const DateTimePicker = ({ options }) => {
const [statusOptions] = useState(() => {
const query = !options.demo ? parseQuery(options.query) : queryForDateTimePicker;
const months = getMonthObjectsFromQuery(query, options.tzid);
const currentMonth = months.length ? months[0].month : moment().format("YYYY-MM");
const statusOptions = useMemo(() => {
const selectedDateObject =
options.config.selectedDate && moment(options.config.selectedDate, "YYYY-MM-DD");
const months = getMonthObjectsFromQuery(
options.query,
options.tzid,
selectedDateObject?.format("YYYY-MM")
);
const endDateObject = moment(options.config.endDate, "YYYY-MM-DD");
const startDateObject = moment(options.config.startDate, "YYYY-MM-DD");
const currentMonthObject = selectedDateObject ?? startDateObject;
const currentMonth = currentMonthObject.format("YYYY-MM");
const monthlyView = {
month: currentMonth,
hasNext: currentMonthObject.isBefore(endDateObject, "month"),
hasPrev: currentMonthObject.isAfter(startDateObject, "month"),
days: parseTimeSlots({

@@ -53,3 +59,3 @@ slots: {},

mode: options.config.mode, // confirm (default) | no_confirm
query,
query: options.query,
months,

@@ -59,2 +65,6 @@ monthlyView,

startDay: options.config.startDay,
focusedDay: options.config.selectedDay,
selectedDay: options.config.selectedDate,
startDateObject,
endDateObject,
focusedSlot: false,

@@ -68,3 +78,3 @@ availableDays: [],

};
});
}, []);

@@ -71,0 +81,0 @@ const themeOptions = {

@@ -24,3 +24,3 @@ import moment from "moment-timezone";

export const getMonthsFromQuery = (periods, tzid) => {
export const getMonthsFromQuery = (periods = [], tzid) => {
const months = periods

@@ -46,5 +46,13 @@ .map(period => getMonthsCoveredByPeriod(period, tzid))

}
const monthStrings = getMonthsFromQuery(query.query_periods, tzid);
const currentMonth = current ? current : monthStrings[0];
const monthObjects = monthStrings.map(month => {
const startMonth = moment(monthStrings[0], "YYYY-MM");
const endMonth = moment(monthStrings[monthStrings.length - 1], "YYYY-MM");
const currentMonth =
current && moment(current, "YYYY-MM").isBetween(startMonth, endMonth)
? current
: monthStrings[0];
return monthStrings.map(month => {
const croppedQueryPeriods = cropPeriodsByMonth(query.query_periods, month, tzid);

@@ -61,3 +69,2 @@ return {

});
return monthObjects;
};

@@ -64,0 +71,0 @@

@@ -59,16 +59,6 @@ import React, { useEffect, useRef } from "react";

useEffect(() => {
// Check for no-slots when all months have been fetched
const fetchCount = status.slotFetchCount;
const monthsCount = status.months.length;
const slotsCount = Object.keys(status.slots).length;
if (fetchCount === monthsCount && slotsCount < 1) {
dispatchStatus({ type: "NO_SLOTS_FOUND" });
if (!status.slotInjectionPoint) {
return;
}
// Set grid display if there are available slots within the current month
if (slotsCount < 1) {
return;
}
const weeksInMonth = status.monthlyView.days;

@@ -79,7 +69,5 @@ const firstDay = moment(weeksInMonth[0][0].date, "YYYY-MM-DD");

const injectionPoint = status.slotInjectionPoint
? moment(status.slotInjectionPoint, "YYYY-MM-DD")
: undefined;
const injectionPoint = moment(status.slotInjectionPoint, "YYYY-MM-DD");
if (injectionPoint && !injectionPoint.isBetween(firstDay, lastDay)) {
if (!injectionPoint.isBetween(firstDay, lastDay)) {
return;

@@ -92,5 +80,43 @@ }

});
}, [status.slotFetchCount, status.slotInjectionPoint]);
}, [status.slotInjectionPoint]);
useEffect(() => {
const fetchCount = status.slotFetchCount;
const monthsCount = status.months.length;
const finishedCallingAllSlots = fetchCount === monthsCount;
const hasAvailableDays = status.availableDays.length;
// No slots available after all queries have been made
if (finishedCallingAllSlots && !hasAvailableDays) {
dispatchStatus({ type: "NO_SLOTS_FOUND" });
return;
}
// Set selectedDay to first available day
if (!status.selectedDay && hasAvailableDays) {
dispatchStatus({
type: "SELECT_DAY",
day: status.availableDays[0],
tzid: tz.selectedTzid.tzid,
});
return;
}
if (!status.selectedDay && !hasAvailableDays) {
return;
}
// For allowing only this to be called once
// Since we know the first month that is being fetched will be for the initial selected day
if (status.selectedDay && fetchCount === 1) {
dispatchStatus({
type: "SELECT_DAY",
day: status.selectedDay,
tzid: tz.selectedTzid.tzid,
});
return;
}
}, [status.slotFetchCount, status.availableDays]);
useEffect(() => {
if (status.selectedDay) {

@@ -97,0 +123,0 @@ const selectedDayParts = status.selectedDay.split("-");

@@ -0,1 +1,3 @@

import moment from "moment-timezone";
import {

@@ -11,3 +13,9 @@ parseConnectionDomains,

import { logConstructor } from "./logging";
import { queryForDateTimePicker } from "./mocks";
import {
getMonthsFromQuery,
parseQuery as parseWithOverlappingSlots,
} from "../components/DateTimePicker/utils/slots";
export const parseDateTimePickerOptions = (options = {}) => {

@@ -70,6 +78,10 @@ const config = typeof options.config === "undefined" ? {} : options.config;

let query;
if (isBookableEventsQuery) {
if (options.demo) {
query = queryForDateTimePicker;
} else if (isBookableEventsQuery) {
query = options.availability_query;
query = parseWithOverlappingSlots(query);
} else {
query = parseQuery({ options, elementSlug: "date-time-picker", log });
query = parseWithOverlappingSlots(query);
}

@@ -98,2 +110,40 @@

let selectedDate = config.selected_date;
if (typeof selectedDate !== "undefined") {
const validDate = moment(selectedDate, "YYYY-MM-DD", true).isValid();
if (!validDate) {
log.warn(
`The provided date ${selectedDate} is not valid. Please ensure it's formatted like "YYYY-MM-DD". Picking the first available date as starting date.`,
{
docsSlug: "#config.start_date",
}
);
selectedDate = undefined;
}
}
const months = getMonthsFromQuery(query?.query_periods, tzid.tzid);
const selectedDateMoment = selectedDate && moment(selectedDate, "YYYY-MM-DD");
let startDateMoment = months.length
? moment(months[0], "YYYY-MM").startOf("month")
: moment().startOf("month");
if (selectedDateMoment?.isBefore(startDate)) {
startDateMoment = selectedDateMoment;
}
let endDateMoment = months.length
? moment(months[months.length - 1], "YYYY-MM").endOf("month")
: moment().endOf("month");
if (selectedDateMoment?.isAfter(endDateMoment)) {
endDateMoment = selectedDateMoment;
}
const startDate = startDateMoment.format("YYYY-MM-DD");
const endDate = endDateMoment.format("YYYY-MM-DD");
delete options.availability_query;

@@ -113,3 +163,12 @@ delete options.element_token;

query,
config: { ...config, mode, logs, startDay, tzList },
config: {
...config,
mode,
logs,
startDay,
selectedDate,
startDate,
endDate,
tzList,
},
translations,

@@ -116,0 +175,0 @@ log,

@@ -13,9 +13,15 @@ import { statusReducer } from "../../../src/js/components/DateTimePicker/contexts/status-reducer";

import { getMonthObjectsFromQuery } from "../../../src/js/components/DateTimePicker/utils/slots";
import {
getAvailableDays,
getMonthObjectsFromQuery,
} from "../../../src/js/components/DateTimePicker/utils/slots";
import { parseTimeSlots } from "../../../src/js/components/DateTimePicker/utils/calendar";
import moment from "moment";
const months = getMonthObjectsFromQuery(testQuery, "Europe/London");
const testMonthlySlots = months.map(month => ({
const testMonthlySlots = months.map((month, i) => ({
month: month.month,
hasNext: i < months.length - 1 ? true : false,
hasPrev: i > 0 ? true : false,
days: parseTimeSlots({

@@ -44,2 +50,4 @@ slots: testSlotsObject,

},
startDateObject: moment("2021-09-01", "YYYY-MM-DD"),
endDateObject: moment("2021-10-31", "YYYY-MM-DD"),
selectedDay: "2021-09-29",

@@ -49,3 +57,3 @@ startDay: "sunday",

focusedSlot: "2021-09-29T08:00:00Z",
availableDays: [],
availableDays: getAvailableDays(testSlotsObject, "Europe/London"),
slots: testSlotsObject,

@@ -173,4 +181,2 @@ slotFetchCount: 1,

...startingState,
selectedDay: false,
focusedDay: false,
slots: {},

@@ -188,4 +194,2 @@ availableDays: [],

delete oldState.selectedDay;
delete oldState.focusedDay;
delete oldState.slots;

@@ -197,4 +201,2 @@ delete oldState.availableDays;

const {
selectedDay,
focusedDay,
slots,

@@ -208,4 +210,2 @@ availableDays,

// These values have been updated
expect(selectedDay).toBe("2021-09-29");
expect(focusedDay).toBe("2021-09-29");
expect(slots).toStrictEqual(testSlotsObject);

@@ -228,4 +228,2 @@ expect(availableDays).toStrictEqual([

...startingState,
selectedDay: false,
focusedDay: false,
slots: {},

@@ -243,4 +241,2 @@ availableDays: [],

delete oldState.selectedDay;
delete oldState.focusedDay;
delete oldState.slots;

@@ -250,7 +246,4 @@ delete oldState.availableDays;

delete oldState.slotInjectionPoint;
delete oldState.daySlots;
const {
selectedDay,
focusedDay,
slots,

@@ -260,3 +253,2 @@ availableDays,

slotInjectionPoint,
daySlots,
...newState

@@ -266,4 +258,2 @@ } = result;

// These values have been updated
expect(selectedDay).toBe("2021-09-29");
expect(focusedDay).toBe("2021-09-29");
expect(slots).toStrictEqual(testSingleSlotsObject);

@@ -273,3 +263,2 @@ expect(availableDays).toStrictEqual(["2021-09-29"]);

expect(slotInjectionPoint).toBe("2021-09-29");
expect(daySlots).toStrictEqual(testSingleSlotsArray);

@@ -293,4 +282,2 @@ // All other values are unchanged

delete oldState.selectedDay;
delete oldState.focusedDay;
delete oldState.slots;

@@ -302,4 +289,2 @@ delete oldState.slotFetchCount;

const {
selectedDay,
focusedDay,
slots,

@@ -312,4 +297,2 @@ slotFetchCount,

expect(selectedDay).toBe("2021-09-29");
expect(focusedDay).toBe("2021-09-29");
expect(slots).toStrictEqual(testSlotsObject);

@@ -402,117 +385,143 @@ expect(slotFetchCount).toBe(2);

describe("SELECT_MONTH", () => {
it("selects month", () => {
it("doesn't select month if month before start bound", () => {
const oldState = { ...startingState };
const month = "2021-10";
const month = "2021-08";
const result = statusReducer(oldState, {
type: "SELECT_MONTH",
month: month,
month,
tzid: "Europe/London",
});
const expectedResultForMonths = [
{
month: "2021-09",
current: false,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-29T08:00:00Z",
end: "2021-09-30T22:59:00Z",
},
],
required_duration: { minutes: 60 },
expect(result).toStrictEqual(oldState);
});
it("doesn't select month if month outside end bound", () => {
const oldState = { ...startingState };
const month = "2021-11";
const result = statusReducer(oldState, {
type: "SELECT_MONTH",
month,
tzid: "Europe/London",
});
expect(result).toStrictEqual(oldState);
});
describe("within start and end bound", () => {
it("selects month within start and end bound", () => {
const oldState = { ...startingState };
const month = "2021-10";
const result = statusReducer(oldState, {
type: "SELECT_MONTH",
month: month,
tzid: "Europe/London",
});
const expectedResultForMonths = [
{
month: "2021-09",
current: false,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-29T08:00:00Z",
end: "2021-09-30T22:59:00Z",
},
],
required_duration: { minutes: 60 },
},
},
},
{
month: "2021-10",
current: true,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-30T23:00:00Z",
end: "2021-10-04T18:00:00Z",
},
],
required_duration: { minutes: 60 },
{
month: "2021-10",
current: true,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-30T23:00:00Z",
end: "2021-10-04T18:00:00Z",
},
],
required_duration: { minutes: 60 },
},
},
},
];
];
delete oldState.months;
delete oldState.focusedDay;
delete oldState.monthlyView;
delete oldState.months;
delete oldState.focusedDay;
delete oldState.monthlyView;
const { focusedDay, months, monthlyView, ...newState } = result;
const { focusedDay, months, monthlyView, ...newState } = result;
// These values have been updated
expect(focusedDay).toBe(false);
expect(monthlyView).toStrictEqual(testMonthlySlots[1]);
expect(months).toStrictEqual(expectedResultForMonths);
// These values have been updated
expect(focusedDay).toBe(false);
expect(monthlyView).toStrictEqual(testMonthlySlots[1]);
expect(months).toStrictEqual(expectedResultForMonths);
// All other values are unchanged
expect(newState).toStrictEqual(oldState);
});
// All other values are unchanged
expect(newState).toStrictEqual(oldState);
});
it("selects month with focusedDay", () => {
const oldState = { ...startingState };
const month = "2021-10";
const date = "2021-10-09";
it("selects month with focusedDay", () => {
const oldState = { ...startingState };
const month = "2021-10";
const date = "2021-10-09";
const result = statusReducer(oldState, {
type: "SELECT_MONTH",
month: month,
focusedDay: date,
tzid: "Europe/London",
});
const result = statusReducer(oldState, {
type: "SELECT_MONTH",
month: month,
focusedDay: date,
tzid: "Europe/London",
});
const expectedResultForMonths = [
{
month: "2021-09",
current: false,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-29T08:00:00Z",
end: "2021-09-30T22:59:00Z",
},
],
required_duration: { minutes: 60 },
const expectedResultForMonths = [
{
month: "2021-09",
current: false,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-29T08:00:00Z",
end: "2021-09-30T22:59:00Z",
},
],
required_duration: { minutes: 60 },
},
},
},
{
month: "2021-10",
current: true,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-30T23:00:00Z",
end: "2021-10-04T18:00:00Z",
},
],
required_duration: { minutes: 60 },
{
month: "2021-10",
current: true,
query: {
max_results: 512,
participants: [{ sub: "acc_5f35432b3f07d06753082354" }],
query_periods: [
{
start: "2021-09-30T23:00:00Z",
end: "2021-10-04T18:00:00Z",
},
],
required_duration: { minutes: 60 },
},
},
},
];
];
delete oldState.months;
delete oldState.focusedDay;
delete oldState.monthlyView;
delete oldState.months;
delete oldState.focusedDay;
delete oldState.monthlyView;
const { focusedDay, months, monthlyView, ...newState } = result;
const { focusedDay, months, monthlyView, ...newState } = result;
// These values have been updated
expect(date).toBe(focusedDay);
expect(monthlyView).toStrictEqual(testMonthlySlots[1]);
expect(months).toStrictEqual(expectedResultForMonths);
// These values have been updated
expect(focusedDay).toBe(date);
expect(monthlyView).toStrictEqual(testMonthlySlots[1]);
expect(months).toStrictEqual(expectedResultForMonths);
// All other values are unchanged
expect(newState).toStrictEqual(oldState);
// All other values are unchanged
expect(newState).toStrictEqual(oldState);
});
});

@@ -519,0 +528,0 @@ });

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc