Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce knowledge schema constraints in the UI #138

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import React from 'react';
import { FormFieldGroupExpandable, FormFieldGroupHeader, FormGroup } from '@patternfly/react-core/dist/dynamic/components/Form';
import { FormFieldGroupExpandable, FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form';
import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput';
import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon';
import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants';
import { KnowledgeFormData } from '..';
import { checkKnowledgeFormCompletion } from '../validation';

interface Props {
knowledgeFormData: KnowledgeFormData;
setDisableAction: React.Dispatch<React.SetStateAction<boolean>>;
titleWork: string;
setTitleWork: React.Dispatch<React.SetStateAction<string>>;
linkWork: string;
Expand All @@ -16,6 +24,8 @@ interface Props {
}

const AttributionInformation: React.FC<Props> = ({
knowledgeFormData,
setDisableAction,
titleWork,
setTitleWork,
linkWork,
Expand All @@ -27,12 +37,87 @@ const AttributionInformation: React.FC<Props> = ({
creators,
setCreators
}) => {
const [validTitle, setValidTitle] = React.useState<ValidatedOptions>();
const [validLink, setValidLink] = React.useState<ValidatedOptions>();
const [validRevision, setValidRevision] = React.useState<ValidatedOptions>();
const [validLicense, setValidLicense] = React.useState<ValidatedOptions>();
const [validCreators, setValidCreators] = React.useState<ValidatedOptions>();

const validateTitle = (title: string) => {
if (title.length > 0) {
setValidTitle(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidTitle(ValidatedOptions.error);
return;
};

const validateLink = (link: string) => {
if (link.length === 0) {
setDisableAction(true);
setValidLink(ValidatedOptions.error);
return;
}
try {
new URL(link);
setValidLink(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
} catch (e) {
setDisableAction(true);
setValidLink(ValidatedOptions.warning);
return;
}
};

const validateRevision = (revision: string) => {
if (revision.length > 0) {
setValidRevision(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidRevision(ValidatedOptions.error);
return;
};

const validateLicense = (license: string) => {
if (license.length > 0) {
setValidLicense(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidLicense(ValidatedOptions.error);
return;
};

const validateCreators = (creators: string) => {
if (creators.length > 0) {
setValidCreators(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidCreators(ValidatedOptions.error);
return;
};

return (
<FormFieldGroupExpandable
toggleAriaLabel="Details"
header={
<FormFieldGroupHeader
titleText={{ text: 'Attribution Info', id: 'attribution-info-id' }}
titleText={{
text: (
<p>
Attribution Info <span style={{ color: 'red' }}>*</span>
</p>
),
id: 'attribution-info-id'
}}
titleDescription="Provide attribution information."
/>
}
Expand All @@ -43,41 +128,106 @@ const AttributionInformation: React.FC<Props> = ({
type="text"
aria-label="title_work"
placeholder="Enter title of work"
validated={validTitle}
value={titleWork}
onChange={(_event, value) => setTitleWork(value)}
onBlur={() => validateTitle(titleWork)}
/>
{validTitle === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validTitle}>
Title is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}

<TextInput
isRequired
type="url"
aria-label="link_work"
placeholder="Enter link to work"
validated={validLink}
value={linkWork}
onChange={(_event, value) => setLinkWork(value)}
onBlur={() => validateLink(linkWork)}
/>
{validLink === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validLink}>
Link to title is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
{validLink === ValidatedOptions.warning && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validLink}>
Please enter a valid URL.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
<TextInput
isRequired
type="text"
aria-label="revision"
placeholder="Enter document revision information"
validated={validRevision}
value={revision}
onChange={(_event, value) => setRevision(value)}
onBlur={() => validateRevision(revision)}
/>
{validRevision === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validRevision}>
Revision is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
<TextInput
isRequired
type="text"
aria-label="license_work"
placeholder="Enter license of the work"
validated={validLicense}
value={licenseWork}
onChange={(_event, value) => setLicenseWork(value)}
onBlur={() => validateLicense(licenseWork)}
/>
{validLicense === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validLicense}>
License is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
<TextInput
isRequired
type="text"
aria-label="creators"
placeholder="Enter creators Name"
validated={validCreators}
value={creators}
onChange={(_event, value) => setCreators(value)}
onBlur={() => validateCreators(creators)}
/>
{validCreators === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validCreators}>
Creators is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
</FormGroup>
</FormFieldGroupExpandable>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,62 @@
import React from 'react';
import { FormFieldGroupExpandable, FormFieldGroupHeader, FormGroup } from '@patternfly/react-core/dist/dynamic/components/Form';
import React, { useState } from 'react';
import { FormFieldGroupExpandable, FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form';
import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput';
import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon';
import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants';
import { KnowledgeFormData } from '..';
import { checkKnowledgeFormCompletion } from '../validation';

interface Props {
knowledgeFormData: KnowledgeFormData;
setDisableAction: React.Dispatch<React.SetStateAction<boolean>>;
email: string;
setEmail: React.Dispatch<React.SetStateAction<string>>;
name: string;
setName: React.Dispatch<React.SetStateAction<string>>;
}
const AuthorInformation: React.FC<Props> = ({ email, setEmail, name, setName }) => {
const AuthorInformation: React.FC<Props> = ({ knowledgeFormData, setDisableAction, email, setEmail, name, setName }) => {
const [validEmail, setValidEmail] = useState<ValidatedOptions>();
const [validName, setValidName] = useState<ValidatedOptions>();

const validateEmail = (email: string) => {
const re = /\S+@\S+\.\S+/;
if (re.test(email)) {
setValidEmail(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidEmail(ValidatedOptions.error);
return;
};

const validateName = (name: string) => {
if (name.length > 0) {
setValidName(ValidatedOptions.success);
setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData));
return;
}
setDisableAction(true);
setValidName(ValidatedOptions.error);
return;
};

return (
<FormFieldGroupExpandable
isExpanded
toggleAriaLabel="Details"
header={
<FormFieldGroupHeader
titleText={{ text: 'Author Info', id: 'author-info-id' }}
titleText={{
text: (
<p>
Author Info <span style={{ color: 'red' }}>*</span>
</p>
),
id: 'author-info-id'
}}
titleDescription="Provide your information required for a GitHub DCO sign-off."
/>
}
Expand All @@ -27,16 +68,38 @@ const AuthorInformation: React.FC<Props> = ({ email, setEmail, name, setName })
aria-label="email"
placeholder="Enter your email address"
value={email}
validated={validEmail}
onChange={(_event, value) => setEmail(value)}
onBlur={() => validateEmail(email)}
/>
{validEmail === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validEmail}>
Please enter a valid email address.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
<TextInput
isRequired
type="text"
aria-label="name"
placeholder="Enter your full name"
value={name}
validated={validName}
onChange={(_event, value) => setName(value)}
onBlur={() => validateName(name)}
/>
{validName === ValidatedOptions.error && (
<FormHelperText>
<HelperText>
<HelperTextItem icon={<ExclamationCircleIcon />} variant={validName}>
Name is required.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
</FormGroup>
</FormFieldGroupExpandable>
);
Expand Down
Loading