diff --git a/.eslintrc.js b/.eslintrc.js index 4fc05f5..d2e75e9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,6 +3,8 @@ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { ecmaFeatures: { jsx: true }, + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], }, extends: [ 'eslint:recommended', @@ -12,11 +14,13 @@ module.exports = { 'plugin:jsx-a11y/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', ], rules: { 'prettier/prettier': ['error', {}, { usePrettierrc: true }], 'react/prop-types': 'off', '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-var-requires': 'off', }, settings: { react: { diff --git a/README.md b/README.md index e84df27..471819a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # OhMyForm UI ![Project Status](https://badgen.net/github/checks/ohmyform/ui) -![Travis Status](https://badgen.net/travis/ohmyform/ui) +[![Build Status](https://travis-ci.org/ohmyform/ui.svg?branch=master)](https://travis-ci.org/ohmyform/ui) ![Latest Release](https://badgen.net/github/tag/ohmyform/ui) ![Docker Pulls](https://badgen.net/docker/pulls/ohmyform/ui) [![Lokalise](https://badgen.net/badge/Lokalise/EN/green?icon=libraries)](https://app.lokalise.com/public/379418475ede5d5c6937b0.31012044/) diff --git a/components/clean.input.ts b/components/clean.input.ts index d9aa1af..7771a15 100644 --- a/components/clean.input.ts +++ b/components/clean.input.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ const omitDeepArrayWalk = (arr, key) => { return arr.map((val) => { if (Array.isArray(val)) return omitDeepArrayWalk(val, key) @@ -6,16 +7,11 @@ const omitDeepArrayWalk = (arr, key) => { }) } -// eslint-disable-next-line @typescript-eslint/no-explicit-any const omitDeep = (obj: any, key: string | number): any => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any const keys: Array = Object.keys(obj) - // eslint-disable-next-line @typescript-eslint/no-explicit-any const newObj: any = {} - // eslint-disable-next-line @typescript-eslint/no-explicit-any keys.forEach((i: any) => { if (i !== key) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any const val: any = obj[i] if (val instanceof Date) newObj[i] = val else if (Array.isArray(val)) newObj[i] = omitDeepArrayWalk(val, key) diff --git a/components/form/admin/field.card.tsx b/components/form/admin/field.card.tsx index 2138fc5..be5c2c3 100644 --- a/components/form/admin/field.card.tsx +++ b/components/form/admin/field.card.tsx @@ -21,10 +21,10 @@ export const FieldCard: React.FC = (props) => { const { t } = useTranslation() const { form, field, fields, onChangeFields, remove, index } = props - const type = form.getFieldValue(['form', 'fields', field.name as string, 'type']) + const type = form.getFieldValue(['form', 'fields', field.name as string, 'type']) as string const TypeComponent = adminTypes[type] || TextType - const [nextTitle, setNextTitle] = useState( + const [nextTitle, setNextTitle] = useState( form.getFieldValue(['form', 'fields', field.name as string, 'title']) ) diff --git a/components/form/admin/fields.tab.tsx b/components/form/admin/fields.tab.tsx index 31ad96d..ad6666b 100644 --- a/components/form/admin/fields.tab.tsx +++ b/components/form/admin/fields.tab.tsx @@ -2,6 +2,7 @@ import { PlusOutlined } from '@ant-design/icons/lib' import { Button, Form, Select, Space, Tabs } from 'antd' import { FormInstance } from 'antd/lib/form' import { TabPaneProps } from 'antd/lib/tabs' +import { FieldData } from 'rc-field-form/lib/interface' import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { AdminFormFieldFragment } from '../../../graphql/fragment/admin.form.fragment' @@ -19,7 +20,7 @@ export const FieldsTab: React.FC = (props) => { const [nextType, setNextType] = useState('textfield') const renderType = useCallback( - (field, index, remove) => { + (field: FieldData, index: number, remove: (index: number) => void) => { return ( = (props) => { ) const addField = useCallback( - (add, index) => { + (add: (defaults: unknown) => void, index: number) => { return ( = (props) => { const [enabled, setEnabled] = useState() useEffect(() => { - const next = props.form.getFieldValue(['form', 'respondentNotifications', 'enabled']) + const next = props.form.getFieldValue(['form', 'respondentNotifications', 'enabled']) as boolean if (next !== enabled) { setEnabled(next) @@ -24,14 +24,18 @@ export const RespondentNotificationsTab: React.FC = (props) => { }, [props.form.getFieldValue(['form', 'respondentNotifications', 'enabled'])]) useEffect(() => { - props.form.validateFields([ - ['form', 'respondentNotifications', 'subject'], - ['form', 'respondentNotifications', 'htmlTemplate'], - ['form', 'respondentNotifications', 'toField'], - ]) + props.form + .validateFields([ + ['form', 'respondentNotifications', 'subject'], + ['form', 'respondentNotifications', 'htmlTemplate'], + ['form', 'respondentNotifications', 'toField'], + ]) + .catch((e: Error) => console.error('failed to validate fields', e)) }, [enabled]) - const groups = {} + const groups: { + [key: string]: AdminFormFieldFragment[] + } = {} props.fields.forEach((field) => { if (!groups[field.type]) { diff --git a/components/form/admin/self.notifications.tab.tsx b/components/form/admin/self.notifications.tab.tsx index 3facebe..aac4938 100644 --- a/components/form/admin/self.notifications.tab.tsx +++ b/components/form/admin/self.notifications.tab.tsx @@ -16,7 +16,7 @@ export const SelfNotificationsTab: React.FC = (props) => { const [enabled, setEnabled] = useState() useEffect(() => { - const next = props.form.getFieldValue(['form', 'selfNotifications', 'enabled']) + const next = props.form.getFieldValue(['form', 'selfNotifications', 'enabled']) as boolean if (next !== enabled) { setEnabled(next) @@ -24,13 +24,17 @@ export const SelfNotificationsTab: React.FC = (props) => { }, [props.form.getFieldValue(['form', 'selfNotifications', 'enabled'])]) useEffect(() => { - props.form.validateFields([ - ['form', 'selfNotifications', 'subject'], - ['form', 'selfNotifications', 'htmlTemplate'], - ]) + props.form + .validateFields([ + ['form', 'selfNotifications', 'subject'], + ['form', 'selfNotifications', 'htmlTemplate'], + ]) + .catch((e: Error) => console.error('failed to validate', e)) }, [enabled]) - const groups = {} + const groups: { + [key: string]: AdminFormFieldFragment[] + } = {} props.fields.forEach((field) => { if (!groups[field.type]) { groups[field.type] = [] diff --git a/components/form/admin/submission.values.tsx b/components/form/admin/submission.values.tsx index 3545821..83bc6d8 100644 --- a/components/form/admin/submission.values.tsx +++ b/components/form/admin/submission.values.tsx @@ -19,7 +19,7 @@ export const SubmissionValues: React.FC = (props) => { const columns: ColumnsType = [ { title: t('submission:field'), - render: (row: AdminPagerSubmissionEntryFieldQueryData) => { + render(row: AdminPagerSubmissionEntryFieldQueryData) { if (row.field) { return `${row.field.title}${row.field.required ? '*' : ''}` } @@ -29,9 +29,9 @@ export const SubmissionValues: React.FC = (props) => { }, { title: t('submission:value'), - render: (row) => { + render(row: AdminPagerSubmissionEntryFieldQueryData) { try { - const data = JSON.parse(row.value) + const data = JSON.parse(row.value) as { value: string } return data.value } catch (e) { diff --git a/components/form/admin/types/date.type.tsx b/components/form/admin/types/date.type.tsx index 4b94146..d082edf 100644 --- a/components/form/admin/types/date.type.tsx +++ b/components/form/admin/types/date.type.tsx @@ -1,5 +1,5 @@ import { DatePicker, Form } from 'antd' -import moment from 'moment' +import moment, { Moment } from 'moment' import React from 'react' import { useTranslation } from 'react-i18next' import { AdminFieldTypeProps } from './type.props' @@ -11,29 +11,29 @@ export const DateType: React.FC = ({ field }) => {
(e ? e.format('YYYY-MM-DD') : undefined)} - getValueProps={(e) => ({ value: e ? moment(e) : undefined })} + getValueFromEvent={(e: Moment) => (e ? e.format('YYYY-MM-DD') : undefined)} + getValueProps={(e: string) => ({ value: e ? moment(e) : undefined })} > e.format('YYYY-MM-DD')} - getValueProps={(e) => ({ value: e ? moment(e) : undefined })} + getValueFromEvent={(e: Moment) => e.format('YYYY-MM-DD')} + getValueProps={(e: string) => ({ value: e ? moment(e) : undefined })} > e.format('YYYY-MM-DD')} - getValueProps={(e) => ({ value: e ? moment(e) : undefined })} + getValueFromEvent={(e: Moment) => e.format('YYYY-MM-DD')} + getValueProps={(e: string) => ({ value: e ? moment(e) : undefined })} > diff --git a/components/form/admin/types/dropdown.type.tsx b/components/form/admin/types/dropdown.type.tsx index 2930532..5a29b34 100644 --- a/components/form/admin/types/dropdown.type.tsx +++ b/components/form/admin/types/dropdown.type.tsx @@ -10,13 +10,13 @@ export const DropdownType: React.FC = (props) => {
- + {(fields, { add, remove }) => { return (
diff --git a/components/form/admin/types/email.type.tsx b/components/form/admin/types/email.type.tsx index 58458c2..752c105 100644 --- a/components/form/admin/types/email.type.tsx +++ b/components/form/admin/types/email.type.tsx @@ -10,7 +10,7 @@ export const EmailType: React.FC = (props) => {
diff --git a/components/form/admin/types/hidden.type.tsx b/components/form/admin/types/hidden.type.tsx index 0ddcc85..4fdb71b 100644 --- a/components/form/admin/types/hidden.type.tsx +++ b/components/form/admin/types/hidden.type.tsx @@ -10,7 +10,7 @@ export const HiddenType: React.FC = (props) => {
diff --git a/components/form/admin/types/link.type.tsx b/components/form/admin/types/link.type.tsx index 5d073ce..77dee7f 100644 --- a/components/form/admin/types/link.type.tsx +++ b/components/form/admin/types/link.type.tsx @@ -10,7 +10,7 @@ export const LinkType: React.FC = (props) => {
diff --git a/components/form/admin/types/number.type.tsx b/components/form/admin/types/number.type.tsx index fb8d806..2903306 100644 --- a/components/form/admin/types/number.type.tsx +++ b/components/form/admin/types/number.type.tsx @@ -10,7 +10,7 @@ export const NumberType: React.FC = (props) => {
diff --git a/components/form/admin/types/radio.type.tsx b/components/form/admin/types/radio.type.tsx index 76d7ea9..7f0b93a 100644 --- a/components/form/admin/types/radio.type.tsx +++ b/components/form/admin/types/radio.type.tsx @@ -10,13 +10,13 @@ export const RadioType: React.FC = (props) => {
- + {(fields, { add, remove }) => { return (
diff --git a/components/form/admin/types/rating.type.tsx b/components/form/admin/types/rating.type.tsx index 8ff8f94..e21f3c5 100644 --- a/components/form/admin/types/rating.type.tsx +++ b/components/form/admin/types/rating.type.tsx @@ -11,7 +11,7 @@ export const RatingType: React.FC = (props) => {
diff --git a/components/form/admin/types/text.type.tsx b/components/form/admin/types/text.type.tsx index 0d34da0..da8fd05 100644 --- a/components/form/admin/types/text.type.tsx +++ b/components/form/admin/types/text.type.tsx @@ -9,7 +9,7 @@ export const TextType: React.FC = (props) => { return ( diff --git a/components/form/admin/types/textarea.type.tsx b/components/form/admin/types/textarea.type.tsx index 8378a3f..5e63c0f 100644 --- a/components/form/admin/types/textarea.type.tsx +++ b/components/form/admin/types/textarea.type.tsx @@ -10,7 +10,7 @@ export const TextareaType: React.FC = (props) => {
diff --git a/components/form/admin/types/type.props.ts b/components/form/admin/types/type.props.ts index 43c7ccd..e86e5b9 100644 --- a/components/form/admin/types/type.props.ts +++ b/components/form/admin/types/type.props.ts @@ -1,6 +1,7 @@ import { FormInstance } from 'antd/lib/form' +import { FieldData } from 'rc-field-form/lib/interface' export interface AdminFieldTypeProps { form: FormInstance - field: { name: string } + field: FieldData } diff --git a/components/form/admin/types/yes_no.type.tsx b/components/form/admin/types/yes_no.type.tsx index 3083405..e5cddcc 100644 --- a/components/form/admin/types/yes_no.type.tsx +++ b/components/form/admin/types/yes_no.type.tsx @@ -11,7 +11,7 @@ export const YesNoType: React.FC = (props) => {
diff --git a/components/form/field.tsx b/components/form/field.tsx index 73be4a2..7bf4ebe 100644 --- a/components/form/field.tsx +++ b/components/form/field.tsx @@ -30,8 +30,8 @@ export const Field: React.FC = ({ field, save, design, next, prev, ...pro next() } - const error = () => { - message.error('Check inputs!') + const error = async () => { + await message.error('Check inputs!') } return ( diff --git a/components/form/types/date.type.tsx b/components/form/types/date.type.tsx index f58620a..e8e82de 100644 --- a/components/form/types/date.type.tsx +++ b/components/form/types/date.type.tsx @@ -25,8 +25,8 @@ export const DateType: React.FC = ({ field, design }) => { e.format('YYYY-MM-DD')} - getValueProps={(e) => ({ value: e ? moment(e) : undefined })} + getValueFromEvent={(e: Moment) => e.format('YYYY-MM-DD')} + getValueProps={(e: string) => ({ value: e ? moment(e) : undefined })} initialValue={field.value ? moment(field.value) : undefined} > = (props) => { triangle={'hide'} width={'100%'} color={props.value} - onChange={(e) => props.onChange(e.hex)} + onChange={(e: { hex: string }) => props.onChange(e.hex)} styles={{ default: { card: { diff --git a/components/structure.tsx b/components/structure.tsx index ba0cb02..afad61f 100644 --- a/components/structure.tsx +++ b/components/structure.tsx @@ -105,9 +105,9 @@ const Structure: FunctionComponent = (props) => { return ( { + onClick={async () => { if (element.href) { - router.push(element.href) + await router.push(element.href) } }} key={element.key} @@ -120,8 +120,8 @@ const Structure: FunctionComponent = (props) => { ) } - const signOut = async (): Promise => { - await clearAuth() + const signOut = (): void => { + clearAuth() router.reload() } @@ -147,7 +147,7 @@ const Structure: FunctionComponent = (props) => { })} {'OhMyForm'} props.background}; - color: ${(props) => props.color}; - border-color: ${(props) => darken(props.background, 10)}; + background: ${(props: Props) => props.background}; + color: ${(props: Props) => props.color}; + border-color: ${(props: Props) => darken(props.background, 10)}; :hover { - color: ${(props) => props.highlight}; - background-color: ${(props) => lighten(props.background, 10)}; - border-color: ${(props) => darken(props.highlight, 10)}; + color: ${(props: Props) => props.highlight}; + background-color: ${(props: Props) => lighten(props.background, 10)}; + border-color: ${(props: Props) => darken(props.highlight, 10)}; } ` diff --git a/components/styled/color.change.ts b/components/styled/color.change.ts index af4d1b5..c1846a7 100644 --- a/components/styled/color.change.ts +++ b/components/styled/color.change.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ /** * @link https://css-tricks.com/snippets/javascript/lighten-darken-color/ * diff --git a/components/styled/date.input.tsx b/components/styled/date.input.tsx index 7bcbea2..6be59f4 100644 --- a/components/styled/date.input.tsx +++ b/components/styled/date.input.tsx @@ -8,9 +8,10 @@ import { transparentize } from './color.change' type Props = { design: FormDesignFragment } & PickerProps +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(DatePicker)` - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; background: none !important; border-right: none; border-top: none; @@ -20,7 +21,7 @@ const Field = styled(DatePicker)` :hover, :active { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } &.ant-picker { @@ -32,15 +33,15 @@ const Field = styled(DatePicker)` } input { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; ::placeholder { - color: ${(props) => transparentize(props.design.colors.answerColor, 60)}; + color: ${(props: Props) => transparentize(props.design.colors.answerColor, 60)}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/styled/h1.tsx b/components/styled/h1.tsx index 373816a..762859c 100644 --- a/components/styled/h1.tsx +++ b/components/styled/h1.tsx @@ -8,7 +8,7 @@ interface Props { } const Header = styled.h1` - color: ${(props) => + color: ${(props: Props) => props.type === 'question' ? props.design.colors.questionColor : props.design.colors.answerColor}; diff --git a/components/styled/h2.tsx b/components/styled/h2.tsx index d907309..67e4225 100644 --- a/components/styled/h2.tsx +++ b/components/styled/h2.tsx @@ -7,7 +7,7 @@ interface Props { design: FormDesignFragment } const Header = styled.h2` - color: ${(props) => + color: ${(props: Props) => props.type === 'question' ? props.design.colors.questionColor : props.design.colors.answerColor}; diff --git a/components/styled/input.tsx b/components/styled/input.tsx index 760a437..26c91b5 100644 --- a/components/styled/input.tsx +++ b/components/styled/input.tsx @@ -9,9 +9,10 @@ interface Props extends InputProps { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(Input)` - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; background: none !important; border-right: none; border-top: none; @@ -19,12 +20,12 @@ const Field = styled(Input)` border-radius: 0; :focus { - outline: ${(props) => props.design.colors.answerColor} auto 5px; + outline: ${(props: Props) => props.design.colors.answerColor} auto 5px; } :hover, :active { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } &.ant-input-affix-wrapper { @@ -33,15 +34,15 @@ const Field = styled(Input)` input { background: none !important; - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; ::placeholder { - color: ${(props) => transparentize(props.design.colors.answerColor, 60)}; + color: ${(props: Props) => transparentize(props.design.colors.answerColor, 60)}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/styled/number.input.tsx b/components/styled/number.input.tsx index cf29d17..5978875 100644 --- a/components/styled/number.input.tsx +++ b/components/styled/number.input.tsx @@ -9,9 +9,10 @@ interface Props extends InputNumberProps { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(InputNumber)` - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; background: none !important; border-right: none; border-top: none; @@ -20,12 +21,12 @@ const Field = styled(InputNumber)` width: 100%; :focus { - outline: ${(props) => props.design.colors.answerColor} auto 5px; + outline: ${(props: Props) => props.design.colors.answerColor} auto 5px; } :hover, :active { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } &.ant-input-number { @@ -34,15 +35,15 @@ const Field = styled(InputNumber)` input { background: none !important; - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; ::placeholder { - color: ${(props) => transparentize(props.design.colors.answerColor, 60)}; + color: ${(props: Props) => transparentize(props.design.colors.answerColor, 60)}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/styled/p.tsx b/components/styled/p.tsx index 7c00886..ada074d 100644 --- a/components/styled/p.tsx +++ b/components/styled/p.tsx @@ -7,8 +7,9 @@ interface Props { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment const Paragraph = styled.p` - color: ${(props) => + color: ${(props: Props) => props.type === 'question' ? props.design.colors.questionColor : props.design.colors.answerColor}; diff --git a/components/styled/radio.tsx b/components/styled/radio.tsx index 127df40..0c1c510 100644 --- a/components/styled/radio.tsx +++ b/components/styled/radio.tsx @@ -8,27 +8,28 @@ interface Props extends RadioProps { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(Radio)` - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; background: none; .ant-radio { .ant-radio-inner { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; &::after { - background: ${(props) => props.design.colors.answerColor}; + background: ${(props: Props) => props.design.colors.answerColor}; } } &::after { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/styled/select.tsx b/components/styled/select.tsx index 4d39606..fb57a45 100644 --- a/components/styled/select.tsx +++ b/components/styled/select.tsx @@ -9,10 +9,11 @@ interface Props extends SelectProps { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(Select)` .ant-select-selector { - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor} !important; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor} !important; background: none !important; border-right: none !important; border-top: none !important; @@ -22,25 +23,25 @@ const Field = styled(Select)` } :focus { - outline: ${(props) => props.design.colors.answerColor} auto 5px; + outline: ${(props: Props) => props.design.colors.answerColor} auto 5px; } :hover, :active { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } input { background: none !important; - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; ::placeholder { - color: ${(props) => transparentize(props.design.colors.answerColor, 60)}; + color: ${(props: Props) => transparentize(props.design.colors.answerColor, 60)}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/styled/textarea.input.tsx b/components/styled/textarea.input.tsx index 15b0c15..577b467 100644 --- a/components/styled/textarea.input.tsx +++ b/components/styled/textarea.input.tsx @@ -9,9 +9,10 @@ interface Props extends TextAreaProps { design: FormDesignFragment } +// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment const Field = styled(Input.TextArea)` - color: ${(props) => props.design.colors.answerColor}; - border-color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; background: none !important; border-right: none; border-top: none; @@ -21,25 +22,25 @@ const Field = styled(Input.TextArea)` :focus { outline: none; box-shadow: none; - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } :hover, :active { - border-color: ${(props) => props.design.colors.answerColor}; + border-color: ${(props: Props) => props.design.colors.answerColor}; } input { background: none !important; - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; ::placeholder { - color: ${(props) => transparentize(props.design.colors.answerColor, 60)}; + color: ${(props: Props) => transparentize(props.design.colors.answerColor, 60)}; } } .anticon { - color: ${(props) => props.design.colors.answerColor}; + color: ${(props: Props) => props.design.colors.answerColor}; } ` diff --git a/components/use.submission.ts b/components/use.submission.ts index 523778d..5f15f5a 100644 --- a/components/use.submission.ts +++ b/components/use.submission.ts @@ -13,7 +13,7 @@ import { interface Submission { // eslint-disable-next-line @typescript-eslint/no-explicit-any - setField: (fieldId: string, data: any) => Promise + setField: (fieldId: string, data: unknown) => Promise finish: () => void } @@ -28,27 +28,28 @@ export const useSubmission = (formId: string): Submission => { ) useEffect(() => { - ;(async () => { - const token = [...Array(40)].map(() => Math.random().toString(36)[2]).join('') + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const token = [...Array(40)].map(() => Math.random().toString(36)[2]).join('') - const { data } = await start({ - variables: { - form: formId, - submission: { - token, - device: { - name: /Mobi/i.test(window.navigator.userAgent) ? 'mobile' : 'desktop', - type: window.navigator.userAgent, - }, + start({ + variables: { + form: formId, + submission: { + token, + device: { + name: /Mobi/i.test(window.navigator.userAgent) ? 'mobile' : 'desktop', + type: window.navigator.userAgent, }, }, + }, + }) + .then(({ data }) => { + setSubmission({ + id: data.submission.id, + token, + }) }) - - setSubmission({ - id: data.submission.id, - token, - }) - })() + .catch((e: Error) => console.error('failed to start submission', e)) }, [formId]) const setField = useCallback( diff --git a/components/user/admin/base.data.tab.tsx b/components/user/admin/base.data.tab.tsx index 26d88e4..44f7477 100644 --- a/components/user/admin/base.data.tab.tsx +++ b/components/user/admin/base.data.tab.tsx @@ -55,7 +55,7 @@ export const BaseDataTab: React.FC = (props) => { return ['user'] } }} - getValueProps={(v) => { + getValueProps={(v: string[]) => { let role = 'user' if (v && v.includes('superuser')) { diff --git a/components/user/role.tsx b/components/user/role.tsx index a5c9737..7348320 100644 --- a/components/user/role.tsx +++ b/components/user/role.tsx @@ -6,7 +6,7 @@ interface Props { } export const UserRole: React.FC = (props) => { - let color + let color: string let level = 'unknown' const css: CSSProperties = {} diff --git a/components/with.auth.tsx b/components/with.auth.tsx index 86d9d7a..600b4b7 100644 --- a/components/with.auth.tsx +++ b/components/with.auth.tsx @@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next' import { ME_QUERY, MeQueryData } from '../graphql/query/me.query' import { LoadingPage } from './loading.page' -export const clearAuth = async (): Promise => { +export const clearAuth = (): void => { localStorage.removeItem('access') localStorage.removeItem('refresh') @@ -18,7 +18,7 @@ export const setAuth = (access: string, refresh: string): void => { localStorage.setItem('refresh', refresh) } -export const authConfig = async (config: AxiosRequestConfig = {}): Promise => { +export const authConfig = (config: AxiosRequestConfig = {}): AxiosRequestConfig => { if (!config.headers) { config.headers = {} } @@ -28,6 +28,7 @@ export const authConfig = async (config: AxiosRequestConfig = {}): Promise { const path = router.asPath || router.pathname localStorage.setItem('redirect', path) - router.push('/login') + router.push('/login').catch((e: Error) => console.error('failed to redirect to login', e)) }, [error]) useEffect(() => { @@ -74,7 +75,7 @@ export const withAuth = (Component: any, roles: string[] = []): React.FC => { setAccess(next) if (!next) { - router.push('/') + router.push('/').catch((e: Error) => console.error('failed to redirect to /', e)) } }, [data]) diff --git a/graphql/mutation/login.mutation.ts b/graphql/mutation/login.mutation.ts index 809a70b..4f86476 100644 --- a/graphql/mutation/login.mutation.ts +++ b/graphql/mutation/login.mutation.ts @@ -1,5 +1,17 @@ import { gql } from 'apollo-boost' +export interface LoginMutationData { + tokens: { + access: string + refresh: string + } +} + +export interface LoginMutationVariables { + username: string + password: string +} + export const LOGIN_MUTATION = gql` mutation login($username: String!, $password: String!) { tokens: authLogin(username: $username, password: $password) { diff --git a/graphql/mutation/register.mutation.ts b/graphql/mutation/register.mutation.ts index 153cb67..40c7580 100644 --- a/graphql/mutation/register.mutation.ts +++ b/graphql/mutation/register.mutation.ts @@ -1,5 +1,22 @@ import { gql } from 'apollo-boost' +export interface RegisterMutationData { + tokens: { + access: string + refresh: string + } +} + +export interface RegisterUserData { + username: string + email: string + password: string +} + +export interface RegisterMutationVariables { + user: RegisterUserData +} + export const REGISTER_MUTATION = gql` mutation register($user: UserCreateInput!) { tokens: authRegister(user: $user) { diff --git a/graphql/query/admin.pager.form.query.ts b/graphql/query/admin.pager.form.query.ts index 43768a1..e75dd2d 100644 --- a/graphql/query/admin.pager.form.query.ts +++ b/graphql/query/admin.pager.form.query.ts @@ -1,5 +1,11 @@ import { gql } from 'apollo-boost' +export interface AdminPagerFormEntryAdminQueryData { + id: string + email: string + username: string +} + export interface AdminPagerFormEntryQueryData { id: string created: string @@ -7,11 +13,7 @@ export interface AdminPagerFormEntryQueryData { title: string isLive: boolean language: string - admin: { - id: string - email: string - username: string - } + admin: AdminPagerFormEntryAdminQueryData } export interface AdminPagerFormQueryData { diff --git a/package.json b/package.json index 9769af3..37f26dd 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "@ant-design/icons": "^4.1.0", "@apollo/react-hooks": "^3.1.5", "@lifeomic/axios-fetch": "^1.4.2", - "@types/swiper": "^5.3.1", "antd": "^4.2.2", "apollo-boost": "^0.4.9", "axios": "^0.19.2", @@ -42,8 +41,13 @@ "swiper": "^5.4.1" }, "devDependencies": { + "@types/axios": "^0.14.0", + "@types/lifeomic__axios-fetch": "^1.4.0", "@types/node": "^14.0.1", + "@types/node-fetch": "^2.5.7", "@types/react": "^16.9.35", + "@types/styled-components": "^5.1.0", + "@types/swiper": "^5.3.1", "@typescript-eslint/eslint-plugin": "^3.2.0", "@typescript-eslint/parser": "^3.2.0", "commander": "^5.1.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index d3386e2..1129208 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -13,13 +13,18 @@ import Head from 'next/head' import React from 'react' import { wrapper } from 'store' -const { publicRuntimeConfig } = getConfig() +const { publicRuntimeConfig } = getConfig() as { + publicRuntimeConfig: { + endpoint: string + } +} const client = new ApolloClient({ uri: publicRuntimeConfig.endpoint, - fetch: buildAxiosFetch(axios), - request: async (operation): Promise => { - operation.setContext(await authConfig()) + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-explicit-any + fetch: buildAxiosFetch(axios) as any, + request: (operation): void => { + operation.setContext(authConfig()) }, }) diff --git a/pages/admin/forms/[id]/index.tsx b/pages/admin/forms/[id]/index.tsx index b047ddc..007f193 100644 --- a/pages/admin/forms/[id]/index.tsx +++ b/pages/admin/forms/[id]/index.tsx @@ -112,10 +112,10 @@ const Index: NextPage = () => { form.setFieldsValue(next) setFields(next.form.fields) - message.success(t('form:updated')) + await message.success(t('form:updated')) } catch (e) { console.error('failed to save', e) - message.error(t('form:updateError')) + await message.error(t('form:updateError')) } setSaving(false) @@ -134,7 +134,7 @@ const Index: NextPage = () => { , @@ -147,9 +147,9 @@ const Index: NextPage = () => {
{ + onFinishFailed={async () => { // TODO process errors - message.error(t('validation:mandatoryFieldsMissing')) + await message.error(t('validation:mandatoryFieldsMissing')) }} labelCol={{ xs: { span: 24 }, diff --git a/pages/admin/forms/[id]/submissions.tsx b/pages/admin/forms/[id]/submissions.tsx index 4abd639..feaf499 100644 --- a/pages/admin/forms/[id]/submissions.tsx +++ b/pages/admin/forms/[id]/submissions.tsx @@ -70,14 +70,14 @@ const Submissions: NextPage = () => { { title: t('submission:created'), dataIndex: 'created', - render(date) { + render(date: string) { return }, }, { title: t('submission:lastModified'), dataIndex: 'lastModified', - render(date) { + render(date: string) { return }, }, @@ -94,15 +94,24 @@ const Submissions: NextPage = () => { { href: '/admin/forms/[id]', name: loading || !form ? t('form:loading') : t('form:mange', { title: form.title }), - as: `/admin/forms/${router.query.id}`, + as: `/admin/forms/${router.query.id as string}`, }, ]} padded={false} extra={[ - + , - , ]} @@ -120,9 +129,9 @@ const Submissions: NextPage = () => { return record.percentageComplete > 0 }, }} - onChange={(next) => { + onChange={async (next) => { setPagination(next) - refetch() + await refetch() }} /> diff --git a/pages/admin/forms/create.tsx b/pages/admin/forms/create.tsx index a11da9e..c36ccda 100644 --- a/pages/admin/forms/create.tsx +++ b/pages/admin/forms/create.tsx @@ -35,12 +35,12 @@ const Create: NextPage = () => { }) ).data - message.success(t('form:created')) + await message.success(t('form:created')) - router.replace('/admin/forms/[id]', `/admin/forms/${next.form.id}`) + await router.replace('/admin/forms/[id]', `/admin/forms/${next.form.id}`) } catch (e) { console.error('failed to save', e) - message.error(t('form:creationError')) + await message.error(t('form:creationError')) } setSaving(false) @@ -65,9 +65,9 @@ const Create: NextPage = () => { { + onFinishFailed={async () => { // TODO process errors - message.error(t('validation:mandatoryFieldsMissing')) + await message.error(t('validation:mandatoryFieldsMissing')) }} labelCol={{ xs: { span: 24 }, diff --git a/pages/admin/forms/index.tsx b/pages/admin/forms/index.tsx index 4103c83..1b3706e 100644 --- a/pages/admin/forms/index.tsx +++ b/pages/admin/forms/index.tsx @@ -15,6 +15,7 @@ import { TimeAgo } from 'components/time.ago' import { withAuth } from 'components/with.auth' import { ADMIN_PAGER_FORM_QUERY, + AdminPagerFormEntryAdminQueryData, AdminPagerFormEntryQueryData, AdminPagerFormQueryData, AdminPagerFormQueryVariables, @@ -56,7 +57,7 @@ const Index: NextPage = () => { AdminFormDeleteMutationVariables >(ADMIN_FORM_DELETE_MUTATION) - const deleteForm = async (form) => { + const deleteForm = async (form: AdminFormDeleteMutationVariables) => { try { await executeDelete({ variables: { @@ -70,9 +71,9 @@ const Index: NextPage = () => { setEntries(next) } - message.success(t('form:deleted')) + await message.success(t('form:deleted')) } catch (e) { - message.error(t('form:deleteError')) + await message.error(t('form:deleteError')) } } @@ -80,7 +81,7 @@ const Index: NextPage = () => { { title: t('form:row.isLive'), dataIndex: 'isLive', - render(live) { + render(live: boolean) { return }, }, @@ -91,7 +92,7 @@ const Index: NextPage = () => { { title: t('form:row.admin'), dataIndex: 'admin', - render(user) { + render(user: AdminPagerFormEntryAdminQueryData) { return ( @@ -104,28 +105,28 @@ const Index: NextPage = () => { { title: t('form:row.language'), dataIndex: 'language', - render(lang) { + render(lang: string) { return t(`language:${lang}`) }, }, { title: t('form:row.created'), dataIndex: 'created', - render(date) { + render(date: string) { return }, }, { title: t('form:row.lastModified'), dataIndex: 'lastModified', - render(date) { + render(date: string) { return }, }, { title: t('form:row.menu'), align: 'right', - render(row) { + render(row: AdminPagerFormEntryQueryData) { return ( @@ -182,9 +183,9 @@ const Index: NextPage = () => { dataSource={entries} rowKey={'id'} pagination={pagination} - onChange={(next) => { + onChange={async (next) => { setPagination(next) - refetch() + await refetch() }} /> diff --git a/pages/admin/profile.tsx b/pages/admin/profile.tsx index bf46fac..07334e0 100644 --- a/pages/admin/profile.tsx +++ b/pages/admin/profile.tsx @@ -49,10 +49,10 @@ const Profile: NextPage = () => { form.setFieldsValue(next) - message.success(t('profile:updated')) + await message.success(t('profile:updated')) } catch (e) { console.error('failed to save', e) - message.error(t('profile:updateError')) + await message.error(t('profile:updateError')) } setSaving(false) @@ -73,9 +73,9 @@ const Profile: NextPage = () => { { + onFinishFailed={async () => { // TODO process errors - message.error(t('validation:mandatoryFieldsMissing')) + await message.error(t('validation:mandatoryFieldsMissing')) }} labelCol={{ xs: { span: 24 }, diff --git a/pages/admin/users/[id]/index.tsx b/pages/admin/users/[id]/index.tsx index 3a86f96..aae8b11 100644 --- a/pages/admin/users/[id]/index.tsx +++ b/pages/admin/users/[id]/index.tsx @@ -53,10 +53,10 @@ const Index: NextPage = () => { form.setFieldsValue(next) - message.success(t('user:updated')) + await message.success(t('user:updated')) } catch (e) { console.error('failed to save', e) - message.error(t('user:updateError')) + await message.error(t('user:updateError')) } setSaving(false) @@ -81,9 +81,9 @@ const Index: NextPage = () => { { + onFinishFailed={async () => { // TODO process errors - message.error(t('validation:mandatoryFieldsMissing')) + await message.error(t('validation:mandatoryFieldsMissing')) }} labelCol={{ xs: { span: 24 }, diff --git a/pages/admin/users/index.tsx b/pages/admin/users/index.tsx index 882f1f9..d386d4e 100644 --- a/pages/admin/users/index.tsx +++ b/pages/admin/users/index.tsx @@ -50,7 +50,7 @@ const Index: NextPage = () => { AdminUserDeleteMutationVariables >(ADMIN_USER_DELETE_MUTATION) - const deleteUser = async (form) => { + const deleteUser = async (form: AdminPagerUserEntryQueryData) => { try { await executeDelete({ variables: { @@ -63,9 +63,9 @@ const Index: NextPage = () => { } else { setEntries(next) } - message.success(t('user:deleted')) + await message.success(t('user:deleted')) } catch (e) { - message.error(t('user:deleteError')) + await message.error(t('user:deleteError')) } } @@ -73,27 +73,27 @@ const Index: NextPage = () => { { title: t('user:row.roles'), dataIndex: 'roles', - render(roles) { + render(roles: string[]) { return }, }, { title: t('user:row.email'), - render(row) { + render(row: AdminPagerUserEntryQueryData) { return {row.email} }, }, { title: t('user:row.created'), dataIndex: 'created', - render(date) { + render(date: string) { return }, }, { title: t('user:row.menu'), align: 'right', - render(row) { + render(row: AdminPagerUserEntryQueryData) { return ( @@ -130,9 +130,9 @@ const Index: NextPage = () => { dataSource={entries} rowKey={'id'} pagination={pagination} - onChange={(next) => { + onChange={async (next) => { setPagination(next) - refetch() + await refetch() }} /> diff --git a/pages/form/[id]/index.tsx b/pages/form/[id]/index.tsx index 60c17cc..2b276e0 100644 --- a/pages/form/[id]/index.tsx +++ b/pages/form/[id]/index.tsx @@ -38,7 +38,9 @@ const Index: NextPage = () => { } if (i18n.language !== data.form.language) { - i18n.changeLanguage(data.form.language) + i18n + .changeLanguage(data.form.language) + .catch((e: Error) => console.error('failed to change language', e)) } }, [data]) @@ -98,8 +100,8 @@ const Index: NextPage = () => { key={field.id} field={field} design={design} - save={(values) => { - submission.setField(field.id, values[field.id]) + save={async (values: { [key: string]: unknown }) => { + await submission.setField(field.id, values[field.id]) if (data.form.fields.length === i + 1) { submission.finish() @@ -144,7 +146,7 @@ const Index: NextPage = () => { ) } -Index.getInitialProps = async ({ query }) => { +Index.getInitialProps = ({ query }) => { return { id: query.id as string, } diff --git a/pages/index.tsx b/pages/index.tsx index 88093ab..1fd8e56 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -7,7 +7,12 @@ import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { LoadingPage } from '../components/loading.page' -const { publicRuntimeConfig } = getConfig() +// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment +const { publicRuntimeConfig } = getConfig() as { + publicRuntimeConfig: { + spa: boolean + } +} const Index: NextPage = () => { const router = useRouter() @@ -17,14 +22,17 @@ const Index: NextPage = () => { if (router.pathname !== window.location.pathname) { let href = router.asPath const as = router.asPath + const possible = [/(\/form\/)[^/]+/i, /(\/admin\/forms\/)[^/]+/i, /(\/admin\/users\/)[^/]+/i] - ;[/(\/form\/)[^/]+/i, /(\/admin\/forms\/)[^/]+/i, /(\/admin\/users\/)[^/]+/i].forEach((r) => { + possible.forEach((r) => { if (r.test(as)) { href = href.replace(r, '$1[id]') } }) - router.replace(href, as) + router.replace(href, as).catch((e: Error) => { + console.error('failed redirect', e) + }) } }) @@ -50,7 +58,7 @@ const Index: NextPage = () => { width: 500, textAlign: 'center', }} - src={require('../assets/images/logo_white.png')} + src={require('../assets/images/logo_white.png') as string} /> diff --git a/pages/login/index.tsx b/pages/login/index.tsx index ba2ffb7..eacf39f 100644 --- a/pages/login/index.tsx +++ b/pages/login/index.tsx @@ -4,7 +4,11 @@ import { useForm } from 'antd/lib/form/Form' import { AuthFooter } from 'components/auth/footer' import { AuthLayout } from 'components/auth/layout' import { setAuth } from 'components/with.auth' -import { LOGIN_MUTATION } from 'graphql/mutation/login.mutation' +import { + LOGIN_MUTATION, + LoginMutationData, + LoginMutationVariables, +} from 'graphql/mutation/login.mutation' import { NextPage } from 'next' import Link from 'next/link' import { useRouter } from 'next/router' @@ -16,29 +20,29 @@ const Index: NextPage = () => { const [form] = useForm() const router = useRouter() const [loading, setLoading] = useState(false) - const [login] = useMutation(LOGIN_MUTATION) + const [login] = useMutation(LOGIN_MUTATION) - const finish = async (data) => { + const finish = async (data: LoginMutationVariables) => { setLoading(true) try { const result = await login({ variables: data, }) - await setAuth(result.data.tokens.access, result.data.tokens.refresh) + setAuth(result.data.tokens.access, result.data.tokens.refresh) - message.success(t('login:welcomeBack')) + await message.success(t('login:welcomeBack')) - router.push('/admin') + await router.push('/admin') } catch (e) { - message.error(t('login:invalidLoginCredentials')) + await message.error(t('login:invalidLoginCredentials')) } setLoading(false) } - const failed = () => { - message.error(t('validation:mandatoryFieldsMissing')) + const failed = async () => { + await message.error(t('validation:mandatoryFieldsMissing')) } return ( @@ -55,7 +59,7 @@ const Index: NextPage = () => { }} > {'OhMyForm'} { const [loading, setLoading] = useState(false) const { data } = useQuery(SETTINGS_QUERY) - const [register] = useMutation(REGISTER_MUTATION) + const [register] = useMutation(REGISTER_MUTATION) - const finish = async (data) => { + const finish = async (data: RegisterUserData) => { setLoading(true) try { @@ -32,19 +37,19 @@ const Register: NextPage = () => { }, }) - await setAuth(result.data.tokens.access, result.data.tokens.refresh) + setAuth(result.data.tokens.access, result.data.tokens.refresh) - message.success(t('register:welcome')) + await message.success(t('register:welcome')) - router.push('/') + await router.push('/') } catch (e) { - message.error(t('register:credentialsAlreadyInUse')) + await message.error(t('register:credentialsAlreadyInUse')) setLoading(false) } } - const failed = () => { - message.error(t('validation:mandatoryFieldsMissing')) + const failed = async () => { + await message.error(t('validation:mandatoryFieldsMissing')) } if (data && data.disabledSignUp.value) { @@ -65,7 +70,7 @@ const Register: NextPage = () => { }} > {'OhMyForm'} { +const root = (state: State, action: AnyAction): State => { switch (action.type) { case HYDRATE: - return { ...state, ...action.payload } + return { ...state, ...action.payload } as State } const combined = combineReducers({ diff --git a/yarn.lock b/yarn.lock index b974bc3..d67013b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1169,6 +1169,13 @@ resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-9.4.0.tgz#6f8732e1909fb12f6dca8a82b7fc4b79c6c8cfcd" integrity sha512-AaEC/diS2two2JLsEItGhuAux8UfPo0o34/7l1SIw0t4SYunUYJsxM/Y55OR2ljiVn9ffKR1n1U9IEQhsK80jw== +"@types/axios@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" + integrity sha1-7CMA++fX3d1+udOr+HmZlkyvzkY= + dependencies: + axios "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -1179,11 +1186,40 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@types/hoist-non-react-statics@*": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/lifeomic__axios-fetch@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@types/lifeomic__axios-fetch/-/lifeomic__axios-fetch-1.4.0.tgz#c3c6e6fd1af7507cbb992864891a809e1bc1d347" + integrity sha512-i6FGbhL840p71LxT4/6qq7LbWfpO1eMRFIfNAYEFqo3WkDI2O+BrJd7ac+FEBy818u+s6gGh5cqw6d1pmwJ3Dw== + dependencies: + "@types/node-fetch" "*" + axios "^0.19.0" + +"@types/node-fetch@*", "@types/node-fetch@^2.5.7": + version "2.5.7" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" + integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "14.0.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.12.tgz#9c1d8ffb8084e8936603a6122a7649e40e68e04b" + integrity sha512-/sjzehvjkkpvLpYtN6/2dv5kg41otMGuHQUt9T2aiAuIfleCQRQHXXzF1eAw/qkZTj5Kcf4JSTf7EIizHocy6Q== + "@types/node@>=6", "@types/node@^14.0.1": version "14.0.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.5.tgz#3d03acd3b3414cf67faf999aed11682ed121f22b" @@ -1199,7 +1235,14 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react@^16.9.35": +"@types/react-native@*": + version "0.62.13" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.13.tgz#c688c5ae03e426f927f7e1fa1a59cd067f35d1c2" + integrity sha512-hs4/tSABhcJx+J8pZhVoXHrOQD89WFmbs8QiDLNSA9zNrD46pityAuBWuwk1aMjPk9I3vC5ewkJroVRHgRIfdg== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.35": version "16.9.35" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368" integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ== @@ -1207,6 +1250,16 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/styled-components@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.0.tgz#24d3412ba5395aa06e14fbc93c52f9454cebd0d6" + integrity sha512-ZFlLCuwF5r+4Vb7JUmd+Yr2S0UBdBGmI7ctFTgJMypIp3xOHI4LCFVn2dKMvpk6xDB2hLRykrEWMBwJEpUAUIQ== + dependencies: + "@types/hoist-non-react-statics" "*" + "@types/react" "*" + "@types/react-native" "*" + csstype "^2.2.0" + "@types/swiper@^5.3.1": version "5.3.1" resolved "https://registry.yarnpkg.com/@types/swiper/-/swiper-5.3.1.tgz#cc0c7c6f84e330ff50bec0a3ed0d172751e9d1fc" @@ -1836,7 +1889,7 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -axios@^0.19.2: +axios@*, axios@^0.19.0, axios@^0.19.2: version "0.19.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== @@ -2411,7 +2464,7 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -combined-stream@^1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -3545,6 +3598,15 @@ form-data@^2.3.3: combined-stream "^1.0.6" mime-types "^2.1.12" +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"