From 97a9e1dc60cad8aabd75f4afbd540ac60a76cd81 Mon Sep 17 00:00:00 2001 From: Michael Schramm Date: Fri, 19 Jun 2020 11:34:25 +0200 Subject: [PATCH] add slug and fix missing admin error https://github.com/ohmyform/ohmyform/issues/100 --- CHANGELOG.md | 3 +++ components/form/admin/field.card.tsx | 24 ++++++++++++++++++++++-- components/form/field.tsx | 16 +++++++++++++++- components/form/types/date.type.tsx | 14 ++++++++++++-- components/form/types/dropdown.type.tsx | 4 ++-- components/form/types/email.type.tsx | 4 ++-- components/form/types/link.type.tsx | 4 ++-- components/form/types/number.type.tsx | 14 ++++++++++++-- components/form/types/radio.type.tsx | 14 ++++++++++++-- components/form/types/rating.type.tsx | 14 ++++++++++++-- components/form/types/text.type.tsx | 4 ++-- components/form/types/textarea.type.tsx | 4 ++-- components/form/types/type.props.ts | 1 + components/form/types/yes_no.type.tsx | 10 ++++++++-- graphql/fragment/admin.form.fragment.ts | 2 ++ graphql/fragment/form.fragment.ts | 2 ++ locales/en/type.json | 2 ++ locales/en/validation.json | 1 + 18 files changed, 114 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 958db1a..9366406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## UNRELEASED ### Added + +- slug for fields to be able to set value by url parameter + ### Changed - minify containers to reduce layer size diff --git a/components/form/admin/field.card.tsx b/components/form/admin/field.card.tsx index b961773..c3eba69 100644 --- a/components/form/admin/field.card.tsx +++ b/components/form/admin/field.card.tsx @@ -1,5 +1,5 @@ import { DeleteOutlined } from '@ant-design/icons/lib' -import { Button, Card, Checkbox, Form, Input, Popconfirm, Tag } from 'antd' +import { Button, Card, Checkbox, Form, Input, Popconfirm, Popover, Tag } from 'antd' import { FormInstance } from 'antd/lib/form' import { FieldData } from 'rc-field-form/lib/interface' import React, { useEffect, useState } from 'react' @@ -53,7 +53,27 @@ export const FieldCard: React.FC = (props) => { type={'inner'} extra={
- {t(`type:${type}.name`)} + + + + } + title={t('type:slug')} + > + {t(`type:${type}.name`)} + = ({ field, save, design, next, prev, ...props }) => { const [form] = useForm() + const router = useRouter() const FieldInput: React.FC = fieldTypes[field.type] || TextType @@ -34,6 +36,18 @@ export const Field: React.FC = ({ field, save, design, next, prev, ...pro await message.error('Check inputs!') } + const getUrlDefault = (): string => { + if (router.query[field.id]) { + return router.query[field.id] as string + } + + if (router.query[field.slug]) { + return router.query[field.slug] as string + } + + return undefined + } + return (
= ({ field, save, design, next, prev, ...pro )} - +
= ({ field, design }) => { +export const DateType: React.FC = ({ field, design, urlValue }) => { const [min, setMin] = useState() const [max, setMax] = useState() const { t } = useTranslation() @@ -22,6 +22,16 @@ export const DateType: React.FC = ({ field, design }) => { }) }, [field]) + let initialValue: Moment = undefined + + if (field.value) { + initialValue = moment(field.value) + } + + if (urlValue) { + initialValue = moment(field.value) + } + return (
= ({ field, design }) => { rules={[{ required: field.required, message: t('validation:valueRequired') }]} getValueFromEvent={(e: Moment) => e.format('YYYY-MM-DD')} getValueProps={(e: string) => ({ value: e ? moment(e) : undefined })} - initialValue={field.value ? moment(field.value) : undefined} + initialValue={initialValue} > = ({ field, design }) => { +export const DropdownType: React.FC = ({ field, design, urlValue }) => { const [open, setOpen] = useState(false) const { t } = useTranslation() @@ -13,7 +13,7 @@ export const DropdownType: React.FC = ({ field, design }) => { = ({ field, design }) => { +export const EmailType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() return ( @@ -15,7 +15,7 @@ export const EmailType: React.FC = ({ field, design }) => { { required: field.required, message: t('validation:valueRequired') }, { type: 'email', message: t('validation:invalidEmail') }, ]} - initialValue={field.value} + initialValue={urlValue || field.value} > diff --git a/components/form/types/link.type.tsx b/components/form/types/link.type.tsx index 1a58ede..8ff9e36 100644 --- a/components/form/types/link.type.tsx +++ b/components/form/types/link.type.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import { StyledInput } from '../../styled/input' import { FieldTypeProps } from './type.props' -export const LinkType: React.FC = ({ field, design }) => { +export const LinkType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() return ( @@ -15,7 +15,7 @@ export const LinkType: React.FC = ({ field, design }) => { { required: field.required, message: t('validation:valueRequired') }, { type: 'url', message: t('validation:invalidUrl') }, ]} - initialValue={field.value} + initialValue={urlValue || field.value} > diff --git a/components/form/types/number.type.tsx b/components/form/types/number.type.tsx index da95719..118791b 100644 --- a/components/form/types/number.type.tsx +++ b/components/form/types/number.type.tsx @@ -4,9 +4,19 @@ import { useTranslation } from 'react-i18next' import { StyledNumberInput } from '../../styled/number.input' import { FieldTypeProps } from './type.props' -export const NumberType: React.FC = ({ field, design }) => { +export const NumberType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() + let initialValue: number = undefined + + if (field.value) { + initialValue = parseFloat(field.value) + } + + if (urlValue) { + initialValue = parseFloat(urlValue) + } + return (
= ({ field, design }) => { { type: 'number', message: t('validation:invalidNumber') }, { required: field.required, message: t('validation:valueRequired') }, ]} - initialValue={typeof field.value === 'number' ? parseFloat(field.value) : undefined} + initialValue={initialValue} > diff --git a/components/form/types/radio.type.tsx b/components/form/types/radio.type.tsx index cb48203..f88746f 100644 --- a/components/form/types/radio.type.tsx +++ b/components/form/types/radio.type.tsx @@ -4,9 +4,19 @@ import { useTranslation } from 'react-i18next' import { StyledRadio } from '../../styled/radio' import { FieldTypeProps } from './type.props' -export const RadioType: React.FC = ({ field, design }) => { +export const RadioType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() + let initialValue: string = undefined + + if (field.value) { + initialValue = field.value + } + + if (urlValue) { + initialValue = urlValue + } + return (
= ({ field, design }) => { rules={[{ required: field.required, message: t('validation:valueRequired') }]} initialValue={field.options .map((option) => option.value) - .find((value) => value === field.value)} + .find((value) => value === initialValue)} > {field.options diff --git a/components/form/types/rating.type.tsx b/components/form/types/rating.type.tsx index 47de9c1..452395d 100644 --- a/components/form/types/rating.type.tsx +++ b/components/form/types/rating.type.tsx @@ -3,16 +3,26 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FieldTypeProps } from './type.props' -export const RatingType: React.FC = ({ field }) => { +export const RatingType: React.FC = ({ field, urlValue }) => { const { t } = useTranslation() // TODO add ratings + let initialValue: number = undefined + + if (field.value) { + initialValue = parseFloat(field.value) + } + + if (urlValue) { + initialValue = parseFloat(urlValue) + } + return (
diff --git a/components/form/types/text.type.tsx b/components/form/types/text.type.tsx index e8d7c77..5bc9933 100644 --- a/components/form/types/text.type.tsx +++ b/components/form/types/text.type.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import { StyledInput } from '../../styled/input' import { FieldTypeProps } from './type.props' -export const TextType: React.FC = ({ field, design }) => { +export const TextType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() // TODO focus when becomes visible @@ -13,7 +13,7 @@ export const TextType: React.FC = ({ field, design }) => { diff --git a/components/form/types/textarea.type.tsx b/components/form/types/textarea.type.tsx index b2e0370..86f492d 100644 --- a/components/form/types/textarea.type.tsx +++ b/components/form/types/textarea.type.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import { StyledTextareaInput } from '../../styled/textarea.input' import { FieldTypeProps } from './type.props' -export const TextareaType: React.FC = ({ field, design }) => { +export const TextareaType: React.FC = ({ field, design, urlValue }) => { const { t } = useTranslation() return ( @@ -12,7 +12,7 @@ export const TextareaType: React.FC = ({ field, design }) => { diff --git a/components/form/types/type.props.ts b/components/form/types/type.props.ts index 4ea16e9..172f8d9 100644 --- a/components/form/types/type.props.ts +++ b/components/form/types/type.props.ts @@ -3,4 +3,5 @@ import { FormDesignFragment, FormFieldFragment } from '../../../graphql/fragment export interface FieldTypeProps { field: FormFieldFragment design: FormDesignFragment + urlValue?: string } diff --git a/components/form/types/yes_no.type.tsx b/components/form/types/yes_no.type.tsx index 87f9188..10c78cf 100644 --- a/components/form/types/yes_no.type.tsx +++ b/components/form/types/yes_no.type.tsx @@ -3,15 +3,21 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FieldTypeProps } from './type.props' -export const YesNoType: React.FC = ({ field }) => { +export const YesNoType: React.FC = ({ field, urlValue }) => { const { t } = useTranslation() + let initialValue = !!field.value + + if (urlValue !== undefined) { + initialValue = !!urlValue + } + return (
(checked ? '1' : '')} getValueProps={(e: string) => ({ checked: !!e })} diff --git a/graphql/fragment/admin.form.fragment.ts b/graphql/fragment/admin.form.fragment.ts index 05aee4a..3f4ba95 100644 --- a/graphql/fragment/admin.form.fragment.ts +++ b/graphql/fragment/admin.form.fragment.ts @@ -35,6 +35,7 @@ export interface AdminFormFieldLogicJumpFragment { export interface AdminFormFieldFragment { id: string title: string + slug?: string type: string description: string required: boolean @@ -106,6 +107,7 @@ export const ADMIN_FORM_FRAGMENT = gql` fields { id title + slug type description required diff --git a/graphql/fragment/form.fragment.ts b/graphql/fragment/form.fragment.ts index 7905f81..fb5b1b9 100644 --- a/graphql/fragment/form.fragment.ts +++ b/graphql/fragment/form.fragment.ts @@ -32,6 +32,7 @@ export interface FormFieldLogicJumpFragment { export interface FormFieldFragment { id: string title: string + slug?: string type: string description: string required: boolean @@ -81,6 +82,7 @@ export const FORM_FRAGMENT = gql` fields { id title + slug type description required diff --git a/locales/en/type.json b/locales/en/type.json index ddf113d..4f7bc24 100644 --- a/locales/en/type.json +++ b/locales/en/type.json @@ -51,6 +51,8 @@ }, "required": "Required", "requiredInfo": "If required, default value must be set to enable users to submit form!", + "slug": "Slug", + "slugInfo": "Use slug to pass the default dynamic as url parameter ?slug=value", "textarea": { "default": "Default Value", "name": "Text Area" diff --git a/locales/en/validation.json b/locales/en/validation.json index c109e48..f297ee6 100644 --- a/locales/en/validation.json +++ b/locales/en/validation.json @@ -3,6 +3,7 @@ "emailRequired": "Please provide an Email", "invalidEmail": "Must be a valid email!", "invalidNumber": "Must be a valid number!", + "invalidSlug": "Slug can only contain lowercase a-z, 0-9 and _", "invalidUrl": "Must be a valid URL", "languageRequired": "Please select a Language", "mandatoryFieldsMissing": "Mandatory fields missing",