Skip to content
This repository has been archived by the owner on Jun 14, 2019. It is now read-only.

fix: expose the isInitialValid property and set it appropriately in the editor, add some IDs #310

Merged
merged 1 commit into from
May 18, 2019
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
5 changes: 5 additions & 0 deletions app/ui-react/packages/auto-form/src/AutoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export interface IAutoFormProps<T> {
* The initial value that should be set on the form
*/
initialValue: T;
/**
* If the passed in value is valid or not
*/
isInitialValid?: boolean;
/**
* String to be displayed when a required field isn't set
*/
Expand Down Expand Up @@ -63,6 +67,7 @@ export class AutoForm<T> extends React.Component<IAutoFormProps<T>> {
<Formik<T>
initialValues={initialValue}
onSubmit={onSave}
isInitialValid={this.props.isInitialValid}
validate={this.props.validate}
>
{({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,18 @@ export class IntegrationEditorForm extends React.Component<
<div className="card-pf-footer">
{this.props.backActionHref && (
<>
<ButtonLink href={this.props.backActionHref}>
<ButtonLink
id={'integration-editor-form-back-button'}
href={this.props.backActionHref}
>
<i className={'fa fa-chevron-left'} />{' '}
{this.props.i18nBackAction}
</ButtonLink>
&nbsp;
</>
)}
<ButtonLink
id={'integration-editor-form-next-button'}
onClick={this.props.submitForm}
disabled={!this.props.isValid}
as={'primary'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class DescribeDataShapeForm extends React.Component<
<FieldLevelHelp content={this.props.i18nSelectTypeHelp} />
</ControlLabel>
<FormControl
data-testid={'describe-data-shape-form-kind-select'}
componentClass="select"
value={this.props.kind}
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
Expand All @@ -96,6 +97,7 @@ export class DescribeDataShapeForm extends React.Component<
content={this.props.i18nDefinitionHelp}
/>
<TextEditor
id={'describe-data-shape-form-definition-editor'}
value={this.props.definition || ''}
onChange={(editor, data, text) =>
this.props.onDefinitionChange(text)
Expand All @@ -121,6 +123,7 @@ export class DescribeDataShapeForm extends React.Component<
/>
</ControlLabel>
<FormControl
data-testid={'describe-data-shape-form-name-text'}
type="text"
value={this.props.name}
onChange={(
Expand All @@ -139,6 +142,9 @@ export class DescribeDataShapeForm extends React.Component<
</ControlLabel>
<FormControl
type="text"
data-testid={
'describe-data-shape-form-description-text'
}
value={this.props.description}
onChange={(
event: React.ChangeEvent<HTMLInputElement>
Expand All @@ -154,14 +160,21 @@ export class DescribeDataShapeForm extends React.Component<
<div className="card-pf-footer">
{this.props.backActionHref && (
<>
<ButtonLink href={this.props.backActionHref}>
<ButtonLink
data-testid={'describe-data-shape-form-back-button'}
href={this.props.backActionHref}
>
<i className={'fa fa-chevron-left'} />{' '}
{this.props.i18nBackAction}
</ButtonLink>
&nbsp;
</>
)}
<ButtonLink onClick={this.props.onNext} as={'primary'}>
<ButtonLink
data-testid={'describe-data-shape-form-next-button'}
onClick={this.props.onNext}
as={'primary'}
>
{this.props.i18nNext}
</ButtonLink>
</div>
Expand Down
15 changes: 9 additions & 6 deletions app/ui-react/packages/ui/src/Shared/TextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export { CodeMirror };
export type ITextEditor = CodeMirror.Editor;

export interface ITextEditorProps {
id?: string;
value: string;
options: { [name: string]: any };
onChange: (editor: ITextEditor, data: any, value: string) => void;
Expand All @@ -25,12 +26,14 @@ export class TextEditor extends React.Component<ITextEditorProps> {
const options = { ...this.props.options };
return (
<>
<ReactCodeMirror
value={this.props.value}
options={options}
onChange={this.props.onChange}
editorDidMount={this.props.editorDidMount}
/>
<div data-testid={this.props.id || 'codemirror'}>
<ReactCodeMirror
value={this.props.value}
options={options}
onChange={this.props.onChange}
editorDidMount={this.props.editorDidMount}
/>
</div>
</>
);
}
Expand Down
38 changes: 32 additions & 6 deletions app/ui-react/packages/utils/src/autoformHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IFormDefinition, IFormDefinitionProperty } from '@syndesis/auto-form';
import {
IConfigurationProperties,
IConfigurationProperty,
StringMap,
} from '@syndesis/models';

/**
Expand Down Expand Up @@ -54,12 +55,32 @@ export function toFormDefinitionProperty(property: IConfigurationProperty) {
} as IFormDefinitionProperty;
}

export function getInitialValues(properties: IConfigurationProperties) {
const configuredProperties = {};
/**
* Returns a new configuredProperties object with any default values set from
* the given definition if they aren't set already
* @param properties
* @param initial
*/
export function applyInitialValues(
properties: IConfigurationProperties,
initial?: StringMap<string>
) {
const configuredProperties =
typeof initial !== 'undefined' ? { ...initial } : {};
Object.keys(properties).forEach(key => {
const property = properties[key];
if (property.value || property.defaultValue) {
configuredProperties[key] = property.value || property.defaultValue;
// `property.value` being set is deprecated, defaultValue takes precedence
if (
typeof property.value !== 'undefined' &&
typeof configuredProperties[key] === 'undefined'
) {
configuredProperties[key] = property.value;
}
if (
typeof property.defaultValue !== 'undefined' &&
typeof configuredProperties[key] === 'undefined'
) {
configuredProperties[key] = property.defaultValue;
}
});
return configuredProperties;
Expand All @@ -72,8 +93,13 @@ export function validateConfiguredProperties(
if (typeof values === 'undefined') {
return false;
}
const allRequiredSet = Object.keys(properties)
.filter(key => properties[key].required)
const allRequired = Object.keys(properties).filter(
key => properties[key].required
);
if (allRequired.length === 0) {
return true;
}
const allRequiredSet = allRequired
.map(key => typeof values[key] !== 'undefined')
.reduce((prev, curr) => curr, false);
return allRequiredSet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,11 @@ export class ConfigureActionPage extends React.Component<
<WithConfigurationForm
connection={connection}
actionId={actionId}
oldAction={oldStepConfig!.action!}
oldAction={
oldStepConfig && oldStepConfig.action
? oldStepConfig!.action!
: undefined
}
configurationStep={stepAsNumber}
initialValue={configuredProperties}
onUpdatedIntegration={onUpdatedIntegration}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
PageSectionLoader,
} from '@syndesis/ui';
import {
getInitialValues,
applyInitialValues,
toFormDefinition,
validateConfiguredProperties,
WithLoader,
Expand Down Expand Up @@ -76,7 +76,7 @@ export interface IWithConfigurationFormProps {
*/
actionId: string;

oldAction: Action;
oldAction?: Action;
/**
* for actions whose configuration must be performed in multiple steps,
* indicates the current step.
Expand Down Expand Up @@ -129,30 +129,39 @@ export class WithConfigurationForm extends React.Component<
values: { [key: string]: string },
actions: any
): Promise<void> => {
action =
typeof this.props.oldAction !== 'undefined'
? applyUserDefinedDataShapesToAction(this.props.oldAction, {
...action,
descriptor,
})
: action;
await this.props.onUpdatedIntegration({
action: applyUserDefinedDataShapesToAction(this.props.oldAction, {
...action,
descriptor,
}),
action,
moreConfigurationSteps,
values,
});
actions.setSubmitting(false);
};
const key = JSON.stringify(definition);
const allRequiredSet = validateConfiguredProperties(
const initialValue = applyInitialValues(
definition,
this.props.initialValue
);
const isInitialValid = validateConfiguredProperties(
definition,
initialValue
);
return (
<AutoForm<{ [key: string]: string }>
i18nRequiredProperty={'* Required field'}
definition={toFormDefinition(definition)}
initialValue={this.props.initialValue || getInitialValues(definition)}
initialValue={initialValue}
isInitialValid={isInitialValid}
onSave={onSave}
validate={(values: { [name: string]: any }): any => {
return true;
}}
validate={(values: { [name: string]: any }): any =>
validateConfiguredProperties(definition, values)
}
key={key}
>
{({ dirty, fields, handleSubmit, isValid, submitForm }) => (
Expand All @@ -161,7 +170,7 @@ export class WithConfigurationForm extends React.Component<
i18nFormTitle={`${action.name} - ${action.description}`}
i18nBackAction={'Choose Action'}
i18nNext={'Next'}
isValid={allRequiredSet || isValid}
isValid={isValid}
submitForm={submitForm}
handleSubmit={handleSubmit}
backActionHref={this.props.chooseActionHref}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import {
getActionSteps,
} from '@syndesis/api';
import { AutoForm } from '@syndesis/auto-form';
import { StepKind } from '@syndesis/models';
import { ConfigurationProperty, StepKind } from '@syndesis/models';
import { IntegrationEditorForm } from '@syndesis/ui';
import { toFormDefinition } from '@syndesis/utils';
import {
applyInitialValues,
toFormDefinition,
validateConfiguredProperties,
} from '@syndesis/utils';
import * as React from 'react';

export interface IWithConfigurationFormChildrenProps {
Expand Down Expand Up @@ -91,9 +95,7 @@ export class WithConfigurationForm extends React.Component<
let step = this.props.step.properties
? this.props.step
: ALL_STEPS.find(s => s.stepKind === this.props.step.stepKind);

let definition;

let definition: { [key: string]: ConfigurationProperty };
// if step is undefined, maybe we are dealing with an extension
if (!step) {
const steps = getActionSteps(this.props.step.action!.descriptor!);
Expand All @@ -103,12 +105,24 @@ export class WithConfigurationForm extends React.Component<
} else {
definition = step.properties;
}
const initialValue = applyInitialValues(
definition,
this.props.step.configuredProperties
);
const isInitialValid = validateConfiguredProperties(
definition,
initialValue
);
return (
<AutoForm<{ [key: string]: string }>
i18nRequiredProperty={'* Required field'}
definition={toFormDefinition(definition)}
initialValue={this.props.step.configuredProperties || {}}
initialValue={initialValue}
isInitialValid={isInitialValid}
onSave={onSave}
validate={(values: { [name: string]: any }): any =>
validateConfiguredProperties(definition, values)
}
key={this.props.step.id}
>
{({ fields, handleSubmit, isSubmitting, isValid, submitForm }) =>
Expand Down