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
175
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.25.1 to 1.25.2

build/CronofyElements.v1.25.2.js

2

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

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

@@ -17,3 +17,3 @@ import React, { useContext } from "react";

if (drag.mouseDown) {
toggleMultiple(drag.dragged, drag.toggleState);
handleRuleChange(drag.dragged, drag.toggleState);
setDrag({

@@ -20,0 +20,0 @@ mouseDown: false,

@@ -1,2 +0,2 @@

import React, { useContext } from "react";
import React, { memo, useContext } from "react";
import { css, jsx } from "@emotion/core";

@@ -8,3 +8,3 @@

const DayColumnDisplay = ({ day }) => {
let DayColumnDisplay = ({ day }) => {
const [theme, setTheme] = useContext(ThemeContext);

@@ -32,2 +32,4 @@ return (

DayColumnDisplay = memo(DayColumnDisplay);
export default DayColumnDisplay;

@@ -1,2 +0,2 @@

import React, { useContext } from "react";
import React, { memo, useContext } from "react";
import { css, jsx } from "@emotion/core";

@@ -6,3 +6,3 @@

const DayColumnWrapper = ({ children, layer = 1 }) => {
let DayColumnWrapper = ({ children, layer = 1 }) => {
const [theme, setTheme] = useContext(ThemeContext);

@@ -28,2 +28,4 @@ return (

DayColumnWrapper = memo(DayColumnWrapper);
export default DayColumnWrapper;

@@ -1,2 +0,2 @@

import React, { useContext } from "react";
import React, { memo, useContext } from "react";
import { css, jsx } from "@emotion/core";

@@ -9,3 +9,5 @@

const Overlay = ({ day, columnCount, toggleMultiple }) => {
import { overlayComparator } from "../../helpers/comparators.AvailabilityViewer";
let Overlay = ({ day, columnCount, toggleMultiple }) => {
const [status, setStatus] = useContext(StatusContext);

@@ -57,2 +59,4 @@ const [theme, setTheme] = useContext(ThemeContext);

Overlay = memo(Overlay, overlayComparator);
export default Overlay;

@@ -21,3 +21,3 @@ import React, { useState, useContext, useEffect } from "react";

// Default slot info
const [slotData, setSlotData] = useState({
const [slotData, setSlotData] = useState(() => ({
position: { y: 0, x: columnCount },

@@ -30,15 +30,14 @@ topSlot: topSlot,

}
});
}));
const defaultTimeDisplayStart = i18n
.f(moment(slot.start, "YYYY-MM-DDTHH:mm:00Z").tz(status.tzid), "LT")
.replace(" ", "");
const defaultTimeDisplayEnd = i18n
.f(moment(slot.end, "YYYY-MM-DDTHH:mm:00Z").tz(status.tzid), "LT")
.replace(" ", "");
// Default time display
const [timeDisplay, setTimeDisplay] = useState(
`${defaultTimeDisplayStart} - ${defaultTimeDisplayEnd}`
);
const [timeDisplay, setTimeDisplay] = useState(() => {
const defaultTimeDisplayStart = i18n
.f(moment(slot.start, "YYYY-MM-DDTHH:mm:00Z").tz(status.tzid), "LT")
.replace(" ", "");
const defaultTimeDisplayEnd = i18n
.f(moment(slot.end, "YYYY-MM-DDTHH:mm:00Z").tz(status.tzid), "LT")
.replace(" ", "");
return `${defaultTimeDisplayStart} - ${defaultTimeDisplayEnd}`;
});

@@ -222,2 +221,3 @@ const updateSlotData = () => {

};
export default Slot;

@@ -1,2 +0,2 @@

import React, { useContext } from "react";
import React, { memo, useContext } from "react";
import { css, jsx } from "@emotion/core";

@@ -7,3 +7,3 @@

const TimeLines = () => {
let TimeLines = () => {
const labels = useContext(LabelsContext);

@@ -73,2 +73,4 @@ const [theme, setTheme] = useContext(ThemeContext);

TimeLines = memo(TimeLines);
export default TimeLines;

@@ -69,22 +69,23 @@ import React, { useContext, useState, useEffect } from "react";

const toggleMultiple = (IDs, toggleStatus) => {
const updatedSlotData = slotData.map(day => ({
...day,
slots: day.slots.map(slot =>
IDs.includes(slot.start)
? { ...slot, selected: toggleStatus }
: slot
)
}));
setSlotData(oldSlotData => {
const updatedSlotData = oldSlotData.map(day => ({
...day,
slots: day.slots.map(slot =>
IDs.includes(slot.start)
? { ...slot, selected: toggleStatus }
: slot
)
}));
const currentlySelectedSlots = getSelectedSlots(updatedSlotData);
const queryPeriods = buildPeriodsFromSlots(currentlySelectedSlots);
const callbackContent = {
notification: {
type: "query_periods_edited",
query_periods: queryPeriods
}
};
status.notificationCallback(callbackContent);
setSlotData(updatedSlotData);
const currentlySelectedSlots = getSelectedSlots(updatedSlotData);
const queryPeriods = buildPeriodsFromSlots(currentlySelectedSlots);
const callbackContent = {
notification: {
type: "query_periods_edited",
query_periods: queryPeriods
}
};
status.notificationCallback(callbackContent);
return updatedSlotData;
});
};

@@ -91,0 +92,0 @@

import {
parseConnectionDomains,
parseTarget,
parseTimzone,
parseTimezone,
parseToken,

@@ -72,3 +72,3 @@ parseTranslations

const tzid = parseTimzone(options.tzid, "availability-rules", log);
const tzid = parseTimezone(options.tzid, "availability-rules", log);

@@ -75,0 +75,0 @@ const domains = parseConnectionDomains(

import moment from "moment-timezone";
import {
adjustInterval,
parseConnectionDomains,
parseGridTime,
parseInterval,
parseQuery,
parseTarget,
parseTimzone,
parseTimezone,
parseToken,

@@ -39,4 +41,27 @@ parseTranslations

const interval = parseInterval(config.interval);
const startTime = parseGridTime(config.start_time, "09:00");
if (startTime.message) {
log.warn(`config.start_time: ${startTime.message}`, {
docsSlug: "availability-viewer/#config.start_time"
});
}
const endTime = parseGridTime(config.end_time, "17:00", true);
if (endTime.message) {
log.warn(`config.end_time: ${endTime.message}`, {
docsSlug: "availability-viewer/#config.end_time"
});
}
if (startTime.time > endTime.time) {
log.error(
`\`config.start_time\` (${startTime.time}) must be earlier than \`config.end_time\` (${endTime.time}).`
);
return false;
}
const rawInterval = parseInterval(config.interval);
const interval = adjustInterval(rawInterval, startTime.offset, log);
if (typeof options.extras !== "undefined") {

@@ -53,3 +78,3 @@ log.warn(

const tzid = parseTimzone(options.tzid, "availability-viewer", log);
const tzid = parseTimezone(options.tzid, "availability-viewer", log);
options = { ...options, ...tzid };

@@ -147,2 +172,4 @@

...config,
start_time: startTime.time,
end_time: endTime.time,
interval,

@@ -149,0 +176,0 @@ startDay,

@@ -228,3 +228,3 @@ import merge from "deepmerge";

export const parseTimzone = (option, elementSlug = false, log) => {
export const parseTimezone = (option, elementSlug = false, log) => {
const docsHash = elementSlug ? `${elementSlug}/#param-tzid` : "";

@@ -246,1 +246,56 @@ const isValidTzid = moment.tz.zone(option);

};
export const parseGridTime = (time, fallback = "09:00", roundUp = false) => {
// If there's no time set, fallback silently.
if (typeof time === "undefined")
return { message: false, time: fallback, offset: 0 };
// If there is a time, is it in a valid format?
const validTime = moment(time, "HH:mm", true).isValid();
if (!validTime) {
return {
message: `using default value of ${fallback}`,
time: fallback,
offset: 0
};
}
const parts = time.split(":");
const rawMinutes = parseInt(parts[1], 10);
// If the time falls on an approved interval, it's valid!
if (rawMinutes % 15 === 0) {
return {
message: false,
time: time,
offset: rawMinutes
};
}
const roundedMinutes = roundUp
? (Math.ceil(rawMinutes / 15) * 15) % 60
: (Math.floor(rawMinutes / 15) * 15) % 60;
const paddedMinutes = roundedMinutes.toString().padStart(2, "0");
return {
message: `rounded from ${time} to ${parts[0]}:${paddedMinutes}`,
time: `${parts[0]}:${paddedMinutes}`,
offset: roundedMinutes
};
};
export const adjustInterval = (rawInterval, offset, log) => {
if (offset > 0 && rawInterval > offset) {
// Positive offsets will only ever be 15, 30 or 45.
const adjustedInterval = offset === 45 ? 15 : offset;
log.warn(
`config.interval of ${rawInterval} minutes has been shortened to ${adjustedInterval} minutes for optimal tessellation of results in the grid.`,
{
docsSlug: "availability-viewer/#config.interval"
}
);
return adjustedInterval;
}
return rawInterval;
};

@@ -5,3 +5,3 @@ import {

parseTarget,
parseTimzone,
parseTimezone,
parseToken,

@@ -47,3 +47,3 @@ parseTranslations

const tzid = parseTimzone(options.tzid, "slot-picker", log);
const tzid = parseTimezone(options.tzid, "slot-picker", log);

@@ -50,0 +50,0 @@ const domains = parseConnectionDomains(

@@ -98,6 +98,14 @@ const moment = require("moment-timezone");

let start = moment.utc(period.start, "YYYY-MM-DDTHH:mm:00Z");
const startIsHalfHour =
start.minute() === 30 &&
start.second() === 0 &&
start.millisecond() === 0;
const startIsQuarter =
start.minute() % 15 === 0 &&
start.second() === 0 &&
start.millisecond() === 0;
if (duration > 30) {
if (duration > 30 && !startIsHalfHour && !startIsQuarter) {
start = hour(start);
} else if (duration > 15) {
} else if (duration > 15 && !startIsQuarter) {
start = half(start);

@@ -104,0 +112,0 @@ } else {

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

import { parseSlotPickerOptions } from "../src/js/helpers/init.SlotPicker";
import { parseQuery } from "../src/js/helpers/init";
import { parseQuery, parseGridTime } from "../src/js/helpers/init";

@@ -651,2 +651,271 @@ // The parsers rely on console warning and errors to

});
it("correctly adds fallback config.start_time and config.end_time", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
target_id: "TARGET",
element_token: "TOKEN"
};
const result = parseAvailabilityViewerOptions(input);
expect(result.config.start_time).toEqual("09:00");
expect(result.config.end_time).toEqual("17:00");
expect(console.warn).toHaveBeenCalledTimes(0);
expect(console.error).toHaveBeenCalledTimes(0);
});
it("correctly fallbacks when config.start_time is invalid", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
config: {
start_time: "A string that is not a time",
end_time: "13:00"
},
target_id: "TARGET",
element_token: "TOKEN"
};
const result = parseAvailabilityViewerOptions(input);
expect(result.config.start_time).toEqual("09:00");
expect(result.config.end_time).toEqual("13:00");
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.start_time: using default value of 09:00"
);
expect(console.error).toHaveBeenCalledTimes(0);
});
it("correctly fallbacks when config.end_time is invalid", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
config: {
start_time: "08:00",
end_time: 1234
},
target_id: "TARGET",
element_token: "TOKEN"
};
const result = parseAvailabilityViewerOptions(input);
expect(result.config.start_time).toEqual("08:00");
expect(result.config.end_time).toEqual("17:00");
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.end_time: using default value of 17:00"
);
expect(console.error).toHaveBeenCalledTimes(0);
});
it("correctly rounds config.start_time to valid interval", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
config: {
start_time: "08:25"
},
target_id: "TARGET",
element_token: "TOKEN"
};
const result = parseAvailabilityViewerOptions(input);
expect(result.config.start_time).toEqual("08:15");
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.start_time: rounded from 08:25 to 08:15"
);
});
it("correctly rounds config.start_time to valid interval", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
target_id: "TARGET",
element_token: "TOKEN"
};
const config_1 = {
config: {
end_time: "17:25"
}
};
const result_1 = parseAvailabilityViewerOptions({
...input,
...config_1
});
expect(result_1.config.end_time).toEqual("17:30");
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.end_time: rounded from 17:25 to 17:30"
);
console.warn.mockClear();
const config_2 = {
config: {
start_time: "08:38"
}
};
const result_2 = parseAvailabilityViewerOptions({
...input,
...config_2
});
expect(result_2.config.start_time).toEqual("08:30");
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.start_time: rounded from 08:38 to 08:30"
);
});
it("adjusts config.interval to match config.start_time when needed", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
target_id: "TARGET",
element_token: "TOKEN"
};
const config_1 = {
config: {
start_time: "08:30",
interval: 60
}
};
const result_1 = parseAvailabilityViewerOptions({
...input,
...config_1
});
expect(result_1.config.interval).toEqual(30);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.interval of 60 minutes has been shortened to 30 minutes for optimal tessellation of results in the grid."
);
console.warn.mockClear();
const config_2 = {
config: {
start_time: "08:15",
interval: 60
}
};
const result_2 = parseAvailabilityViewerOptions({
...input,
...config_2
});
expect(result_2.config.interval).toEqual(15);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.interval of 60 minutes has been shortened to 15 minutes for optimal tessellation of results in the grid."
);
console.warn.mockClear();
const config_3 = {
config: {
start_time: "08:45",
interval: 60
}
};
const result_3 = parseAvailabilityViewerOptions({
...input,
...config_3
});
expect(result_3.config.interval).toEqual(15);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn.mock.calls[0][0]).toContain(
"config.interval of 60 minutes has been shortened to 15 minutes for optimal tessellation of results in the grid."
);
});
it("fails if start_time is after end_time", () => {
const input = {
data_center: "DATA_CENTER",
availability_query: {
query_periods: generic_query_periods,
required_duration: "TEST"
},
target_id: "TARGET",
element_token: "TOKEN",
config: {
start_time: "08:00",
end_time: "06:00",
interval: 60
}
};
const result = parseAvailabilityViewerOptions(input);
expect(result).toEqual(false);
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls[0][0]).toContain(
"must be earlier than"
);
});
it("correctly parses grid times", () => {
const simpleTime = parseGridTime("08:00");
expect(simpleTime.time).toBe("08:00");
expect(simpleTime.offset).toBe(0);
expect(simpleTime.message).toBe(false);
const offsetTime = parseGridTime("08:30");
expect(offsetTime.time).toBe("08:30");
expect(offsetTime.offset).toBe(30);
expect(offsetTime.message).toBe(false);
const invalidTime = parseGridTime("INVALID");
expect(invalidTime.time).toBe("09:00");
expect(invalidTime.offset).toBe(0);
expect(invalidTime.message).toContain("using default value");
const roundedDown = parseGridTime("08:42");
expect(roundedDown.time).toBe("08:30");
expect(roundedDown.offset).toBe(30);
expect(roundedDown.message).toContain("rounded");
const roundedUp = parseGridTime("08:42", "", true);
expect(roundedUp.time).toBe("08:45");
expect(roundedUp.offset).toBe(45);
expect(roundedUp.message).toContain("rounded");
const noLeadingZeroTime = parseGridTime("8:00");
expect(noLeadingZeroTime.time).toBe("09:00");
expect(noLeadingZeroTime.offset).toBe(0);
expect(noLeadingZeroTime.message).toContain("using default value");
const emptyTime = parseGridTime();
expect(emptyTime.time).toBe("09:00");
expect(emptyTime.offset).toBe(0);
expect(emptyTime.message).toBe(false);
const customFallbackTime = parseGridTime("INVALID", "06:00");
expect(customFallbackTime.time).toBe("06:00");
expect(customFallbackTime.offset).toBe(0);
expect(customFallbackTime.message).toContain("using default value");
});
});

@@ -653,0 +922,0 @@

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

Sorry, the diff of this file is not supported yet

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