diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3ba4d647..6d7f4f90 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -8,6 +8,7 @@ jobs:
docker:
- image: cimg/node:14.19.3
working_directory: ~/repo
+ resource_class: large
steps:
- checkout
- run:
@@ -34,7 +35,9 @@ jobs:
- run:
name: Test
command: |
- yarn test:unit
+ yarn test:unit:ci
+ - store_test_results:
+ path: ./coverage/clover.xml
- codecov/upload:
flags: unittest
file:
diff --git a/README.md b/README.md
index 578e3c02..25d52e36 100644
--- a/README.md
+++ b/README.md
@@ -42,8 +42,9 @@ A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provid
- [Plugin file](#in-v202-and-older--default-configuration-state-for-v203-and-newer)
5. [πΈοΈ Public API - REST](#%EF%B8%8F-public-rest-api-specification)
6. [πΈοΈ Public API - GraphQL](#%EF%B8%8F-public-graphql-specification)
-7. [π€ Contributing](#-contributing)
-8. [π¨βπ» Community support](#-community-support)
+7. [βοΈ Custom fields](#-custom-fields)
+8. [π€ Contributing](#-contributing)
+9. [π¨βπ» Community support](#-community-support)
## β¨ Features
@@ -828,6 +829,14 @@ _Available reason enums:_ `BAD_WORDS`, `OTHER`, `DISCRIMINATION` (want more? See
Live example of plugin usage can be found in the [VirtusLab Strapi Examples](https://github.com/VirtusLab/strapi-examples/tree/master/strapi-v4-plugin-comments) repository.
+## βοΈ Custom fields
+
+**THIS IS AN UNSTABLE FEATURE**
+
+For developers who upgrades their Strapi instance custom field from Comments plugin is available. Custom field can be picked from content types' edit page or added in definition file.
+
+Read more about this feature in [Strapi's docs](https://docs-next.strapi.io/user-docs/latest/plugins/introduction-to-plugins.html#custom-fields).
+
## π€ Contributing
diff --git a/admin/src/custom-fields/comments/components/icon.tsx b/admin/src/custom-fields/comments/components/icon.tsx
new file mode 100644
index 00000000..5840c47e
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/icon.tsx
@@ -0,0 +1,29 @@
+import React from "react";
+
+export const CustomFieldIcon = () => (
+
+
+
+
+
+
+);
diff --git a/admin/src/custom-fields/comments/components/index.ts b/admin/src/custom-fields/comments/components/index.ts
new file mode 100644
index 00000000..ebf016df
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/index.ts
@@ -0,0 +1,2 @@
+export * from "./icon";
+export * from "./input";
diff --git a/admin/src/custom-fields/comments/components/input/__tests__/utils.test.ts b/admin/src/custom-fields/comments/components/input/__tests__/utils.test.ts
new file mode 100644
index 00000000..0f9644d3
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/input/__tests__/utils.test.ts
@@ -0,0 +1,435 @@
+import { Dispatch, SetStateAction } from "react";
+import { CommentsFieldValue } from "../types";
+import {
+ assertCorrectState,
+ asString,
+ fromInput,
+ getApprovalStatusOptions,
+ getFilterByOptions,
+ getRenderTypeOptions,
+ getSortByDateOptions,
+ handlePopulateChange,
+ handleStateSliceChange,
+ toOutput,
+} from "../utils";
+
+jest.mock("axios", () => ({
+ create: () => ({
+ interceptors: {
+ request: { use: jest.fn() },
+ response: { use: jest.fn() },
+ },
+ }),
+}));
+
+jest.mock("@strapi/helper-plugin", () => ({
+ auth: { getToken: jest.fn() },
+}));
+
+const state: CommentsFieldValue = {
+ commentsNumber: 99,
+};
+const createSetter: (
+ initialState: typeof state
+) => Dispatch
> =
+ (initialState) => (action) => {
+ if (action instanceof Function) {
+ return action(initialState);
+ }
+
+ return action;
+ };
+
+describe("Custom fields", () => {
+ describe("Comments", () => {
+ describe("asString()", () => {
+ it("should return standard result", () => {
+ expect(asString()).toMatchInlineSnapshot(`""`);
+ });
+ });
+ describe("fromInput()", () => {
+ it("should validate input", () => {
+ expect(() => fromInput("")).toThrow();
+ expect(() => fromInput(undefined)).toThrow();
+ expect(() => fromInput(null)).toThrow();
+ });
+ it("should prepare input for consumption", () => {
+ const state = fromInput(
+ `{ "commentsNumber": 35, "filterBy": "DATE_CREATED", "filterByValue": "${new Date(
+ 2022,
+ 7,
+ 7
+ )}" }`
+ );
+
+ expect(state.filterByValue).toBeInstanceOf(Date);
+ });
+ });
+ describe("toOutput()", () => {
+ it("should serialize state", () => {
+ const state: CommentsFieldValue = {
+ commentsNumber: 1,
+ populate: [],
+ sortByDate: "ASC",
+ };
+
+ expect(toOutput(state)).toMatchInlineSnapshot(
+ `"{\\"commentsNumber\\":1,\\"populate\\":[],\\"sortByDate\\":\\"ASC\\"}"`
+ );
+ });
+ });
+ describe("assertCorrectState()", () => {
+ it("should validate commentsNumber", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ });
+ it("should validate renderType", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: 1 })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: [] })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: {} })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: "TREE" })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: "LIST" })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: "TEST" })
+ ).not.toThrow();
+ });
+ it("should validate sortByDate", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, sortByDate: 1 })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, sortByDate: [] })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, sortByDate: {} })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: "ASC" })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, renderType: "DESC" })
+ ).not.toThrow();
+ });
+ it("should validate filterBy", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: 1 })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: [] })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: {} })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: "DATE_CREATED" })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: "APPROVAL_STATUS" })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterBy: "TEST" })
+ ).not.toThrow();
+ });
+ it("should validate filterByValue", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterByValue: 1 })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterByValue: [] })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterByValue: {} })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, filterByValue: "any" })
+ ).not.toThrow();
+ });
+ it("should validate populate", () => {
+ expect(() => assertCorrectState({})).toThrow();
+ expect(() => assertCorrectState({ commentsNumber: 1 })).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: 1 })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: {} })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: "any" })
+ ).toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: [] })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: ["avatar"] })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({ commentsNumber: 1, populate: ["author"] })
+ ).not.toThrow();
+ expect(() =>
+ assertCorrectState({
+ commentsNumber: 1,
+ populate: ["author", "avatar"],
+ })
+ ).not.toThrow();
+ });
+ });
+ describe("handleStateSliceChange()", () => {
+ const setter = createSetter(state);
+
+ it("should handle state slice", () => {
+ expect(handleStateSliceChange("commentsNumber", setter)(1))
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 1,
+ }
+ `);
+ expect(handleStateSliceChange("filterBy", setter)("FOO"))
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "filterBy": "FOO",
+ }
+ `);
+ expect(handleStateSliceChange("filterByValue", setter)("VALUE"))
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "filterByValue": "VALUE",
+ }
+ `);
+ expect(handleStateSliceChange("renderType", setter)("TREE"))
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "renderType": "TREE",
+ }
+ `);
+ expect(handleStateSliceChange("sortByDate", setter)("ASC"))
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "sortByDate": "ASC",
+ }
+ `);
+ });
+ });
+ describe("handlePopulateChange", () => {
+ it("should handle populate change", () => {
+ expect(handlePopulateChange("author", createSetter(state))())
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "author",
+ ],
+ }
+ `);
+ expect(handlePopulateChange("avatar", createSetter(state))())
+ .toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "avatar",
+ ],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "author",
+ createSetter({
+ ...state,
+ populate: [],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "author",
+ ],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "author",
+ createSetter({
+ ...state,
+ populate: ["author"],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "author",
+ createSetter({
+ ...state,
+ populate: ["avatar"],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "avatar",
+ "author",
+ ],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "avatar",
+ createSetter({
+ ...state,
+ populate: [],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "avatar",
+ ],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "avatar",
+ createSetter({
+ ...state,
+ populate: ["author"],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [
+ "author",
+ "avatar",
+ ],
+ }
+ `);
+ expect(
+ handlePopulateChange(
+ "avatar",
+ createSetter({
+ ...state,
+ populate: ["avatar"],
+ })
+ )()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "commentsNumber": 99,
+ "populate": Array [],
+ }
+ `);
+ });
+ });
+ describe("getRenderTypeOptions()", () => {
+ it("should render options", () => {
+ expect(getRenderTypeOptions(({ id }) => `translated.${id}`))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "label": "translated.customField.comments.input.renderType.option.tree.label",
+ "value": "TREE",
+ },
+ Object {
+ "label": "translated.customField.comments.input.renderType.option.flat.label",
+ "value": "FLAT",
+ },
+ ]
+ `);
+ });
+ });
+ describe("getSortByDateOptions()", () => {
+ it("should render options", () => {
+ expect(getSortByDateOptions(({ id }) => `translated.${id}`))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "label": "",
+ "value": undefined,
+ },
+ Object {
+ "label": "translated.customField.comments.input.sortByDate.option.asc.label",
+ "value": "ASC",
+ },
+ Object {
+ "label": "translated.customField.comments.input.sortByDate.option.desc.label",
+ "value": "DESC",
+ },
+ ]
+ `);
+ });
+ });
+ describe("getFilterByOptions()", () => {
+ it("should render options", () => {
+ expect(getFilterByOptions(({ id }) => `translated.${id}`))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "label": "",
+ "value": undefined,
+ },
+ Object {
+ "label": "translated.customField.comments.input.filterBy.option.dateCreated.label",
+ "value": "DATE_CREATED",
+ },
+ Object {
+ "label": "translated.customField.comments.input.filterBy.option.approvalStatus.label",
+ "value": "APPROVAL_STATUS",
+ },
+ ]
+ `);
+ });
+ });
+ describe("getApprovalStatusOptions()", () => {
+ it("should render options", () => {
+ expect(getApprovalStatusOptions(({ id }) => `translated.${id}`))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "label": "",
+ "value": undefined,
+ },
+ Object {
+ "label": "translated.customField.comments.input.filterBy.option.approvalStatus.option.approved.label",
+ "value": "APPROVED",
+ },
+ Object {
+ "label": "translated.customField.comments.input.filterBy.option.approvalStatus.option.pending.label",
+ "value": "PENDING",
+ },
+ Object {
+ "label": "translated.customField.comments.input.filterBy.option.approvalStatus.option.rejected.label",
+ "value": "REJECTED",
+ },
+ ]
+ `);
+ });
+ });
+ });
+});
diff --git a/admin/src/custom-fields/comments/components/input/index.ts b/admin/src/custom-fields/comments/components/input/index.ts
new file mode 100644
index 00000000..0f15f9aa
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/input/index.ts
@@ -0,0 +1,3 @@
+import { CustomFieldInput } from "./input";
+
+export default CustomFieldInput;
diff --git a/admin/src/custom-fields/comments/components/input/input.tsx b/admin/src/custom-fields/comments/components/input/input.tsx
new file mode 100644
index 00000000..71f467b2
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/input/input.tsx
@@ -0,0 +1,278 @@
+import React, { useCallback, useEffect, useState } from "react";
+// @ts-ignore
+import { Stack } from "@strapi/design-system/Stack";
+// @ts-ignore
+import { Typography } from "@strapi/design-system/Typography";
+// @ts-ignore
+import { Flex } from "@strapi/design-system/Flex";
+// @ts-ignore
+import { Box } from "@strapi/design-system/Box";
+import {
+ Field,
+ FieldError,
+ FieldHint,
+ FieldLabel,
+ // @ts-ignore
+} from "@strapi/design-system/Field";
+// @ts-ignore
+import { Option, Select } from "@strapi/design-system/Select";
+// @ts-ignore
+import { NumberInput } from "@strapi/design-system/NumberInput";
+// @ts-ignore
+import { Checkbox } from "@strapi/design-system/Checkbox";
+// @ts-ignore
+import { DatePicker } from "@strapi/design-system/DatePicker";
+import { CustomFieldInputProps } from "strapi-typed";
+// @ts-ignore
+import { Grid, GridItem } from "@strapi/design-system/Grid";
+import { CommentsFieldValue } from "./types";
+import {
+ asString,
+ fromInput,
+ getApprovalStatusOptions,
+ getFilterByOptions,
+ getRenderTypeOptions,
+ getSortByDateOptions,
+ handleStateSliceChange,
+ handlePopulateChange,
+ toOutput,
+} from "./utils";
+import { getMessage } from "../../../../utils";
+import { useIntl } from "react-intl";
+
+const DEFAULTS: CommentsFieldValue = {
+ commentsNumber: 30,
+ populate: [],
+ renderType: "FLAT",
+};
+
+export const CustomFieldInput: React.FC = ({
+ attribute,
+ description,
+ disabled,
+ error,
+ intlLabel,
+ labelAction,
+ name,
+ onChange,
+ required,
+ value,
+}) => {
+ const { formatMessage } = useIntl();
+ const [currentState, setCurrentState] = useState(
+ value ? fromInput(value) : DEFAULTS
+ );
+
+ const onCommentsNumberChange = useCallback(
+ handleStateSliceChange("commentsNumber", setCurrentState),
+ [setCurrentState]
+ );
+
+ const onRenderTypeChange = useCallback(
+ handleStateSliceChange("renderType", setCurrentState),
+ [setCurrentState]
+ );
+
+ const onSortByDateChange = useCallback(
+ handleStateSliceChange("sortByDate", setCurrentState),
+ [setCurrentState]
+ );
+
+ const onFilterByChange = useCallback(
+ (filterBy: CommentsFieldValue["filterBy"]) => {
+ setCurrentState((current) => ({
+ ...current,
+ filterBy,
+ filterByValue: undefined,
+ }));
+ },
+ [setCurrentState]
+ );
+
+ const onFilterByValueChange = useCallback(
+ handleStateSliceChange("filterByValue", setCurrentState),
+ [setCurrentState]
+ );
+
+ const onPopulateAuthorChange = useCallback(
+ handlePopulateChange("author", setCurrentState),
+ [setCurrentState]
+ );
+
+ const onPopulateAvatarChange = useCallback(
+ handlePopulateChange("avatar", setCurrentState),
+ [setCurrentState]
+ );
+
+ useEffect(() => {
+ const nextValue = toOutput(currentState);
+ const initialValue = value ? toOutput(fromInput(value)) : "";
+
+ if (initialValue !== nextValue && onChange) {
+ onChange({
+ target: {
+ name,
+ value: nextValue,
+ type: attribute.type,
+ },
+ });
+ }
+ }, [currentState, value]);
+
+ return (
+
+
+
+
+ {formatMessage(intlLabel)}
+
+ {labelAction && {labelAction} }
+
+
+
+
+
+
+
+
+ {getRenderTypeOptions(getMessage).map(({ value, label }) => (
+
+ {label}
+
+ ))}
+
+
+
+
+ {getSortByDateOptions(getMessage).map(({ value, label }) => (
+
+ {label}
+
+ ))}
+
+
+
+
+
+
+ {getFilterByOptions(getMessage).map(({ value, label }) => (
+
+ {label}
+
+ ))}
+
+
+ {currentState.filterBy === "APPROVAL_STATUS" ? (
+
+ {getApprovalStatusOptions(getMessage).map(
+ ({ value, label }) => (
+
+ {label}
+
+ )
+ )}
+
+ ) : null}
+ {currentState.filterBy === "DATE_CREATED" ? (
+
+ ) : null}
+
+
+
+
+ {getMessage(
+ "customField.comments.input.populate.label",
+ "Populate"
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/admin/src/custom-fields/comments/components/input/types.ts b/admin/src/custom-fields/comments/components/input/types.ts
new file mode 100644
index 00000000..579f22d8
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/input/types.ts
@@ -0,0 +1,10 @@
+export type PopulateField = "avatar" | "author";
+
+export type CommentsFieldValue = {
+ commentsNumber: number;
+ renderType?: "FLAT" | "TREE";
+ sortByDate?: "ASC" | "DESC";
+ filterBy?: "DATE_CREATED" | "APPROVAL_STATUS";
+ filterByValue?: string | Date;
+ populate?: Array;
+};
diff --git a/admin/src/custom-fields/comments/components/input/utils.ts b/admin/src/custom-fields/comments/components/input/utils.ts
new file mode 100644
index 00000000..0a8203e8
--- /dev/null
+++ b/admin/src/custom-fields/comments/components/input/utils.ts
@@ -0,0 +1,169 @@
+import { SetStateAction, Dispatch } from "react";
+import { uniq } from "lodash";
+import {
+ getMessage,
+ APPROVAL_STATUS,
+ ValidationError,
+ assertString,
+} from "../../../../utils";
+import { CommentsFieldValue, PopulateField } from "./types";
+
+export const asString = () => "";
+
+export const fromInput = (value: unknown) => {
+ assertString(value);
+
+ const state = JSON.parse(value);
+
+ assertCorrectState(state);
+
+ if (state.filterBy === "DATE_CREATED" && state.filterByValue) {
+ state.filterByValue = new Date(state.filterByValue);
+ }
+
+ return state;
+};
+
+export const toOutput = (state: CommentsFieldValue) => JSON.stringify(state);
+
+export function assertCorrectState(
+ state: any
+): asserts state is CommentsFieldValue {
+ if (typeof state.commentsNumber !== "number") {
+ throw new ValidationError("Comments number is not a number");
+ }
+
+ if (state.populate && !Array.isArray(state.populate)) {
+ throw new ValidationError("Comments populate is not an array");
+ }
+
+ stringFields.forEach((field) => {
+ if (state[field] && typeof state[field] !== "string") {
+ assertString(state[field]);
+ }
+ });
+}
+
+export const handleStateSliceChange =
+ (
+ key: keyof CommentsFieldValue,
+ setState: Dispatch>
+ ) =>
+ (value: CommentsFieldValue[typeof key]) => {
+ return setState((current) => ({
+ ...current,
+ [key]: value,
+ }));
+ };
+
+export const handlePopulateChange =
+ (
+ key: PopulateField,
+ setState: Dispatch>
+ ) =>
+ () => {
+ return setState((current) => {
+ const populate = current.populate || [];
+
+ return {
+ ...current,
+ populate: populate.includes(key)
+ ? populate.filter((field) => field !== key)
+ : uniq(populate.concat(key)),
+ };
+ });
+ };
+
+export const getRenderTypeOptions = (translate: typeof getMessage) => [
+ {
+ value: "TREE",
+ label: translate({
+ id: "customField.comments.input.renderType.option.tree.label",
+ defaultMessage: "Tree",
+ }),
+ },
+ {
+ value: "FLAT",
+ label: translate({
+ id: "customField.comments.input.renderType.option.flat.label",
+ defaultMessage: "Flat list",
+ }),
+ },
+];
+
+export const getSortByDateOptions = (translate: typeof getMessage) => [
+ {
+ value: undefined,
+ label: "",
+ },
+ {
+ value: "ASC",
+ label: translate({
+ id: "customField.comments.input.sortByDate.option.asc.label",
+ defaultMessage: "Ascending",
+ }),
+ },
+ {
+ value: "DESC",
+ label: translate({
+ id: "customField.comments.input.sortByDate.option.desc.label",
+ defaultMessage: "Descending",
+ }),
+ },
+];
+
+export const getFilterByOptions = (translate: typeof getMessage) => [
+ {
+ value: undefined,
+ label: "",
+ },
+ {
+ value: "DATE_CREATED",
+ label: translate({
+ id: "customField.comments.input.filterBy.option.dateCreated.label",
+ defaultMessage: "Creation date",
+ }),
+ },
+ {
+ value: "APPROVAL_STATUS",
+ label: translate({
+ id: "customField.comments.input.filterBy.option.approvalStatus.label",
+ defaultMessage: "Approval Status",
+ }),
+ },
+];
+
+export const getApprovalStatusOptions = (translate: typeof getMessage) => [
+ {
+ value: undefined,
+ label: "",
+ },
+ {
+ value: APPROVAL_STATUS.APPROVED,
+ label: translate({
+ id: "customField.comments.input.filterBy.option.approvalStatus.option.approved.label",
+ defaultMessage: "Approved",
+ }),
+ },
+ {
+ value: APPROVAL_STATUS.PENDING,
+ label: translate({
+ id: "customField.comments.input.filterBy.option.approvalStatus.option.pending.label",
+ defaultMessage: "Pending",
+ }),
+ },
+ {
+ value: APPROVAL_STATUS.REJECTED,
+ label: translate({
+ id: "customField.comments.input.filterBy.option.approvalStatus.option.rejected.label",
+ defaultMessage: "Rejected",
+ }),
+ },
+];
+
+const stringFields = [
+ "renderType",
+ "sortByDate",
+ "filterBy",
+ "filterByValue",
+] as const;
diff --git a/admin/src/custom-fields/comments/index.ts b/admin/src/custom-fields/comments/index.ts
new file mode 100644
index 00000000..1d3a2a7d
--- /dev/null
+++ b/admin/src/custom-fields/comments/index.ts
@@ -0,0 +1,28 @@
+import { StrapiAdminCustomFieldRegisterInput } from "strapi-typed";
+import { pluginId } from "../../pluginId";
+import { CustomFieldIcon } from "./components";
+
+export const commentsCustomField: StrapiAdminCustomFieldRegisterInput = {
+ name: "comments",
+ pluginId,
+ type: "json",
+ icon: CustomFieldIcon,
+ intlLabel: {
+ defaultMessage: "Comments",
+ description: "",
+ id: `${pluginId}.customField.comments.label`,
+ },
+ intlDescription: {
+ defaultMessage: "Specify comments query params",
+ description: "",
+ id: `${pluginId}.customField.comments.description`,
+ },
+ components: {
+ Input: async () => import("./components/input"),
+ },
+ options: {
+ base: [],
+ advanced: [],
+ validator: () => ({}),
+ },
+};
diff --git a/admin/src/custom-fields/index.ts b/admin/src/custom-fields/index.ts
new file mode 100644
index 00000000..c6e2cfd8
--- /dev/null
+++ b/admin/src/custom-fields/index.ts
@@ -0,0 +1,12 @@
+import { StrapiAdminInstance } from "strapi-typed";
+import { commentsCustomField } from "./comments";
+
+export const registerCustomFields = (app: StrapiAdminInstance) => {
+ if (!canRegister(app)) {
+ return;
+ }
+
+ app.customFields.register(commentsCustomField);
+};
+
+const canRegister = (app: StrapiAdminInstance) => !!app.customFields;
diff --git a/admin/src/index.ts b/admin/src/index.ts
index 03d9eafd..30e5761e 100644
--- a/admin/src/index.ts
+++ b/admin/src/index.ts
@@ -1,5 +1,6 @@
// @ts-ignore
import { prefixPluginTranslations } from "@strapi/helper-plugin";
+import { StrapiAdminInstance } from "strapi-typed";
import * as pluginPkg from "../../package.json";
import { pluginId } from "./pluginId";
import Initializer from "./components/Initializer";
@@ -7,11 +8,12 @@ import PluginIcon from "./components/PluginIcon";
import pluginPermissions from "./permissions";
import reducers from "./reducers";
import { ToBeFixed } from "../../types";
+import { registerCustomFields } from "./custom-fields";
const { name, displayName } = pluginPkg.strapi;
export default {
- register(app: ToBeFixed) {
+ register(app: StrapiAdminInstance) {
app.addMenuLink({
to: `/plugins/${pluginId}`,
badgeContent: 1,
@@ -65,6 +67,8 @@ export default {
isReady: false,
name,
});
+
+ registerCustomFields(app);
},
// bootstrap(app: ToBeFixed) {
diff --git a/admin/src/translations/en.json b/admin/src/translations/en.json
index faf6b5c9..eb65d9cf 100644
--- a/admin/src/translations/en.json
+++ b/admin/src/translations/en.json
@@ -166,5 +166,25 @@
"compontents.author.unknown": "Author removed",
"components.reason.unknown": "Reason not provided",
"components.content.unknown": "Content not provided",
- "components.notAccessPage.back": "Back to homepage"
+ "components.notAccessPage.back": "Back to homepage",
+ "customField.comments.label": "Comments",
+ "customField.comments.description": "Specify comments query params",
+ "customField.comments.input.commentsNumber.label": "Number of comments",
+ "customField.comments.input.renderType.label": "Render comments as",
+ "customField.comments.input.renderType.option.tree.label": "Tree",
+ "customField.comments.input.renderType.option.flat.label": "Flat list",
+ "customField.comments.input.sortByDate.label": "Sort by creation date",
+ "customField.comments.input.sortByDate.option.asc.label": "Ascending",
+ "customField.comments.input.sortByDate.option.desc.label": "Descending",
+ "customField.comments.input.filterBy.label": "Filter by",
+ "customField.comments.input.filterBy.option.dateCreated.label": "Creation date",
+ "customField.comments.input.filterBy.option.dateCreated.label.details.label": "Specify date",
+ "customField.comments.input.filterBy.option.approvalStatus.label": "Approval Status",
+ "customField.comments.input.filterBy.option.approvalStatus.label.details.label": "Specify status",
+ "customField.comments.input.filterBy.option.approvalStatus.option.pending.label": "Pending",
+ "customField.comments.input.filterBy.option.approvalStatus.option.approved.label": "Approved",
+ "customField.comments.input.filterBy.option.approvalStatus.option.rejected.label": "Rejected",
+ "customField.comments.input.populate.label": "Populate",
+ "customField.comments.input.populate.author.label": "Populate author field",
+ "customField.comments.input.populate.avatar.label": "Populate avatar field"
}
diff --git a/admin/src/utils/__tests__/functions.test.ts b/admin/src/utils/__tests__/functions.test.ts
new file mode 100644
index 00000000..645ca22f
--- /dev/null
+++ b/admin/src/utils/__tests__/functions.test.ts
@@ -0,0 +1,15 @@
+import { assertString } from "../functions";
+
+describe("assertString()", () => {
+ it("should allow strings", () => {
+ expect(() => assertString("Content")).not.toThrow();
+ });
+
+ it("should reject everything that is not a string", () => {
+ expect(() => assertString(1)).toThrow();
+ expect(() => assertString(null)).toThrow();
+ expect(() => assertString(undefined)).toThrow();
+ expect(() => assertString({})).toThrow();
+ expect(() => assertString(new Error("Error"))).toThrow();
+ });
+});
diff --git a/admin/src/utils/__tests__/getApiUrl.test.ts b/admin/src/utils/__tests__/getApiUrl.test.ts
new file mode 100644
index 00000000..c66b05bb
--- /dev/null
+++ b/admin/src/utils/__tests__/getApiUrl.test.ts
@@ -0,0 +1,7 @@
+import getApiURL from "../getApiUrl";
+
+describe("getApiURL()", () => {
+ it("should return valid URL", () => {
+ expect(getApiURL("comments")).toMatchInlineSnapshot(`"/comments/comments"`);
+ });
+});
diff --git a/admin/src/utils/__tests__/getMessage.test.ts b/admin/src/utils/__tests__/getMessage.test.ts
new file mode 100644
index 00000000..127c0666
--- /dev/null
+++ b/admin/src/utils/__tests__/getMessage.test.ts
@@ -0,0 +1,58 @@
+import getMessage from "../getMessage";
+
+jest.mock("react-intl", () => ({
+ useIntl: () => ({
+ formatMessage: (x: any, y: any) => ({
+ ...x,
+ ...y,
+ }),
+ }),
+}));
+
+describe("getMessage()", () => {
+ it("should handle simple string", () => {
+ expect(getMessage("message.key")).toMatchInlineSnapshot(`
+ Object {
+ "defaultMessage": "",
+ "id": "comments.message.key",
+ }
+ `);
+ expect(getMessage("message.key", "message.default")).toMatchInlineSnapshot(`
+ Object {
+ "defaultMessage": "message.default",
+ "id": "comments.message.key",
+ }
+ `);
+ });
+ it("should handle config object", () => {
+ expect(
+ getMessage(
+ {
+ id: "message.key",
+ },
+ "message.default"
+ )
+ ).toMatchInlineSnapshot(`
+ Object {
+ "defaultMessage": "message.default",
+ "id": "comments.message.key",
+ }
+ `);
+ });
+ it("should allow out of scope translates", () => {
+ expect(
+ getMessage(
+ {
+ id: "message.key",
+ },
+ "message.key.default",
+ false
+ )
+ ).toMatchInlineSnapshot(`
+ Object {
+ "defaultMessage": "message.key.default",
+ "id": "app.components.message.key",
+ }
+ `);
+ });
+});
diff --git a/admin/src/utils/__tests__/getUrl.test.ts b/admin/src/utils/__tests__/getUrl.test.ts
new file mode 100644
index 00000000..d7a55265
--- /dev/null
+++ b/admin/src/utils/__tests__/getUrl.test.ts
@@ -0,0 +1,10 @@
+import getUrl from "../getUrl";
+
+describe("getUrl()", () => {
+ it("should return valid URL", () => {
+ expect(getUrl("comments")).toMatchInlineSnapshot(
+ `"/plugins/comments/comments"`
+ );
+ expect(getUrl(undefined)).toMatchInlineSnapshot(`"/plugins/comments/"`);
+ });
+});
diff --git a/admin/src/utils/__tests__/handleAPIError.test.ts b/admin/src/utils/__tests__/handleAPIError.test.ts
new file mode 100644
index 00000000..3fb229c2
--- /dev/null
+++ b/admin/src/utils/__tests__/handleAPIError.test.ts
@@ -0,0 +1,28 @@
+import handleAPIError from "../handleAPIError";
+
+describe("handleAPIError()", () => {
+ it("should re-throw error", () => {
+ const err = new Error("Error");
+
+ expect(() => handleAPIError(null, jest.fn)).toThrowError(Error);
+ expect(() => handleAPIError(undefined, jest.fn)).toThrowError();
+ expect(() => handleAPIError(err, undefined)).toThrowError(Error);
+ expect(() => handleAPIError(err, jest.fn)).toThrowError(err);
+ });
+
+ it("should notify app", () => {
+ const err = new Error("Error");
+ const notify = jest.fn();
+
+ expect(() => handleAPIError(err, notify, "message")).toThrowError(err);
+ expect(notify).toHaveBeenCalled();
+ expect(notify.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "message": "comments.message",
+ "type": "warning",
+ },
+ ]
+ `);
+ });
+});
diff --git a/admin/src/utils/__tests__/perseRegExp.test.ts b/admin/src/utils/__tests__/perseRegExp.test.ts
new file mode 100644
index 00000000..15d509a1
--- /dev/null
+++ b/admin/src/utils/__tests__/perseRegExp.test.ts
@@ -0,0 +1,12 @@
+import parseRegExp from "../parseRegExp";
+
+describe("parseRegExp()", () => {
+ it("should parse regexp", () => {
+ expect(parseRegExp("/[a-z]/gi")).toMatchInlineSnapshot(`
+ Object {
+ "flags": "gi",
+ "value": "[a-z]",
+ }
+ `);
+ });
+});
diff --git a/admin/src/utils/__tests__/resolveCommentStatus.test.ts b/admin/src/utils/__tests__/resolveCommentStatus.test.ts
new file mode 100644
index 00000000..4aacafbf
--- /dev/null
+++ b/admin/src/utils/__tests__/resolveCommentStatus.test.ts
@@ -0,0 +1,49 @@
+import { COMMENT_STATUS } from "../constants";
+import resolveCommentStatus from "../resolveCommentStatus";
+
+describe("resolveCommentStatus()", () => {
+ it("should handle removed comments", () => {
+ expect(
+ resolveCommentStatus({
+ removed: true,
+ })
+ ).toMatchInlineSnapshot(`"REMOVED"`);
+ });
+ it("should handle blocked comments", () => {
+ expect(
+ resolveCommentStatus({
+ blocked: true,
+ })
+ ).toMatchInlineSnapshot(`"BLOCKED"`);
+ expect(
+ resolveCommentStatus({
+ blockedThread: true,
+ })
+ ).toMatchInlineSnapshot(`"BLOCKED"`);
+ });
+ it.each(Object.values(COMMENT_STATUS))(
+ "should handle %s comment's status",
+ (approvalStatus) => {
+ expect(
+ resolveCommentStatus({
+ approvalStatus,
+ })
+ ).toEqual(approvalStatus);
+ }
+ );
+ it("should handle unknown status", () => {
+ expect(
+ resolveCommentStatus({
+ approvalStatus: "FOO",
+ })
+ ).toMatchInlineSnapshot(`"UNKNOWN"`);
+ });
+ it("should handle review comment", () => {
+ expect(
+ resolveCommentStatus({ reviewFlowEnabled: true })
+ ).toMatchInlineSnapshot(`"TO_REVIEW"`);
+ });
+ it("should empty input", () => {
+ expect(resolveCommentStatus({})).toMatchInlineSnapshot(`"OPEN"`);
+ });
+});
diff --git a/admin/src/utils/errors.ts b/admin/src/utils/errors.ts
new file mode 100644
index 00000000..cdb64238
--- /dev/null
+++ b/admin/src/utils/errors.ts
@@ -0,0 +1,3 @@
+export class UIError extends Error {}
+
+export class ValidationError extends UIError {}
diff --git a/admin/src/utils/functions.ts b/admin/src/utils/functions.ts
new file mode 100644
index 00000000..7b5fbe18
--- /dev/null
+++ b/admin/src/utils/functions.ts
@@ -0,0 +1,7 @@
+import { ValidationError } from "./errors";
+
+export function assertString(value: unknown): asserts value is string {
+ if (typeof value !== "string") {
+ throw new ValidationError(`String expected, but "${typeof value}" given`);
+ }
+}
diff --git a/admin/src/utils/getRelatedGroups.ts b/admin/src/utils/getRelatedGroups.ts
index 74c96bcc..b59ac4cc 100644
--- a/admin/src/utils/getRelatedGroups.ts
+++ b/admin/src/utils/getRelatedGroups.ts
@@ -1,6 +1,10 @@
-import { ToBeFixed } from "../../../types";
+type Config = {
+ regex: {
+ relatedUid: string;
+ };
+};
-const getRelatedGroups = (related: string, config: ToBeFixed) =>
+const getRelatedGroups = (related: string, config: Config) =>
related.split(config.regex.relatedUid).filter((s) => s && s.length > 0);
export default getRelatedGroups;
diff --git a/admin/src/utils/handleAPIError.ts b/admin/src/utils/handleAPIError.ts
index 2d3a6cf6..cfe36f30 100644
--- a/admin/src/utils/handleAPIError.ts
+++ b/admin/src/utils/handleAPIError.ts
@@ -2,7 +2,7 @@ import { ToBeFixed } from "../../../types";
import { pluginId } from "../pluginId";
const handleAPIError = (
- err = null,
+ err: Error | null = null,
toggleNotification: ToBeFixed = null,
message = "app.components.notification.error"
) => {
diff --git a/admin/src/utils/index.ts b/admin/src/utils/index.ts
index f6a8d576..adf8238f 100644
--- a/admin/src/utils/index.ts
+++ b/admin/src/utils/index.ts
@@ -11,3 +11,6 @@ export {default as resolveCommentStatusColor} from './resolveCommentStatusColor'
export {default as resolveReportStatus} from './resolveReportStatus';
export {default as resolveReportStatusColor} from './resolveReportStatusColor';
export {default as parseRegExp} from './parseRegExp';
+export { APPROVAL_STATUS } from './constants'
+export { UIError, ValidationError } from './errors'
+export { assertString } from './functions'
diff --git a/admin/src/utils/resolveCommentStatus.ts b/admin/src/utils/resolveCommentStatus.ts
index dd5da4e1..6f167c31 100644
--- a/admin/src/utils/resolveCommentStatus.ts
+++ b/admin/src/utils/resolveCommentStatus.ts
@@ -1,14 +1,21 @@
import { isNil } from "lodash";
-import { ToBeFixed } from "../../../types";
import { COMMENT_STATUS } from "./constants";
+type Config = {
+ removed?: boolean;
+ blocked?: boolean;
+ blockedThread?: boolean;
+ approvalStatus?: string;
+ reviewFlowEnabled?: boolean;
+};
+
const resolveCommentStatus = ({
removed,
blocked,
blockedThread,
approvalStatus,
reviewFlowEnabled,
-}: ToBeFixed) => {
+}: Config) => {
const gotApprovalFlow = !isNil(approvalStatus);
if (removed) {
diff --git a/package.json b/package.json
index 374c49da..81e9c134 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "strapi-plugin-comments",
- "version": "2.2.0-beta.1",
+ "version": "2.2.0-beta.0",
"description": "Strapi - Comments plugin",
"strapi": {
"name": "comments",
@@ -18,6 +18,7 @@
"clean": "rm -rf build",
"develop": "nodemon --exec \"yarn build:dev\"",
"test:unit": "jest --verbose --coverage",
+ "test:unit:ci": "CI=true jest --ci --verbose --coverage",
"lint": "prettier --check .",
"format": "prettier --write ."
},
@@ -34,6 +35,7 @@
"bad-words": "^3.0.4"
},
"devDependencies": {
+ "@strapi/helper-plugin": "^4.3.8",
"@types/bad-words": "^3.0.1",
"@types/jest": "^27.4.1",
"codecov": "^3.7.2",
@@ -46,7 +48,7 @@
"nodemon": "^2.0.15",
"prettier": "^2.6.0",
"rimraf": "^3.0.2",
- "strapi-typed": "^1.0.12",
+ "strapi-typed": "^1.0.14",
"ts-jest": "^27.1.3",
"ts-node": "^10.7.0",
"typescript": "^4.6.3"
diff --git a/server/register.ts b/server/register.ts
deleted file mode 100644
index 32fad849..00000000
--- a/server/register.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export = () => {
- // register phase
-};
diff --git a/server/register/custom-fields/__tests__/index.test.ts b/server/register/custom-fields/__tests__/index.test.ts
new file mode 100644
index 00000000..dc4fd667
--- /dev/null
+++ b/server/register/custom-fields/__tests__/index.test.ts
@@ -0,0 +1,37 @@
+import { IStrapi } from "strapi-typed";
+import { registerCustomFields } from "..";
+
+describe("registerCustomFields()", () => {
+ it("should apply custom field when strapi supports it", () => {
+ const strapi: Pick = {
+ customFields: {
+ register: jest.fn(),
+ },
+ };
+
+ registerCustomFields({ strapi } as any);
+
+ expect(strapi.customFields.register).toHaveBeenCalled();
+ expect((strapi.customFields.register as jest.Mock).mock.calls[0][0])
+ .toMatchInlineSnapshot(`
+ Object {
+ "name": "comments",
+ "plugin": "comments",
+ "type": "json",
+ }
+ `);
+ });
+ it("should not require custom fields functionality to bootstrap comments plugin", () => {
+ expect(() =>
+ registerCustomFields({ strapi: { log: { warn: jest.fn() } } } as any)
+ ).not.toThrow();
+ });
+ it("should notify about custom field option", () => {
+ const warn = jest.fn();
+
+ expect(() =>
+ registerCustomFields({ strapi: { log: { warn } } } as any)
+ ).not.toThrow();
+ expect(warn).toHaveBeenCalled();
+ });
+});
diff --git a/server/register/custom-fields/comments.ts b/server/register/custom-fields/comments.ts
new file mode 100644
index 00000000..b815d19d
--- /dev/null
+++ b/server/register/custom-fields/comments.ts
@@ -0,0 +1,5 @@
+export const commentsCustomField = {
+ name: "comments",
+ plugin: "comments",
+ type: "json",
+} as const;
diff --git a/server/register/custom-fields/index.ts b/server/register/custom-fields/index.ts
new file mode 100644
index 00000000..46fa827c
--- /dev/null
+++ b/server/register/custom-fields/index.ts
@@ -0,0 +1,16 @@
+import { StrapiContext } from "strapi-typed";
+import { commentsCustomField } from "./comments";
+
+export const registerCustomFields = ({ strapi }: StrapiContext) => {
+ if (!canRegister({ strapi })) {
+ strapi.log.warn(
+ "[Comments Plugin] Custom fields disabled. Upgrade Strapi to use custom fields."
+ );
+
+ return;
+ }
+
+ strapi.customFields.register(commentsCustomField);
+};
+
+const canRegister = ({ strapi }: StrapiContext) => !!strapi.customFields;
diff --git a/server/register/index.ts b/server/register/index.ts
new file mode 100644
index 00000000..d7e2473e
--- /dev/null
+++ b/server/register/index.ts
@@ -0,0 +1,8 @@
+import { StrapiContext } from "strapi-typed";
+import { registerCustomFields } from "./custom-fields";
+
+const register = (context: StrapiContext) => {
+ registerCustomFields(context);
+};
+
+export default register;
diff --git a/server/services/__tests__/client.test.ts b/server/services/__tests__/client.test.ts
index 69cb2abd..7a7e7e5d 100644
--- a/server/services/__tests__/client.test.ts
+++ b/server/services/__tests__/client.test.ts
@@ -1,4 +1,4 @@
-import { StrapiUser } from "strapi-typed";
+import { Id, StrapiUser } from "strapi-typed";
import { IServiceClient } from "../../../types";
import { Comment } from "../../../types/contentTypes";
import { setupStrapi, resetStrapi } from "../../../__mocks__/initSetup";
@@ -59,7 +59,7 @@ describe("Test Comments service - Client", () => {
},
];
const relatedEntity = { id: 1, title: "Test", uid: collection };
- const adminUser = { id: 1, username: "Admin", email: "admin@example.com" }
+ const adminUser = { id: 1, username: "Admin", email: "admin@example.com" };
const errorThrown = (e: unknown, message: string, status: number = 400) => {
expect(e).toBeInstanceOf(PluginError);
@@ -833,7 +833,7 @@ describe("Test Comments service - Client", () => {
await getPluginService("client").markAsRemoved(
1,
"api::not-enabled.relation:1",
- undefined,
+ undefined as unknown as Id,
undefined
);
} catch (e) {
@@ -964,7 +964,7 @@ describe("Test Comments service - Client", () => {
const result = await getPluginService(
"client"
- ).markAsRemoved(1, related, undefined, user);
+ ).markAsRemoved(1, related, undefined as unknown as Id, user);
expect(result).toHaveProperty(["id"], 4);
expect(result).toHaveProperty(["related"], related);
@@ -1078,7 +1078,7 @@ describe("Test Comments service - Client", () => {
default:
return resolve([related]);
}
- }),
+ }),
create: async (args: any) =>
new Promise((resolve) => {
return resolve({
@@ -1089,13 +1089,12 @@ describe("Test Comments service - Client", () => {
}));
const spyPluginEmail = jest
- .spyOn(global.strapi.plugins.email.services.email, 'send')
+ .spyOn(global.strapi.plugins.email.services.email, "send")
// @ts-ignore
.mockImplementation((args: any) => ({
- status: 200,
- params: args,
- })
- );
+ status: 200,
+ params: args,
+ }));
const result = await getPluginService(
"client"
@@ -1107,9 +1106,18 @@ describe("Test Comments service - Client", () => {
expect(result).toHaveProperty(["reason"], payload.reason);
expect(spyPluginEmail).toHaveBeenCalledTimes(1);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["from"], adminUser.email);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["to", 0], adminUser.email);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["subject"], "New abuse report on comment");
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["from"],
+ adminUser.email
+ );
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["to", 0],
+ adminUser.email
+ );
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["subject"],
+ "New abuse report on comment"
+ );
spyQuery.mockRestore();
spyPluginEmail.mockRestore();
@@ -1119,24 +1127,26 @@ describe("Test Comments service - Client", () => {
describe("Inform about response", () => {
const clientSettings = {
- url: 'http://testsite.com',
- contactEmail: 'contact@example.com',
+ url: "http://testsite.com",
+ contactEmail: "contact@example.com",
};
beforeEach(() =>
- setupStrapi({ enabledCollections: [collection], client: { ...clientSettings } }, true, {
- "plugins::comments": db,
- "api::collection": [
- relatedEntity,
- { id: 2, title: "Test 2", uid: collection },
- ],
- })
+ setupStrapi(
+ { enabledCollections: [collection], client: { ...clientSettings } },
+ true,
+ {
+ "plugins::comments": db,
+ "api::collection": [
+ relatedEntity,
+ { id: 2, title: "Test 2", uid: collection },
+ ],
+ }
+ )
);
describe("Successful path", () => {
-
test("Should sent e-mail with proper content to comment author", async () => {
-
const spyQuery = jest
.spyOn(global.strapi.db, "query")
// @ts-ignore
@@ -1162,29 +1172,43 @@ describe("Test Comments service - Client", () => {
default:
return resolve([related]);
}
- }),
+ }),
}));
const spyPluginEmail = jest
- .spyOn(global.strapi.plugins.email.services.email, 'send')
+ .spyOn(global.strapi.plugins.email.services.email, "send")
// @ts-ignore
.mockImplementation((args: any) => ({
- status: 200,
- params: args,
- })
- );
+ status: 200,
+ params: args,
+ }));
const result = await getPluginService(
"client"
).sendResponseNotification(db[1]);
expect(spyPluginEmail).toHaveBeenCalledTimes(1);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["from"], clientSettings.contactEmail);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["to", 0], db[0].authorEmail);
- expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(["subject"], "You've got a new response to your comment");
- expect(spyPluginEmail.mock.results[0].value.params.text).toContain(db[0].authorName);
- expect(spyPluginEmail.mock.results[0].value.params.text).toContain(db[1].authorName);
- expect(spyPluginEmail.mock.results[0].value.params.text).toContain(clientSettings.url);
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["from"],
+ clientSettings.contactEmail
+ );
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["to", 0],
+ db[0].authorEmail
+ );
+ expect(spyPluginEmail.mock.results[0].value.params).toHaveProperty(
+ ["subject"],
+ "You've got a new response to your comment"
+ );
+ expect(spyPluginEmail.mock.results[0].value.params.text).toContain(
+ db[0].authorName
+ );
+ expect(spyPluginEmail.mock.results[0].value.params.text).toContain(
+ db[1].authorName
+ );
+ expect(spyPluginEmail.mock.results[0].value.params.text).toContain(
+ clientSettings.url
+ );
spyQuery.mockRestore();
spyPluginEmail.mockRestore();
diff --git a/server/utils/__tests__/error.test.ts b/server/utils/__tests__/error.test.ts
new file mode 100644
index 00000000..6743f52c
--- /dev/null
+++ b/server/utils/__tests__/error.test.ts
@@ -0,0 +1,40 @@
+import PluginError from "../error";
+
+describe("PluginError", () => {
+ describe("toString()", () => {
+ it("should serialize error", () => {
+ expect(
+ new PluginError(404, "Not found", {
+ item: "comment",
+ random: "value",
+ }).toString()
+ ).toMatchInlineSnapshot(`"Strapi:Plugin:Comments - Not found"`);
+ expect(new PluginError(0, "").toString()).toMatchInlineSnapshot(
+ `"Strapi:Plugin:Comments - Internal error"`
+ );
+ });
+ });
+ describe("toJSON()", () => {
+ it("should serialize an error", () => {
+ expect(
+ new PluginError(404, "Not found", {
+ item: "comment",
+ random: "value",
+ }).toJSON()
+ ).toMatchInlineSnapshot(`
+ Object {
+ "item": "comment",
+ "message": "Not found",
+ "name": "Strapi:Plugin:Comments",
+ "random": "value",
+ }
+ `);
+ expect(new PluginError(404, "Not found").toJSON()).toMatchInlineSnapshot(
+ `[Strapi:Plugin:Comments: Not found]`
+ );
+ expect(new PluginError(0, "").toJSON()).toMatchInlineSnapshot(
+ `[Strapi:Plugin:Comments: Internal error]`
+ );
+ });
+ });
+});
diff --git a/server/utils/__tests__/functions.test.ts b/server/utils/__tests__/functions.test.ts
index d299396a..66345422 100644
--- a/server/utils/__tests__/functions.test.ts
+++ b/server/utils/__tests__/functions.test.ts
@@ -1,5 +1,10 @@
import { setupStrapi, resetStrapi } from "../../../__mocks__/initSetup";
-import { getPluginService } from "../functions";
+import {
+ assertNotEmpty,
+ assertParamsPresent,
+ getPluginService,
+ parseParams,
+} from "../functions";
beforeEach(setupStrapi);
afterEach(resetStrapi);
@@ -10,4 +15,39 @@ describe("Test plugin functions utils", () => {
expect(getPluginService("common")).toHaveProperty("findAllFlat");
});
});
+ describe("parseParams()", () => {
+ it("should parse params", () => {
+ expect(
+ parseParams({
+ id: "1",
+ name: "NAME",
+ })
+ ).toMatchInlineSnapshot(`
+ Object {
+ "id": 1,
+ "name": "NAME",
+ }
+ `);
+ });
+ });
+ describe("assertParamsPresent()", () => {
+ it("should assert params", () => {
+ expect(() => assertParamsPresent(1, ["id"])).toThrow();
+ expect(() => assertParamsPresent(null, ["id"])).toThrow();
+ expect(() => assertParamsPresent(undefined, ["id"])).toThrow();
+ expect(() => assertParamsPresent("", ["id"])).toThrow();
+ expect(() => assertParamsPresent("a text", ["id"])).toThrow();
+ expect(() => assertParamsPresent({}, ["id"])).toThrow();
+ expect(() => assertParamsPresent({ id: "1" }, ["id"])).not.toThrow();
+ });
+ });
+ describe("assertNotEmpty()", () => {
+ it("should assert non empty value", () => {
+ expect(() => assertNotEmpty(null)).toThrow();
+ expect(() => assertNotEmpty(undefined)).toThrow();
+ expect(() => assertNotEmpty(0)).toThrow();
+ expect(() => assertNotEmpty(1)).not.toThrow();
+ expect(() => assertNotEmpty({ id: 1 })).not.toThrow();
+ });
+ });
});
diff --git a/server/utils/error.ts b/server/utils/error.ts
index b7cb744c..f98c2a83 100644
--- a/server/utils/error.ts
+++ b/server/utils/error.ts
@@ -34,9 +34,9 @@ export default class PluginError extends Error implements IPluginError {
toJSON() {
if (this.payload) {
return {
+ ...this.payload,
name: this.name,
message: this.message,
- ...(this.payload || {}),
};
}
return this;
diff --git a/types/__tests__/utils.test.ts b/types/__tests__/utils.test.ts
new file mode 100644
index 00000000..4552de32
--- /dev/null
+++ b/types/__tests__/utils.test.ts
@@ -0,0 +1,14 @@
+import { assertComment } from "../utils";
+
+describe("Types", () => {
+ describe("Utils", () => {
+ describe("assertComment()", () => {
+ it("should validate input", () => {
+ expect(() => assertComment(undefined)).toThrow();
+ expect(() => assertComment(null)).toThrow();
+ expect(() => assertComment({})).toThrow();
+ expect(() => assertComment({ id: 1, content: "A comment" })).not.toThrow();
+ });
+ });
+ });
+});
diff --git a/types/utils.ts b/types/utils.ts
index 205e6082..066a40bd 100644
--- a/types/utils.ts
+++ b/types/utils.ts
@@ -2,7 +2,7 @@ import { Comment } from "./contentTypes";
// TODO => change to arrow function
export function assertComment(value: any): asserts value is Comment {
- if (!(value.id && value.content)) {
+ if (!(value?.id && value?.content)) {
throw new Error("Provided value is not Comment type");
}
}
diff --git a/yarn.lock b/yarn.lock
index 2719f10f..0be6d620 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -140,6 +140,13 @@
"@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1"
+"@babel/helper-annotate-as-pure@^7.16.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
+ integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
"@babel/helper-compilation-targets@^7.19.1":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c"
@@ -170,7 +177,7 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-module-imports@^7.18.6":
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.0", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
@@ -283,6 +290,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
+"@babel/plugin-syntax-jsx@^7.17.12":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0"
+ integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
"@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
@@ -339,7 +353,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2":
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7":
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
@@ -355,7 +369,7 @@
"@babel/parser" "^7.18.10"
"@babel/types" "^7.18.10"
-"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.7.2":
+"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.2":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347"
integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==
@@ -392,6 +406,136 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
+"@emotion/babel-plugin@^11.10.0":
+ version "11.10.2"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz#879db80ba622b3f6076917a1e6f648b1c7d008c7"
+ integrity sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/plugin-syntax-jsx" "^7.17.12"
+ "@babel/runtime" "^7.18.3"
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/serialize" "^1.1.0"
+ babel-plugin-macros "^3.1.0"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "4.0.13"
+
+"@emotion/cache@^11.0.0", "@emotion/cache@^11.10.0":
+ version "11.10.3"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.3.tgz#c4f67904fad10c945fea5165c3a5a0583c164b87"
+ integrity sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==
+ dependencies:
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/sheet" "^1.2.0"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ stylis "4.0.13"
+
+"@emotion/css@^11.0.0":
+ version "11.10.0"
+ resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.10.0.tgz#270b4fdf2419e59cb07081d0e9f7940d88b8b443"
+ integrity sha512-dH9f+kSCucc8ilMg0MUA1AemabcyzYpe5EKX24F528PJjD7HyIY/VBNJHxfUdc8l400h2ncAjR6yEDu+DBj2cg==
+ dependencies:
+ "@emotion/babel-plugin" "^11.10.0"
+ "@emotion/cache" "^11.10.0"
+ "@emotion/serialize" "^1.1.0"
+ "@emotion/sheet" "^1.2.0"
+ "@emotion/utils" "^1.2.0"
+
+"@emotion/hash@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7"
+ integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==
+
+"@emotion/is-prop-valid@^0.8.8":
+ version "0.8.8"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
+ integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
+ dependencies:
+ "@emotion/memoize" "0.7.4"
+
+"@emotion/memoize@0.7.4":
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
+ integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
+
+"@emotion/memoize@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f"
+ integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==
+
+"@emotion/react@^11.1.1":
+ version "11.10.4"
+ resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.4.tgz#9dc6bccbda5d70ff68fdb204746c0e8b13a79199"
+ integrity sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.10.0"
+ "@emotion/cache" "^11.10.0"
+ "@emotion/serialize" "^1.1.0"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8"
+ integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==
+ dependencies:
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/unitless" "^0.8.0"
+ "@emotion/utils" "^1.2.0"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5"
+ integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==
+
+"@emotion/stylis@^0.8.4":
+ version "0.8.5"
+ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
+ integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
+
+"@emotion/unitless@^0.7.4":
+ version "0.7.5"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
+ integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
+
+"@emotion/unitless@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db"
+ integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df"
+ integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==
+
+"@emotion/utils@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561"
+ integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==
+
+"@emotion/weak-memoize@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb"
+ integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
+
+"@formatjs/ecma402-abstract@1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz#b962dfc4ae84361f9f08fbce411b4e4340930eda"
+ integrity sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==
+ dependencies:
+ "@formatjs/intl-localematcher" "0.2.25"
+ tslib "^2.1.0"
+
"@formatjs/ecma402-abstract@1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.12.0.tgz#2fb5e8983d5fae2fad9ec6c77aec1803c2b88d8e"
@@ -400,6 +544,13 @@
"@formatjs/intl-localematcher" "0.2.31"
tslib "2.4.0"
+"@formatjs/fast-memoize@1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz#e6f5aee2e4fd0ca5edba6eba7668e2d855e0fc21"
+ integrity sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==
+ dependencies:
+ tslib "^2.1.0"
+
"@formatjs/fast-memoize@1.2.6":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.6.tgz#a442970db7e9634af556919343261a7bbe5e88c3"
@@ -407,6 +558,15 @@
dependencies:
tslib "2.4.0"
+"@formatjs/icu-messageformat-parser@2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz#a54293dd7f098d6a6f6a084ab08b6d54a3e8c12d"
+ integrity sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/icu-skeleton-parser" "1.3.6"
+ tslib "^2.1.0"
+
"@formatjs/icu-messageformat-parser@2.1.7":
version "2.1.7"
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.7.tgz#35dc556c13a0544cc730300c8ddb730ba7f44bd4"
@@ -424,6 +584,23 @@
"@formatjs/ecma402-abstract" "1.12.0"
tslib "2.4.0"
+"@formatjs/icu-skeleton-parser@1.3.6":
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz#4ce8c0737d6f07b735288177049e97acbf2e8964"
+ integrity sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ tslib "^2.1.0"
+
+"@formatjs/intl-displaynames@5.4.3":
+ version "5.4.3"
+ resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-5.4.3.tgz#e468586694350c722c7efab1a31fcde68aeaed8b"
+ integrity sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/intl-localematcher" "0.2.25"
+ tslib "^2.1.0"
+
"@formatjs/intl-displaynames@6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.1.3.tgz#c9d283db518cd721c0855e9854bfadb9ba304b6a"
@@ -433,6 +610,15 @@
"@formatjs/intl-localematcher" "0.2.31"
tslib "2.4.0"
+"@formatjs/intl-listformat@6.5.3":
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-6.5.3.tgz#f29da613a8062dc3e4e3d847ba890c3ea745f051"
+ integrity sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/intl-localematcher" "0.2.25"
+ tslib "^2.1.0"
+
"@formatjs/intl-listformat@7.1.2":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.1.2.tgz#3c5145436434795fa834150d0b6b6dc577aa6964"
@@ -442,6 +628,13 @@
"@formatjs/intl-localematcher" "0.2.31"
tslib "2.4.0"
+"@formatjs/intl-localematcher@0.2.25":
+ version "0.2.25"
+ resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz#60892fe1b271ec35ba07a2eb018a2dd7bca6ea3a"
+ integrity sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==
+ dependencies:
+ tslib "^2.1.0"
+
"@formatjs/intl-localematcher@0.2.31":
version "0.2.31"
resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.31.tgz#aada2b1e58211460cedba56889e3c489117eb6eb"
@@ -449,6 +642,19 @@
dependencies:
tslib "2.4.0"
+"@formatjs/intl@2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.2.1.tgz#6daf4dabed055b17f467f0aa1bc073a626bc9189"
+ integrity sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/fast-memoize" "1.2.1"
+ "@formatjs/icu-messageformat-parser" "2.1.0"
+ "@formatjs/intl-displaynames" "5.4.3"
+ "@formatjs/intl-listformat" "6.5.3"
+ intl-messageformat "9.13.0"
+ tslib "^2.1.0"
+
"@formatjs/intl@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.4.1.tgz#3e8ae8542e827c55cb1b7298bd72d4a009c2224d"
@@ -462,6 +668,49 @@
intl-messageformat "10.1.4"
tslib "2.4.0"
+"@fortawesome/fontawesome-common-types@6.1.2":
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz#c1095b1bbabf19f37f9ff0719db38d92a410bcfe"
+ integrity sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA==
+
+"@fortawesome/fontawesome-common-types@^0.2.36":
+ version "0.2.36"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903"
+ integrity sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==
+
+"@fortawesome/fontawesome-free@^5.15.2":
+ version "5.15.4"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5"
+ integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==
+
+"@fortawesome/fontawesome-svg-core@6.1.2":
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz#11e2e8583a7dea75d734e4d0e53d91c63fae7511"
+ integrity sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA==
+ dependencies:
+ "@fortawesome/fontawesome-common-types" "6.1.2"
+
+"@fortawesome/free-brands-svg-icons@^5.15.2":
+ version "5.15.4"
+ resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz#ec8a44dd383bcdd58aa7d1c96f38251e6fec9733"
+ integrity sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==
+ dependencies:
+ "@fortawesome/fontawesome-common-types" "^0.2.36"
+
+"@fortawesome/free-solid-svg-icons@^5.15.3":
+ version "5.15.4"
+ resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz#2a68f3fc3ddda12e52645654142b9e4e8fbb6cc5"
+ integrity sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==
+ dependencies:
+ "@fortawesome/fontawesome-common-types" "^0.2.36"
+
+"@fortawesome/react-fontawesome@^0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4"
+ integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==
+ dependencies:
+ prop-types "^15.8.1"
+
"@graphql-tools/merge@8.3.1":
version "8.3.1"
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.1.tgz#06121942ad28982a14635dbc87b5d488a041d722"
@@ -860,7 +1109,35 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
-"@strapi/plugin-graphql@^4.3.0", "@strapi/plugin-graphql@^4.3.8":
+"@strapi/helper-plugin@^4.3.8":
+ version "4.3.8"
+ resolved "https://registry.yarnpkg.com/@strapi/helper-plugin/-/helper-plugin-4.3.8.tgz#e9053e3fa00e43aaeadbbb8e06eee7aead92ed41"
+ integrity sha512-qEv1YnDwDMe8nNH9m6drUcnfGLPmt7TiLaD+sg2fcwNwILO3Imis7l4vy/qKraOmj4iWiB+j160+J5oiiN3a3w==
+ dependencies:
+ "@fortawesome/fontawesome-free" "^5.15.2"
+ "@fortawesome/fontawesome-svg-core" "6.1.2"
+ "@fortawesome/free-brands-svg-icons" "^5.15.2"
+ "@fortawesome/free-solid-svg-icons" "^5.15.3"
+ "@fortawesome/react-fontawesome" "^0.2.0"
+ axios "0.27.2"
+ date-fns "2.29.2"
+ formik "^2.2.6"
+ immer "9.0.6"
+ invariant "^2.2.1"
+ lodash "4.17.21"
+ match-sorter "^4.0.2"
+ qs "6.10.1"
+ react "^17.0.2"
+ react-dom "^17.0.2"
+ react-helmet "^6.1.0"
+ react-intl "5.25.1"
+ react-router "^5.2.0"
+ react-router-dom "5.2.0"
+ react-select "4.0.2"
+ styled-components "5.3.3"
+ whatwg-fetch "^3.6.2"
+
+"@strapi/plugin-graphql@^4.3.8":
version "4.3.8"
resolved "https://registry.yarnpkg.com/@strapi/plugin-graphql/-/plugin-graphql-4.3.8.tgz#1cd0ac23f1a373a63c6de687c0e4991cde009347"
integrity sha512-nHXWEje3nqF5v1NHQFqcfjJRbzk1B1HNZknKwiESeQ5IfiiDKSEx2Hq0pTT7FMeJx568SdbZaHT30R2Jih5eNQ==
@@ -882,7 +1159,7 @@
pluralize "^8.0.0"
subscriptions-transport-ws "0.9.19"
-"@strapi/utils@4.3.8", "@strapi/utils@^4.3.0", "@strapi/utils@^4.3.8":
+"@strapi/utils@4.3.8", "@strapi/utils@^4.3.8":
version "4.3.8"
resolved "https://registry.yarnpkg.com/@strapi/utils/-/utils-4.3.8.tgz#10212a2deba66be85aabc3214f9ed5eb945cfed5"
integrity sha512-Ckgd3B+gOLRXyuAt2hFiXQQ7nay5UtsqAcy8On25gvsidz+5LK70k+afXG9A02Hg6pNeNU3goU/Ah3gpRho7fg==
@@ -1136,6 +1413,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
+"@types/parse-json@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
+ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
"@types/prettier@^2.1.5":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.0.tgz#ea03e9f0376a4446f44797ca19d9c46c36e352dc"
@@ -1467,7 +1749,7 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
-axios@*:
+axios@*, axios@0.27.2:
version "0.27.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
@@ -1510,6 +1792,31 @@ babel-plugin-jest-hoist@^27.5.1:
"@types/babel__core" "^7.0.0"
"@types/babel__traverse" "^7.0.6"
+babel-plugin-macros@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
+ integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ cosmiconfig "^7.0.0"
+ resolve "^1.19.0"
+
+"babel-plugin-styled-components@>= 1.12.0":
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086"
+ integrity sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.0"
+ "@babel/helper-module-imports" "^7.16.0"
+ babel-plugin-syntax-jsx "^6.18.0"
+ lodash "^4.17.11"
+ picomatch "^2.3.0"
+
+babel-plugin-syntax-jsx@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
+ integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==
+
babel-preset-current-node-syntax@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
@@ -1674,10 +1981,15 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
+camelize@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
+ integrity sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==
+
caniuse-lite@^1.0.30001400:
- version "1.0.30001409"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001409.tgz#6135da9dcab34cd9761d9cdb12a68e6740c5e96e"
- integrity sha512-V0mnJ5dwarmhYv8/MzhJ//aW68UpvnQBXv8lJ2QUsvn2pHcmAuNtu8hQEDz37XnA1iE+lRR9CIfGWWpgJ5QedQ==
+ version "1.0.30001408"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001408.tgz#8f5e96bd9c5fd1a8c629e4415cdbaf556333a591"
+ integrity sha512-DdUCktgMSM+1ndk9EFMZcavsGszV7zxV9O7MtOHniTa/iyAIwJCF0dFVBdU9SijJbfh29hC9bCs07wu8pjnGJQ==
chalk@^2.0.0:
version "2.4.2"
@@ -1819,7 +2131,7 @@ content-type@^1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
+convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
@@ -1862,6 +2174,17 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+cosmiconfig@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
+ integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.2.1"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.10.0"
+
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -1876,6 +2199,20 @@ cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
+css-color-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
+ integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
+
+css-to-react-native@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756"
+ integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==
+ dependencies:
+ camelize "^1.0.0"
+ css-color-keywords "^1.0.0"
+ postcss-value-parser "^4.0.2"
+
cssfilter@0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
@@ -1951,6 +2288,11 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+deepmerge@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
+ integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
+
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
@@ -2008,6 +2350,14 @@ diff@^4.0.1:
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+dom-helpers@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+ dependencies:
+ "@babel/runtime" "^7.8.7"
+ csstype "^3.0.2"
+
domexception@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
@@ -2165,6 +2515,11 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
+find-root@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
find-up@^4.0.0, find-up@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
@@ -2196,6 +2551,19 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
+formik@^2.2.6:
+ version "2.2.9"
+ resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
+ integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
+ dependencies:
+ deepmerge "^2.1.1"
+ hoist-non-react-statics "^3.3.0"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ react-fast-compare "^2.0.1"
+ tiny-warning "^1.0.2"
+ tslib "^1.10.0"
+
fresh@~0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -2358,7 +2726,19 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
-hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+history@^4.9.0:
+ version "4.10.1"
+ resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
+ integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ loose-envify "^1.2.0"
+ resolve-pathname "^3.0.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+ value-equal "^1.0.1"
+
+hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -2453,6 +2833,19 @@ ignore-walk@3.0.4:
dependencies:
minimatch "^3.0.4"
+immer@9.0.6:
+ version "9.0.6"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73"
+ integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ==
+
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
import-local@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
@@ -2494,6 +2887,23 @@ intl-messageformat@10.1.4:
"@formatjs/icu-messageformat-parser" "2.1.7"
tslib "2.4.0"
+intl-messageformat@9.13.0:
+ version "9.13.0"
+ resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-9.13.0.tgz#97360b73bd82212e4f6005c712a4a16053165468"
+ integrity sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/fast-memoize" "1.2.1"
+ "@formatjs/icu-messageformat-parser" "2.1.0"
+ tslib "^2.1.0"
+
+invariant@^2.2.1:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+ dependencies:
+ loose-envify "^1.0.0"
+
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -3041,7 +3451,7 @@ js-sha3@0.8.0:
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
-js-tokens@^4.0.0:
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@@ -3189,7 +3599,7 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
-lodash-es@^4.17.15:
+lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@@ -3209,7 +3619,7 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
-lodash@4.17.21, lodash@^4.17.20, lodash@^4.7.0:
+lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -3224,6 +3634,13 @@ long@^4.0.0:
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -3255,6 +3672,14 @@ makeerror@1.0.12:
dependencies:
tmpl "1.0.5"
+match-sorter@^4.0.2:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-4.2.1.tgz#575b4b3737185ba9518b67612b66877ea0b37358"
+ integrity sha512-s+3h9TiZU9U1pWhIERHf8/f4LmBN6IXaRgo2CI17+XGByGS1GvG5VvXK9pcGyCjGe3WM3mSYRC3ipGrd5UEVgw==
+ dependencies:
+ "@babel/runtime" "^7.10.5"
+ remove-accents "0.4.2"
+
match-sorter@^6.0.2:
version "6.3.1"
resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda"
@@ -3268,6 +3693,11 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+memoize-one@^5.0.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
+ integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
+
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -3303,6 +3733,14 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+mini-create-react-context@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
+ integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
+ dependencies:
+ "@babel/runtime" "^7.12.1"
+ tiny-warning "^1.0.3"
+
minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -3420,6 +3858,11 @@ nwsapi@^2.2.0:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0"
integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==
+object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
@@ -3492,7 +3935,14 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-parse-json@^5.2.0:
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-json@^5.0.0, parse-json@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
@@ -3532,12 +3982,24 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+path-to-regexp@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
+ integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+ dependencies:
+ isarray "0.0.1"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -3559,6 +4021,11 @@ pluralize@^8.0.0:
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+postcss-value-parser@^4.0.2:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -3591,6 +4058,15 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.5"
+prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
property-expr@^2.0.4:
version "2.0.5"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
@@ -3616,6 +4092,13 @@ punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+qs@6.10.1:
+ version "6.10.1"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
+ integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
+ dependencies:
+ side-channel "^1.0.4"
+
qs@^6.5.2:
version "6.11.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
@@ -3638,6 +4121,42 @@ raw-body@^2.3.3:
iconv-lite "0.4.24"
unpipe "1.0.0"
+react-dom@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
+ integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ scheduler "^0.20.2"
+
+react-fast-compare@^2.0.1:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
+ integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+
+react-fast-compare@^3.1.1:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
+ integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
+
+react-helmet@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726"
+ integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==
+ dependencies:
+ object-assign "^4.1.1"
+ prop-types "^15.7.2"
+ react-fast-compare "^3.1.1"
+ react-side-effect "^2.1.0"
+
+react-input-autosize@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85"
+ integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==
+ dependencies:
+ prop-types "^15.5.8"
+
react-intl@*:
version "6.1.1"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.1.1.tgz#9c9b613f8de8a7d08311455d6a901806da005f8d"
@@ -3654,7 +4173,23 @@ react-intl@*:
intl-messageformat "10.1.4"
tslib "2.4.0"
-react-is@^16.7.0:
+react-intl@5.25.1:
+ version "5.25.1"
+ resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.25.1.tgz#68a73aefc485c9bf70062381ae7f6f4791680879"
+ integrity sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==
+ dependencies:
+ "@formatjs/ecma402-abstract" "1.11.4"
+ "@formatjs/icu-messageformat-parser" "2.1.0"
+ "@formatjs/intl" "2.2.1"
+ "@formatjs/intl-displaynames" "5.4.3"
+ "@formatjs/intl-listformat" "6.5.3"
+ "@types/hoist-non-react-statics" "^3.3.1"
+ "@types/react" "16 || 17 || 18"
+ hoist-non-react-statics "^3.3.2"
+ intl-messageformat "9.13.0"
+ tslib "^2.1.0"
+
+react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -3673,6 +4208,88 @@ react-query@*:
broadcast-channel "^3.4.1"
match-sorter "^6.0.2"
+react-router-dom@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
+ integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ history "^4.9.0"
+ loose-envify "^1.3.1"
+ prop-types "^15.6.2"
+ react-router "5.2.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+
+react-router@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
+ integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ history "^4.9.0"
+ hoist-non-react-statics "^3.1.0"
+ loose-envify "^1.3.1"
+ mini-create-react-context "^0.4.0"
+ path-to-regexp "^1.7.0"
+ prop-types "^15.6.2"
+ react-is "^16.6.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+
+react-router@^5.2.0:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288"
+ integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w==
+ dependencies:
+ "@babel/runtime" "^7.12.13"
+ history "^4.9.0"
+ hoist-non-react-statics "^3.1.0"
+ loose-envify "^1.3.1"
+ mini-create-react-context "^0.4.0"
+ path-to-regexp "^1.7.0"
+ prop-types "^15.6.2"
+ react-is "^16.6.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+
+react-select@4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/react-select/-/react-select-4.0.2.tgz#4dcca9f38d6a41e01f2dc7673e244a325e3b4e0e"
+ integrity sha512-BiihrRpRIBBvNqofNZIBpo08Kw8DBHb/kgpIDW4bxgkttk50Sxf0alEIKobns3U7UJXk/CA4rsFUueQEg9Pm5A==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ "@emotion/cache" "^11.0.0"
+ "@emotion/css" "^11.0.0"
+ "@emotion/react" "^11.1.1"
+ memoize-one "^5.0.0"
+ prop-types "^15.6.0"
+ react-input-autosize "^3.0.0"
+ react-transition-group "^4.3.0"
+
+react-side-effect@^2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.2.tgz#dc6345b9e8f9906dc2eeb68700b615e0b4fe752a"
+ integrity sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==
+
+react-transition-group@^4.3.0:
+ version "4.4.5"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
+ integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
readable-stream@~1.0.31:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
@@ -3730,17 +4347,27 @@ resolve-cwd@^3.0.0:
dependencies:
resolve-from "^5.0.0"
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+resolve-pathname@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
+ integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
+
resolve.exports@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
-resolve@^1.20.0:
+resolve@^1.19.0, resolve@^1.20.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@@ -3783,6 +4410,14 @@ saxes@^5.0.1:
dependencies:
xmlchars "^2.2.0"
+scheduler@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
semver@7.x, semver@^7.3.2:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
@@ -3818,6 +4453,11 @@ sha.js@^2.4.11:
inherits "^2.0.1"
safe-buffer "^5.0.1"
+shallowequal@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
+ integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
+
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@@ -3869,6 +4509,11 @@ source-map-support@^0.5.6:
buffer-from "^1.0.0"
source-map "^0.6.0"
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -3901,7 +4546,7 @@ statuses@2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
-strapi-typed@^1.0.12:
+strapi-typed@^1.0.14:
version "1.0.14"
resolved "https://registry.yarnpkg.com/strapi-typed/-/strapi-typed-1.0.14.tgz#26132f1037357079a733ccd8620c9de5e3680f33"
integrity sha512-z00rDFyMW9aJCZGpxV7UJ83RYZH6CTTd2SCNbAzcgGhctIdNW2G8hmLZwxrbrmhcoBFmad8H+RVPjUfx89r2lw==
@@ -3979,6 +4624,27 @@ stubs@^3.0.0:
resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"
integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==
+styled-components@5.3.3:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743"
+ integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/traverse" "^7.4.5"
+ "@emotion/is-prop-valid" "^0.8.8"
+ "@emotion/stylis" "^0.8.4"
+ "@emotion/unitless" "^0.7.4"
+ babel-plugin-styled-components ">= 1.12.0"
+ css-to-react-native "^3.0.0"
+ hoist-non-react-statics "^3.0.0"
+ shallowequal "^1.1.0"
+ supports-color "^5.5.0"
+
+stylis@4.0.13:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91"
+ integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==
+
subscriptions-transport-ws@0.9.19:
version "0.9.19"
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz#10ca32f7e291d5ee8eb728b9c02e43c52606cdcf"
@@ -4075,6 +4741,16 @@ through2@^2.0.1:
readable-stream "~2.3.6"
xtend "~4.0.1"
+tiny-invariant@^1.0.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9"
+ integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==
+
+tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
@@ -4169,6 +4845,11 @@ tslib@2.4.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+tslib@^1.10.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
tslib@~2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
@@ -4291,6 +4972,11 @@ v8-to-istanbul@^8.1.0:
convert-source-map "^1.6.0"
source-map "^0.7.3"
+value-equal@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
+ integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
+
value-or-promise@1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.10.tgz#5bf041f1e9a8e7043911875547636768a836e446"
@@ -4349,6 +5035,11 @@ whatwg-encoding@^1.0.5:
dependencies:
iconv-lite "0.4.24"
+whatwg-fetch@^3.6.2:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
+ integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
+
whatwg-mimetype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
@@ -4450,6 +5141,11 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+yaml@^1.10.0:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
yargs-parser@20.x, yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"