Skip to content

Commit

Permalink
Merge pull request #334 from IQSS/feature/316-create-functional-creat…
Browse files Browse the repository at this point in the history
…e-dataset-form

316 - Functional create dataset form
  • Loading branch information
GPortas authored Mar 28, 2024
2 parents 1ce4113 + 5b2343f commit 75fe4fb
Show file tree
Hide file tree
Showing 39 changed files with 1,086 additions and 200 deletions.
2 changes: 1 addition & 1 deletion dev-env/docker-compose-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ services:
DATAVERSE_DB_HOST: postgres
DATAVERSE_DB_PASSWORD: secret
DATAVERSE_DB_USER: ${DATAVERSE_DB_USER}
DATAVERSE_FEATURE_API_SESSION_AUTH: '1'
DATAVERSE_FEATURE_API_SESSION_AUTH: 1
JVM_ARGS: -Ddataverse.pid.providers=fake
-Ddataverse.pid.default-provider=fake
-Ddataverse.pid.fake.type=FAKE
Expand Down
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"dependencies": {
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "2.0.0-pr130.dbec86f",
"@iqss/dataverse-client-javascript": "2.0.0-pr132.dd49caf",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand All @@ -29,6 +29,7 @@
"i18next": "22.4.9",
"i18next-browser-languagedetector": "7.0.1",
"i18next-http-backend": "2.1.1",
"lodash": "^4.17.21",
"moment-timezone": "0.5.43",
"react-bootstrap": "2.7.2",
"react-bootstrap-icons": "1.10.3",
Expand Down
4 changes: 3 additions & 1 deletion packages/design-system/src/lib/components/form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FormGroup } from './form-group/FormGroup'
import { Form as FormBS } from 'react-bootstrap'
import { FormGroupWithMultipleFields } from './form-group-multiple-fields/FormGroupWithMultipleFields'
import { FormInputGroup } from './form-group/form-input-group/FormInputGroup'
import { FormCheckboxGroup } from './form-checkbox-group/FormCheckboxGroup'

