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

style: Updated Array UI #1617

Merged
merged 31 commits into from
Dec 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
75de04d
Update validation and choice array ui
tdurnford Nov 20, 2019
3d7f18b
Updated string array
tdurnford Nov 21, 2019
b19e31e
Merge branch 'master' into 1510
tdurnford Nov 27, 2019
c67cf89
Merge branch 'master' into 1510
tdurnford Nov 30, 2019
3d00f9f
Updated regex pattern
tdurnford Dec 2, 2019
dbefebf
Merge branch 'master' into 1510
tdurnford Dec 2, 2019
37712b5
Updated array styles
tdurnford Dec 3, 2019
4141ee9
Style cleanup
tdurnford Dec 3, 2019
3771450
Merge branch 'master' into 1510
tdurnford Dec 3, 2019
8e5286a
Merge branch 'master' into 1510
tdurnford Dec 4, 2019
227af8d
Merge branch 'master' into 1510
cwhitten Dec 4, 2019
8f27478
Fixed string array test
tdurnford Dec 4, 2019
731944d
Fixed ObjectArray tests
tdurnford Dec 4, 2019
3069d84
Merge branch 'master' into 1510
tdurnford Dec 5, 2019
fd7d0f6
Updated request header object
tdurnford Dec 5, 2019
be85e06
Small change to custom object field
tdurnford Dec 5, 2019
d647273
Fixed styling
tdurnford Dec 5, 2019
9b93233
Updated dialogs
tdurnford Dec 5, 2019
9478ea5
Merge branch 'master' into 1510
tdurnford Dec 5, 2019
1c4a4b0
Fix margin issue
tdurnford Dec 6, 2019
755a04d
Merge branch 'master' into 1510
tdurnford Dec 6, 2019
945c935
Updated callback dependencies
tdurnford Dec 6, 2019
577664a
Added error message
tdurnford Dec 6, 2019
dd63e4f
Updated callback dependencies
tdurnford Dec 6, 2019
ef65401
Merge branch 'master' into 1510
cwhitten Dec 7, 2019
5648c34
Merge branch 'master' into 1510
tdurnford Dec 9, 2019
a0e9e36
Fixed margin issues
tdurnford Dec 9, 2019
2a43183
Fixed styles
tdurnford Dec 9, 2019
3c9843a
Fixed transparent border issue
tdurnford Dec 9, 2019
cfbf7ab
Fixed border color
tdurnford Dec 9, 2019
cbee1c0
Merge branch 'master' into 1510
tdurnford Dec 9, 2019
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
Expand Up @@ -53,9 +53,10 @@ describe('<StringArray />', () => {

it('can add an item', async () => {
const onAddClick = jest.fn();
const { findByText } = renderDefault({ canAdd: true, onAddClick });
const addBtn = await findByText('Add');
fireEvent.click(addBtn);
const { findByTestId } = renderDefault({ canAdd: true, onAddClick });
const input = await findByTestId('string-array-text-input');
fireEvent.change(input, { target: { value: 'test' } });
fireEvent.keyDown(input, { key: 'Enter', code: 13 });
expect(onAddClick).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/** @jsx jsx */
import { jsx } from '@emotion/core';
import React from 'react';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { IContextualMenuItem } from 'office-ui-fabric-react/lib/ContextualMenu';
import { ArrayFieldItem } from '@bfcomposer/react-jsonschema-form';
import formatMessage from 'format-message';
import { NeutralColors, FontSizes } from '@uifabric/fluent-theme';

import { arrayItem, arrayItemField } from './styles';

const ArrayItem: React.FC<ArrayFieldItem> = props => {
const { hasMoveUp, hasMoveDown, hasRemove, onReorderClick, onDropIndexClick, index } = props;
const { children, hasMoveUp, hasMoveDown, hasRemove, onReorderClick, onDropIndexClick, index } = props;

// This needs to return true to dismiss the menu after a click.
const fabricMenuItemClickHandler = fn => e => {
Expand Down Expand Up @@ -42,17 +46,15 @@ const ArrayItem: React.FC<ArrayFieldItem> = props => {
];

return (
<div className="ArrayItem">
<div className="ArrayItemField">{props.children}</div>
<div className="ArrayItemContext">
<IconButton
menuProps={{ items: contextItems }}
menuIconProps={{ iconName: 'MoreVertical' }}
ariaLabel={formatMessage('Item Actions')}
data-testid="ArrayItemContextMenu"
styles={{ menuIcon: { color: NeutralColors.black, fontSize: FontSizes.size16 } }}
/>
</div>
<div css={arrayItem}>
<div css={arrayItemField}>{children}</div>
<IconButton
menuProps={{ items: contextItems }}
menuIconProps={{ iconName: 'MoreVertical' }}
ariaLabel={formatMessage('Item Actions')}
data-testid="ArrayItemContextMenu"
styles={{ menuIcon: { color: NeutralColors.black, fontSize: FontSizes.size16 } }}
a-b-r-o-w-n marked this conversation as resolved.
Show resolved Hide resolved
/>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,146 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useCallback, useState } from 'react';
import { ArrayFieldTemplateProps } from '@bfcomposer/react-jsonschema-form';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { FontSizes, NeutralColors, SharedColors } from '@uifabric/fluent-theme';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { JSONSchema6 } from 'json-schema';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import formatMessage from 'format-message';

import { BaseField } from '../fields/BaseField';
import { WidgetLabel } from '../widgets/WidgetLabel';

import ArrayItem from './ArrayItem';
import {
arrayItemInputFieldContainer,
arrayItemField,
objectItemLabel,
objectItemInputField,
objectItemValueLabel,
} from './styles';

const ObjectArray: React.FunctionComponent<ArrayFieldTemplateProps> = props => {
const { items, canAdd, onAddClick } = props;
const { canAdd, idSchema, items, onAddClick, schema = {}, uiSchema = {} } = props;
const { object } = (uiSchema['ui:options'] || {}) as any;
const { items: itemSchema = {} } = schema;
const { properties = {} } = itemSchema as JSONSchema6;

const [value, setValue] = useState({});

const handleChange = useCallback(
property => (_, newValue?: string) => {
setValue(currentValue => ({ ...currentValue, [property]: newValue || '' }));
},
[setValue]
);

const handleKeyDown = useCallback(
event => {
if (event.key.toLowerCase() === 'enter') {
event.preventDefault();

if (Object.keys(value).length) {
onAddClick(event, value);
setValue({});
}
}
},
[onAddClick, setValue, value]
);

const isVisible = useCallback(
(property: string) => {
const { items: itemsSchema } = uiSchema;
return !(
itemsSchema['ui:hidden'] &&
Array.isArray(itemsSchema['ui:hidden']) &&
itemsSchema['ui:hidden'].includes(property)
);
},
[uiSchema]
);

return (
<BaseField {...props}>
{object && (
<div css={objectItemLabel}>
{Object.keys(properties)
.filter(isVisible)
.map((key, index) => {
const { description, title } = properties[key] as JSONSchema6;
const { __id = '' } = idSchema[key] || {};

return (
<div css={objectItemValueLabel} key={index}>
<WidgetLabel description={description} label={title} inline={true} id={__id} />
</div>
);
})}
<div style={{ width: '32px' }} />
</div>
)}
<div className="ObjectArray">
{items.map((element, idx) => (
<ArrayItem {...element} key={idx} />
))}
{canAdd && (
<DefaultButton
type="button"
onClick={onAddClick}
data-testid="ArrayContainerAdd"
styles={{ root: { marginTop: '14px' } }}
>
{formatMessage('Add')}
</DefaultButton>
)}
{canAdd &&
(!object ? (
<DefaultButton
type="button"
onClick={onAddClick}
data-testid="ArrayContainerAdd"
styles={{ root: { marginTop: '14px' } }}
>
{formatMessage('Add')}
</DefaultButton>
) : (
<div css={arrayItemInputFieldContainer}>
<div css={arrayItemField}>
{Object.keys(properties)
.filter(isVisible)
.map((property, index, items) => (
<div css={objectItemInputField} key={index}>
<TextField
autoComplete="off"
onChange={handleChange(property)}
onKeyDown={handleKeyDown}
placeholder={`${formatMessage('Add new')} ${property}`}
value={value[property] || ''}
iconProps={{
...(index === items.length - 1
? {
iconName: 'ReturnKey',
style: { color: SharedColors.cyanBlue10, opacity: 0.6 },
}
: {}),
}}
data-testid="object-array-text-input"
/>
</div>
))}
</div>
<IconButton
disabled={true}
menuIconProps={{ iconName: 'MoreVertical' }}
ariaLabel={formatMessage('Item Actions')}
styles={{
menuIcon: {
backgroundColor: NeutralColors.white,
color: NeutralColors.gray130,
fontSize: FontSizes.size16,
},
rootDisabled: {
backgroundColor: NeutralColors.white,
},
}}
/>
</div>
))}
</div>
</BaseField>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,77 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useCallback, useState } from 'react';
import { ArrayFieldTemplateProps } from '@bfcomposer/react-jsonschema-form';
import { FontSizes, NeutralColors, SharedColors } from '@uifabric/fluent-theme';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import formatMessage from 'format-message';

import { BaseField } from '../fields/BaseField';

import { arrayItemField, arrayItemInputFieldContainer } from './styles';
import ArrayItem from './ArrayItem';

import './styles.css';

const StringArray: React.FunctionComponent<ArrayFieldTemplateProps> = props => {
const { canAdd, items, onAddClick } = props;
const [value, setValue] = useState('');

const handleChange = useCallback((_, newValue?: string) => setValue(newValue || ''), [setValue]);

const handleKeyDown = useCallback(
event => {
if (event.key.toLowerCase() === 'enter') {
event.preventDefault();

if (value) {
onAddClick(event, value);
setValue('');
}
}
},
[onAddClick, setValue, value]
);

return (
<BaseField {...props}>
{props.items.map((element, idx) => (
<ArrayItem {...element} key={idx} />
))}
{props.canAdd && (
<DefaultButton type="button" onClick={e => props.onAddClick(e)} styles={{ root: { marginTop: '10px' } }}>
{formatMessage('Add')}
</DefaultButton>
<div>
{items.map((element, idx) => (
<ArrayItem {...element} key={idx} />
))}
</div>
{canAdd && (
<div css={arrayItemInputFieldContainer}>
<div css={arrayItemField}>
<TextField
onChange={handleChange}
onKeyDown={handleKeyDown}
value={value}
iconProps={{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use useMemo.

iconName: 'ReturnKey',
style: { color: SharedColors.cyanBlue10, opacity: 0.6 },
}}
data-testid="string-array-text-input"
/>
</div>
<IconButton
disabled={true}
menuIconProps={{ iconName: 'MoreVertical' }}
ariaLabel={formatMessage('Item Actions')}
styles={{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use useMemo.

menuIcon: {
backgroundColor: NeutralColors.white,
color: NeutralColors.gray130,
fontSize: FontSizes.size16,
},
rootDisabled: {
backgroundColor: NeutralColors.white,
},
}}
/>
</div>
)}
</BaseField>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import ObjectArray from './ObjectArray';
import IDialogArray from './IDialogArray';

const ArrayFieldTemplate: React.FunctionComponent<ArrayFieldTemplateProps> = props => {
if (!props.schema.items) {
const { registry, schema } = props;

if (!schema.items) {
return null;
}

let itemSchema = props.schema.items as any;
let itemSchema = schema.items as any;
const $ref = itemSchema.$ref;

if (!itemSchema.type && $ref) {
itemSchema = findSchemaDefinition($ref, props.registry.definitions);
itemSchema = findSchemaDefinition($ref, registry.definitions);
}

switch (itemSchema.type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { css } from '@emotion/core';
import { NeutralColors } from '@uifabric/fluent-theme';

export const arrayItem = css`
display: flex;
padding: 7px 0;

border-bottom: 1px solid ${NeutralColors.gray30};

&:first-type-of {
border-top: 1px solid ${NeutralColors.gray30};
}
`;

export const arrayItemField = css`
flex: 1;
display: flex;
`;

export const arrayItemInputFieldContainer = css`
display: flex;
padding: 7px 0;
`;

export const objectItemLabel = css`
border-bottom: 1px solid ${NeutralColors.gray30};
display: flex;
`;

export const objectItemValueLabel = css`
color: ${NeutralColors.gray130};
flex: 1;
font-size: 14px;
margin-left: 7px;
& + & {
margin-left: 20px;
}
`;

export const objectItemInputField = css`
flex: 1;
& + & {
margin-left: 20px;
}
`;
Loading