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

feat: Align with the new design in form for inline error display #1683

Merged
merged 12 commits into from
Dec 4, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

.ObjectItem .ObjectItemField {
flex: 1;
overflow: hidden;
padding: 0px 18px;
margin: 10px 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@
// Licensed under the MIT License.

import React, { useState, useEffect } from 'react';
import { TextField, ITextFieldStyles, ITextFieldProps } from 'office-ui-fabric-react/lib/TextField';
import { TextField, ITextFieldProps } from 'office-ui-fabric-react/lib/TextField';
import { NeutralColors } from '@uifabric/fluent-theme';
import { mergeStyles } from '@uifabric/styling';
import { mergeStyleSets } from '@uifabric/styling';

interface EditableFieldProps extends ITextFieldProps {
onChange: (e: any, newTitle?: string) => void;
styleOverrides?: Partial<ITextFieldStyles>;
placeholder?: string;
fontSize?: string;
}

export const EditableField: React.FC<EditableFieldProps> = props => {
const { styleOverrides = {}, placeholder, fontSize, onChange, onBlur, value, ...rest } = props;
const { styles = {}, placeholder, fontSize, onChange, onBlur, value, ...rest } = props;
const [editing, setEditing] = useState<boolean>(false);
const [hasFocus, setHasFocus] = useState<boolean>(false);
const [localValue, setLocalValue] = useState<string | undefined>(value);
Expand Down Expand Up @@ -49,21 +48,18 @@ export const EditableField: React.FC<EditableFieldProps> = props => {
<TextField
placeholder={placeholder || value}
value={localValue}
styles={{
root: mergeStyles({ margin: '5px 0 7px -9px' }, styleOverrides.root),
field: mergeStyles(
{
styles={mergeStyleSets(
{
root: { margin: '5px 0 7px -9px' },
field: {
fontSize: fontSize,
selectors: {
'::placeholder': {
fontSize: fontSize,
},
},
},
styleOverrides.field
),
fieldGroup: mergeStyles(
{
fieldGroup: {
borderColor,
transition: 'border-color 0.1s linear',
selectors: {
Expand All @@ -72,9 +68,9 @@ export const EditableField: React.FC<EditableFieldProps> = props => {
},
},
},
styleOverrides.fieldGroup
),
}}
},
styles
)}
onBlur={handleCommit}
onFocus={() => setHasFocus(true)}
onChange={handleChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const ChoiceItem: React.FC<ChoiceItemProps> = props => {
<EditableField
onChange={handleEdit('value')}
value={choice.value}
styleOverrides={{
styles={{
root: { margin: '5px 0 7px 0' },
}}
onBlur={handleBlur}
Expand All @@ -95,7 +95,7 @@ const ChoiceItem: React.FC<ChoiceItemProps> = props => {
onChange={handleEdit('synonyms')}
value={choice.synonyms && choice.synonyms.join(', ')}
placeholder={formatMessage('Add multiple comma-separated synonyms')}
styleOverrides={{
styles={{
root: { margin: '5px 0 7px 0' },
}}
onBlur={handleBlur}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { MicrosoftInputDialog } from '@bfc/shared';

import { TextWidget, CheckboxWidget } from '../../widgets';

import { field, settingsFields, settingsFieldHalf, settingsFieldFull, settingsFieldInline } from './styles';
import { PromptFieldChangeHandler, GetSchema } from './types';
import { TwoSettingFields } from './twoSettingFields';
import { field, settingsFields, settingsFieldFull, settingsFieldInline } from './styles';
import { PromptFieldChangeHandler, GetSchema, InputDialogKeys } from './types';

interface PromptSettingsrops extends FieldProps<MicrosoftInputDialog> {
onChange: PromptFieldChangeHandler;
Expand All @@ -19,52 +20,43 @@ interface PromptSettingsrops extends FieldProps<MicrosoftInputDialog> {

export const PromptSettings: React.FC<PromptSettingsrops> = props => {
const { formData, idSchema, getSchema, onChange, errorSchema } = props;
const fields: { [key: string]: InputDialogKeys | string }[] = [
{
name: 'maxTurnCount',
title: formatMessage('Max turn count'),
},
{
name: 'defaultValue',
title: formatMessage('Default value'),
},
];

return (
<div css={settingsFields}>
<div css={[field, settingsFieldHalf]}>
<TextWidget
onChange={onChange('maxTurnCount')}
schema={getSchema('maxTurnCount')}
id={idSchema.maxTurnCount.__id}
value={formData.maxTurnCount}
label={formatMessage('Max turn count')}
formContext={props.formContext}
rawErrors={errorSchema.maxTurnCount && errorSchema.maxTurnCount.__errors}
/>
</div>
<div css={[field, settingsFieldHalf]}>
<TextWidget
onChange={onChange('defaultValue')}
schema={getSchema('defaultValue')}
id={idSchema.defaultValue.__id}
value={formData.defaultValue}
label={formatMessage('Default value')}
formContext={props.formContext}
rawErrors={errorSchema.defaultValue && errorSchema.defaultValue.__errors}
/>
</div>
<div css={[field, settingsFieldFull]}>
<TextWidget
onChange={onChange('allowInterruptions')}
schema={getSchema('allowInterruptions')}
id={idSchema.allowInterruptions.__id}
value={formData.allowInterruptions}
label={formatMessage('Allow interruptions')}
formContext={props.formContext}
rawErrors={errorSchema.allowInterruptions && errorSchema.allowInterruptions.__errors}
/>
</div>
<div css={[field, settingsFieldFull, settingsFieldInline]}>
<CheckboxWidget
onChange={onChange('alwaysPrompt')}
schema={getSchema('alwaysPrompt')}
id={idSchema.alwaysPrompt.__id}
value={formData.alwaysPrompt}
label={formatMessage('Always prompt')}
formContext={props.formContext}
rawErrors={errorSchema.alwaysPrompt && errorSchema.alwaysPrompt.__errors}
/>
<div>
<TwoSettingFields fields={fields} {...props} />
<div css={settingsFields}>
<div css={[field, settingsFieldFull]}>
<TextWidget
onChange={onChange('allowInterruptions')}
schema={getSchema('allowInterruptions')}
id={idSchema.allowInterruptions.__id}
value={formData.allowInterruptions}
label={formatMessage('Allow interruptions')}
formContext={props.formContext}
rawErrors={errorSchema.allowInterruptions && errorSchema.allowInterruptions.__errors}
/>
</div>
<div css={[field, settingsFieldFull, settingsFieldInline]}>
<CheckboxWidget
onChange={onChange('alwaysPrompt')}
schema={getSchema('alwaysPrompt')}
id={idSchema.alwaysPrompt.__id}
value={formData.alwaysPrompt}
label={formatMessage('Always prompt')}
formContext={props.formContext}
rawErrors={errorSchema.alwaysPrompt && errorSchema.alwaysPrompt.__errors}
/>
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,17 @@ export const settingsContainer = css`
export const settingsFields = css`
display: flex;
flex-wrap: wrap;
position: relative;
`;

export const settingsFieldFull = css`
flex-basis: 100%;
overflow: hidden;
`;

export const settingsFieldHalf = css`
flex: 1;
overflow: hidden;

& + & {
margin-left: 36px;
Expand All @@ -67,6 +70,10 @@ export const settingsFieldInline = css`
margin: 0;
`;

export const settingsFieldValidation = css`
margin-top: -10px;
`;

export const choiceItemContainer = (align = 'center') => css`
display: flex;
align-items: ${align};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable format-message/literal-pattern */
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useState } from 'react';
import formatMessage from 'format-message';
import { FieldProps } from '@bfcomposer/react-jsonschema-form';
import { MicrosoftInputDialog } from '@bfc/shared';

import { TextWidget } from '../../widgets';

import { field, settingsFieldHalf, settingsFields, settingsFieldFull, settingsFieldValidation } from './styles';
import { PromptFieldChangeHandler, GetSchema, InputDialogKeys } from './types';

interface TwoSettingFieldsProps extends FieldProps<MicrosoftInputDialog> {
onChange: PromptFieldChangeHandler;
getSchema: GetSchema;
fields: { [key: string]: InputDialogKeys | string }[];
}
export const TwoSettingFields: React.FC<TwoSettingFieldsProps> = props => {
const { fields, formData, idSchema, getSchema, onChange, errorSchema } = props;
const [errorMessage, setErrorMessage] = useState<JSX.Element | string | undefined>();

const onValidate = (err?: JSX.Element | string) => {
setErrorMessage(err);
};

return (
<div css={settingsFields}>
{fields.map((settingField, index) => (
<div key={index} css={[field, settingsFieldHalf]}>
<TextWidget
onChange={onChange(settingField.name as InputDialogKeys)}
schema={getSchema(settingField.name as InputDialogKeys)}
id={idSchema[settingField.name].__id}
value={formData[settingField.name]}
label={formatMessage(settingField.title as string)}
formContext={props.formContext}
rawErrors={errorSchema[settingField.name] && errorSchema[settingField.name].__errors}
hiddenErrMessage={true}
onValidate={onValidate}
/>
</div>
))}
<div css={[field, settingsFieldFull, settingsFieldValidation]}>{errorMessage}</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { LuEditor } from '@bfc/code-editor';
import { LuFile } from '@bfc/shared';

Expand All @@ -15,16 +15,19 @@ const InlineLuEditor: React.FC<InlineLuEditorProps> = props => {
const { file, onSave, errorMsg } = props;
const [content, setContent] = useState(file.content || '');

// save on mount to trigger validation
useEffect(() => {
if (content) {
onSave(content);
}
}, []);

const commitChanges = value => {
setContent(value);
onSave(value);
};

return (
<div style={{ margin: '10px 0', padding: '0 18px' }}>
<LuEditor value={content} onChange={commitChanges} errorMsg={errorMsg} height={450} />
</div>
);
return <LuEditor value={content} onChange={commitChanges} errorMsg={errorMsg} height={450} />;
};

export default InlineLuEditor;
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
/** @jsx jsx */
import { jsx } from '@emotion/core';
import { toIdSchema } from '@bfcomposer/react-jsonschema-form/lib/utils';
import { FieldProps } from '@bfcomposer/react-jsonschema-form';
import { JSONSchema6 } from 'json-schema';
import { MicrosoftIRecognizer } from '@bfc/shared';

import { regexEditorContainer } from './styles';

export default function RegexEditor(props: FieldProps<MicrosoftIRecognizer>) {
if (!props.schema.oneOf) {
return null;
Expand All @@ -25,5 +28,9 @@ export default function RegexEditor(props: FieldProps<MicrosoftIRecognizer>) {
) as JSONSchema6;
const idSchema = toIdSchema(schema, props.idSchema.__id, definitions, formData, idPrefix);

return <ObjectField {...props} schema={schema} idSchema={idSchema} />;
return (
<div css={regexEditorContainer}>
<ObjectField {...props} schema={schema} idSchema={idSchema} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function ToggleEditor(props: ToggleEditorProps) {
? formatMessage('Hide {title}', { title: props.title })
: formatMessage('View {title}', { title: props.title })}
</Link>
<div className="ToggleEditorContent">{showEditor && props.children()}</div>
<div>{showEditor && props.children()}</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
.ToggleEditor .BaseField {
margin-top: 5px;
}
.ToggleEditor .ToggleEditorContent {
margin: 0 -18px -26px -18px; /* offset ObjectFieldTemplate padding */
}
.ToggleEditor .ToggleEditorContent .ObjectItemContainer:last-child {
margin-bottom: 0;
border-bottom: none;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { css } from '@emotion/core';

// offset ObjectField's margin
export const regexEditorContainer = css`
margin: 0 -18px -26px -18px;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const RootField: React.FC<RootFieldProps> = props => {
<EditableField
value={getTitle()}
onChange={handleTitleChange}
styleOverrides={{ field: { fontWeight: FontWeights.semibold } }}
styles={{ field: { fontWeight: FontWeights.semibold } }}
fontSize={FontSizes.size20}
/>
<p className="RootFieldSubtitle">{getSubTitle()}</p>
Expand Down
Loading