interface FormProps {
className?: string
Expand All @@ -12,7 +13,7 @@ interface FormProps {

function Form({ validated, onSubmit, children, className }: PropsWithChildren<FormProps>) {
return (
<FormBS validated={validated} onSubmit={onSubmit} className={className}>
<FormBS validated={validated} onSubmit={onSubmit} className={className} noValidate={true}>
{children}
</FormBS>
)
Expand All @@ -21,5 +22,6 @@ function Form({ validated, onSubmit, children, className }: PropsWithChildren<Fo
Form.InputGroup = FormInputGroup
Form.Group = FormGroup
Form.GroupWithMultipleFields = FormGroupWithMultipleFields
Form.CheckboxGroup = FormCheckboxGroup

export { Form }
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@import "src/lib/assets/styles/design-tokens/typography.module";

.title {
padding-top: calc(0.375rem + 1px);
padding-bottom: calc(0.375rem + 1px);
font-weight: $dv-font-weight-bold;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Row } from '../../grid/Row'
import { Col } from '../../grid/Col'
import { PropsWithChildren } from 'react'
import styles from './FormCheckboxGroup.module.scss'
import { RequiredInputSymbol } from '../required-input-symbol/RequiredInputSymbol'
import { QuestionMarkTooltip } from '../../tooltip/question-mark-tooltip/QuestionMarkTooltip'

interface FormCheckboxGroupProps {
title: string
required?: boolean
message?: string
isValid?: boolean
isInvalid?: boolean
}

export function FormCheckboxGroup({
title,
required,
message,
isValid,
isInvalid,
children
}: PropsWithChildren<FormCheckboxGroupProps>) {
const validationClass = isInvalid ? 'is-invalid' : isValid ? 'is-valid' : ''
return (
<Row>
<Col sm={3}>
<span className={styles.title}>
{title} {required && <RequiredInputSymbol />}{' '}
{message && (
<QuestionMarkTooltip placement="right" message={message}></QuestionMarkTooltip>
)}
</span>
</Col>
<Col sm={9}>
{<div className={validationClass}></div>}
{children}
</Col>
</Row>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FormTextArea } from './form-element/FormTextArea'
import { Col, ColProps } from '../../grid/Col'
import { Row } from '../../grid/Row'
import { FormCheckbox } from './form-element/FormCheckbox'
import { FormFeedback } from './form-element/FormFeedback'

interface FormGroupProps extends ColProps {
as?: typeof Col | typeof Row
Expand Down Expand Up @@ -48,5 +49,6 @@ FormGroup.Select = FormSelect
FormGroup.TextArea = FormTextArea
FormGroup.Text = FormText
FormGroup.Checkbox = FormCheckbox
FormGroup.Feedback = FormFeedback

export { FormGroup }
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,27 @@ import * as React from 'react'
interface FormCheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
id: string
label: string
name: string
isValid?: boolean
isInvalid?: boolean
invalidFeedback?: string
validFeedback?: string
}

export function FormCheckbox({ label, name, id, ...props }: FormCheckboxProps) {
return <FormBS.Check label={label} name={name} type="checkbox" id={id} {...props} />
export function FormCheckbox({
label,
id,
isValid,
isInvalid,
validFeedback,
invalidFeedback,
...props
}: FormCheckboxProps) {
return (
<FormBS.Check type="checkbox" id={id}>
<FormBS.Check.Input type="checkbox" isValid={isValid} isInvalid={isInvalid} {...props} />
<FormBS.Check.Label>{label}</FormBS.Check.Label>
<FormBS.Control.Feedback type="invalid">{invalidFeedback}</FormBS.Control.Feedback>
<FormBS.Control.Feedback type="valid">{validFeedback}</FormBS.Control.Feedback>
</FormBS.Check>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@ import { Col } from '../../../grid/Col'

interface LayoutFormGroupElementProps {
withinMultipleFieldsGroup?: boolean
isValid?: boolean
isInvalid?: boolean
}
export function FormElementLayout({
withinMultipleFieldsGroup,
isValid,
isInvalid,
children
}: PropsWithChildren<LayoutFormGroupElementProps>) {
return withinMultipleFieldsGroup ? <>{children}</> : <Col sm={9}>{children}</Col>
const className = isInvalid ? 'is-invalid' : isValid ? 'is-valid' : ''
return withinMultipleFieldsGroup ? (
<>{children}</>
) : (
<Col sm={9} className={className}>
{children}
</Col>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FormControl } from 'react-bootstrap'
import { PropsWithChildren } from 'react'
import { Col } from '../../../grid/Col'

interface FormFeedbackProps {
type?: 'valid' | 'invalid'
withinMultipleFieldsGroup?: boolean
}

export function FormFeedback({
type = 'valid',
withinMultipleFieldsGroup,
children
}: PropsWithChildren<FormFeedbackProps>) {
return withinMultipleFieldsGroup ? (
<FormControl.Feedback type={type}>{children}</FormControl.Feedback>
) : (
<FormControl.Feedback as={Col} sm={{ offset: 3, span: 9 }} type={type}>
{children}
</FormControl.Feedback>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,36 @@ interface FormInputProps extends React.HTMLAttributes<FormInputElement> {
readOnly?: boolean
withinMultipleFieldsGroup?: boolean
name?: string
isValid?: boolean
isInvalid?: boolean
disabled?: boolean
}

export function FormInput({
type = 'text',
name,
readOnly,
isValid,
isInvalid,
disabled,
withinMultipleFieldsGroup,
...props
}: FormInputProps) {
return (
<FormElementLayout withinMultipleFieldsGroup={withinMultipleFieldsGroup}>
<FormBS.Control name={name} type={type} readOnly={readOnly} plaintext={readOnly} {...props} />
<FormElementLayout
withinMultipleFieldsGroup={withinMultipleFieldsGroup}
isInvalid={isInvalid}
isValid={isValid}>
<FormBS.Control
name={name}
type={type}
readOnly={readOnly}
plaintext={readOnly}
isValid={isValid}
isInvalid={isInvalid}
disabled={disabled}
{...props}
/>
</FormElementLayout>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,26 @@ import * as React from 'react'
export type FormInputElement = HTMLInputElement | HTMLTextAreaElement
interface FormTextAreaProps extends Omit<React.HTMLAttributes<FormInputElement>, 'rows'> {
withinMultipleFieldsGroup?: boolean
name?: string
disabled?: boolean
isValid?: boolean
isInvalid?: boolean
}

export function FormTextArea({ withinMultipleFieldsGroup, ...props }: FormTextAreaProps) {
export function FormTextArea({
name,
disabled,
isValid,
isInvalid,
withinMultipleFieldsGroup,
...props
}: FormTextAreaProps) {
return (
<FormElementLayout withinMultipleFieldsGroup={withinMultipleFieldsGroup}>
<FormBS.Control as="textarea" rows={5} {...props} />
<FormElementLayout
withinMultipleFieldsGroup={withinMultipleFieldsGroup}
isInvalid={isInvalid}
isValid={isValid}>
<FormBS.Control as="textarea" rows={5} disabled={disabled} name={name} {...props} />
</FormElementLayout>
)
}
18 changes: 15 additions & 3 deletions packages/design-system/src/lib/stories/form/Form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ export const ReadOnlyInput: Story = {
)
}

export const DisabledInput: Story = {
render: () => (
<Form>
<Form.Group controlId="basic-form-email">
<Form.Group.Label>Email</Form.Group.Label>
<Form.Group.Input type="email" disabled defaultValue="[email protected]" />
</Form.Group>
</Form>
)
}

export const InputWithPrefix: Story = {
render: () => (
<Form>
Expand Down Expand Up @@ -169,7 +180,7 @@ export const TextArea: Story = {
export const Checkbox: Story = {
render: () => (
<Form>
<Form.GroupWithMultipleFields title="Metadata Fields">
<Form.CheckboxGroup title="Metadata Fields">
<Form.Group.Checkbox
defaultChecked
name="metadata-field"
Expand All @@ -187,7 +198,7 @@ export const Checkbox: Story = {
label="Social Science and Humanities Metadata"
id="basic-form-social-science-metadata"
/>
</Form.GroupWithMultipleFields>
</Form.CheckboxGroup>
</Form>
)
}
Expand Down Expand Up @@ -254,11 +265,12 @@ export const FormValidation: Story = {
</Form.Group.Label>
<Form.Group.Input type="text" placeholder="Name" />
</Form.Group>
<Form.Group as={Col} controlId="basic-form-affiliation">
<Form.Group as={Col} controlId="basic-form-affiliation" required>
<Form.Group.Label message="The name of the entity affiliated with the author, e.g. an organization's name">
Affiliation
</Form.Group.Label>
<Form.Group.Input type="text" placeholder="Affiliation" />
<Form.Group.Feedback type="invalid">Please provide an affiliation</Form.Group.Feedback>
</Form.Group>
</Row>
<Row>
Expand Down
6 changes: 5 additions & 1 deletion packages/design-system/tests/component/form/Form.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ describe('Form', () => {
it('should call onSubmit when the form is submitted', () => {
const handleSubmit = cy.stub().as('handleSubmit')
cy.mount(
<Form onSubmit={handleSubmit}>
<Form
onSubmit={(e) => {
e.preventDefault()
handleSubmit()
}}>
<button type="submit">Submit Form</button>
</Form>
)
Expand Down
Loading

0 comments on commit 75fe4fb

Please sign in to comment.