Skip to content

Commit

Permalink
Merge pull request #138 from vishnoianil/knowledge-constraints
Browse files Browse the repository at this point in the history
Enforce knowledge schema constraints in the UI
  • Loading branch information
nerdalert authored Aug 30, 2024
2 parents fb1c4e5 + ac8bf08 commit 9f70518
Show file tree
Hide file tree
Showing 15 changed files with 1,054 additions and 221 deletions.
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

0 comments on commit 9f70518

Please sign in to comment.