Skip to content

Commit

Permalink
Added validation messages to copying source form
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Oct 25, 2021
1 parent 006b7fb commit f5c5678
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 79 deletions.
41 changes: 21 additions & 20 deletions ui/src/app/metadata/copy/CopySource.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import { useForm } from 'react-hook-form';
import Check from 'react-bootstrap/FormCheck';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowCircleRight, faAsterisk, faCheck, faTimes } from '@fortawesome/free-solid-svg-icons';

import { Translate } from '../../i18n/components/translate';
import { EntityTypeahead } from './EntityTypeahead';
import kebabCase from 'lodash/kebabCase';
import { useMetadataSources } from '../hooks/api';

const sections = [
{ i18nKey: 'organizationInformation', property: 'organization' },
Expand All @@ -23,6 +24,8 @@ const sections = [

export function CopySource({ copy, onNext }) {

const { data = [] } = useMetadataSources({ cachePolicy: 'no-cache' }, []);

const [selected, setSelected] = React.useState(copy.properties);
const onSelect = (item, checked) => {
let s = [...selected];
Expand Down Expand Up @@ -59,6 +62,8 @@ export function CopySource({ copy, onNext }) {
setValue('properties', selected);
}, [selected, setValue]);

const sourceIds = data.map(p => p.entityId);

return (
<>
<div className="row">
Expand Down Expand Up @@ -120,28 +125,24 @@ export function CopySource({ copy, onNext }) {
<Translate value="message.service-resolver-name-required">Service Resolver Name is required</Translate>
</small>}
</div>
<div className="form-group">
<label htmlFor="entityId">
<Form.Group className={`form-group ${errors.entityId ? 'text-danger' : ''}`}>
<Form.Label htmlFor="entityId">
<Translate value="label.service-resolver-entity-id">New Entity ID</Translate>
<FontAwesomeIcon icon={faAsterisk} className="text-danger" />
</label>
<input id="entityId" type="text"
className="form-control"
placeholder=""
</Form.Label>
<Form.Control id="entityId" type="text"
isInvalid={errors.entityId}
aria-describedby="entityId-help"
{...register('entityId', { required: true })} />
{errors?.entityId &&
<small className="form-text text-danger"
id="entityId-help">
{errors.entityId.type === 'required' &&
<Translate value="message.entity-id-required">Entity ID is required</Translate>
{...register('entityId', {
required: true, validate: {
unique: v => !(sourceIds.indexOf(v) > -1)
}
{errors.entityId.type === 'unique' &&
<Translate value="message.entity-id-must-be-unique">Entity ID must be unique</Translate>
}
</small>
}
</div>
})} />
<Form.Text className={errors.entityId ? 'text-danger' : 'text-muted'}>
{errors?.entityId?.type === 'unique' && <Translate value={`message.must-be-unique`} />}
{errors?.entityId?.type === 'required' && <Translate value={`message.entity-id-required`} />}
</Form.Text>
</Form.Group>
</fieldset>
</form>
</div>
Expand All @@ -158,7 +159,7 @@ export function CopySource({ copy, onNext }) {
<tr key={i}>
<td><label className="mb-0" htmlFor={`property-checkbox-${i}`}><Translate value={`label.${kebabCase(item.i18nKey)}`} /></label></td>
<td>
<Check
<Form.Check
custom
type={'checkbox'}
id={`property-checkbox-${i}`}
Expand Down
95 changes: 36 additions & 59 deletions ui/src/app/metadata/copy/SaveCopy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import Check from 'react-bootstrap/FormCheck';
import Button from 'react-bootstrap/Button';
import { faArrowCircleLeft, faCheck, faSave, faSpinner } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
Expand All @@ -12,9 +11,6 @@ import { removeNull } from '../../core/utility/remove_null';
import { MetadataConfiguration } from '../component/MetadataConfiguration';
import Translate from '../../i18n/components/translate';

import { InfoIcon } from '../../form/component/InfoIcon';


export function useCopiedModel (copy) {
const { properties, target, serviceProviderName, entityId } = copy;
const copied = removeNull(properties.reduce((c, section) => ({ ...c, ...{ [section]: target[section] } }), {}));
Expand All @@ -37,7 +33,7 @@ export function SaveCopy ({ copy, saving, onSave, onBack }) {
const model = useCopiedModel(copy);
const configuration = useCopiedConfiguration(model, schema, definition);

const { register, handleSubmit } = useForm({
const { handleSubmit } = useForm({
mode: 'onChange',
reValidateMode: 'onBlur',
defaultValues: {
Expand All @@ -59,61 +55,42 @@ export function SaveCopy ({ copy, saving, onSave, onBack }) {

return (
<>
<div className="row">
<div className="col col-xs-12">
<ul className="nav nav-wizard m-3">
<li className="nav-item">
<Button type="button" className="nav-link previous btn d-flex justify-content-between align-items-start" onClick={onBack}>
<span className="direction d-flex flex-column align-items-center">
<FontAwesomeIcon icon={faArrowCircleLeft} size="2x" />
<Translate value="action.back">Back</Translate>
</span>
<span className="label">
<Translate value="label.name-and-entityid">
Name and Entity ID.
</Translate>
</span>
</Button>
</li>
<li className="nav-item">
<h3 className="tag tag-primary">
<span className="index">
<FontAwesomeIcon icon={faCheck} />
</span>
<Translate value="label.finish-summary-validation">Finished!</Translate>
</h3>
</li>
<li className="nav-item">
<Button className="nav-link save btn d-flex justify-content-between align-items-start" aria-label="Save" onClick={() => handleSubmit(onFinish)()} type="button">
<span className="label"><Translate value="action.save">Save</Translate></span>
<span className="direction d-flex flex-column align-items-center">
<FontAwesomeIcon icon={saving ? faSpinner : faSave} pulse={saving} size="2x" />
<Translate value="action.save">Save</Translate>
</span>
</Button>
</li>
</ul>
</div>
<div className="row">
<div className="col col-xs-12">
<ul className="nav nav-wizard m-3">
<li className="nav-item">
<Button type="button" className="nav-link previous btn d-flex justify-content-between align-items-start" onClick={onBack}>
<span className="direction d-flex flex-column align-items-center">
<FontAwesomeIcon icon={faArrowCircleLeft} size="2x" />
<Translate value="action.back">Back</Translate>
</span>
<span className="label">
<Translate value="label.name-and-entityid">
Name and Entity ID.
</Translate>
</span>
</Button>
</li>
<li className="nav-item">
<h3 className="tag tag-primary">
<span className="index">
<FontAwesomeIcon icon={faCheck} />
</span>
<Translate value="label.finish-summary-validation">Finished!</Translate>
</h3>
</li>
<li className="nav-item">
<Button className="nav-link save btn d-flex justify-content-between align-items-start" aria-label="Save" onClick={() => handleSubmit(onFinish)()} type="button">
<span className="label"><Translate value="action.save">Save</Translate></span>
<span className="direction d-flex flex-column align-items-center">
<FontAwesomeIcon icon={saving ? faSpinner : faSave} pulse={saving} size="2x" />
<Translate value="action.save">Save</Translate>
</span>
</Button>
</li>
</ul>
</div>
<form onSubmit={ handleSubmit(onFinish) }>
<div className="row">
<fieldset className="col-xl-6 form-section">
<section className="entity-section">
<div className="form-group d-flex">
<label htmlFor="serviceEnabled" className="mr-2"><Translate value="label.enable-this-service" /></label>
<Check custom
id="serviceEnabled"
className="mr-2"
type={'checkbox'}
{...register('serviceEnabled')}
/>
<InfoIcon value={`tooltip.enable-this-service-upon-saving`} placement="right" />
</div>
</section>
</fieldset>
</div>
</form>

</div>
<MetadataConfiguration configuration={configuration} />
</>
);
Expand Down
9 changes: 9 additions & 0 deletions ui/src/app/metadata/view/MetadataCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import { CopySource } from '../copy/CopySource';
import { SaveCopy } from '../copy/SaveCopy';
import { useMetadataEntity } from '../hooks/api';
import { useHistory } from 'react-router';
import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications';

export function MetadataCopy ({ onShowNav }) {

const { post, response, loading } = useMetadataEntity('source');
const history = useHistory();

const dispatch = useNotificationDispatcher();

const [copy, setCopy] = React.useState({
target: null,
serviceProviderName: null,
Expand All @@ -34,6 +37,12 @@ export function MetadataCopy ({ onShowNav }) {
await post('', data);
if (response.ok) {
history.push('/');
} else {
const { errorCode, errorMessage, cause } = response.data;
dispatch(createNotificationAction(
`${errorCode}: ${errorMessage} ${cause ? `-${cause}` : ''}`,
NotificationTypes.ERROR
));
}
}

Expand Down

0 comments on commit f5c5678

Please sign in to comment.