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

fix: Check all expressions in dialog #1798

Merged
merged 31 commits into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
129807d
check all expressions in dialog
lei9444 Dec 19, 2019
3e535fc
update the schema"
lei9444 Dec 23, 2019
716d4ec
update schema
lei9444 Dec 23, 2019
0ee6ae5
Merge branch 'master' into fixcheck
lei9444 Dec 23, 2019
944b273
check items in schema
lei9444 Dec 24, 2019
b262a69
navigation
lei9444 Dec 24, 2019
3bf8dae
update the fragment function
lei9444 Dec 24, 2019
9ff6938
move convert function to client
lei9444 Dec 24, 2019
0dd2282
fix unit test
lei9444 Dec 25, 2019
7a4ef0c
update the diagnostic path
lei9444 Dec 25, 2019
58fdb72
commit -m change the checkfun structure
lei9444 Dec 27, 2019
bc17a5a
update the schema
lei9444 Dec 27, 2019
b1d0344
expression regx
alanlong9278 Dec 27, 2019
954bc4c
Merge branch 'fixcheck' of https://github.com/lei9444/BotFramework-Co…
alanlong9278 Dec 27, 2019
478be0b
ui adjust for assignment property in setProperties
alanlong9278 Dec 28, 2019
7ca6362
Merge branch 'master' into fixcheck
lei9444 Dec 28, 2019
b8ecd88
fix e2e bug
alanlong9278 Dec 29, 2019
f022292
fix the array copy error
lei9444 Dec 30, 2019
0ba0f19
Merge branch 'master' into fixcheck
lei9444 Dec 30, 2019
24d83dc
sync expression error in formEditor
alanlong9278 Dec 30, 2019
686c152
Merge branch 'fixcheck' of https://github.com/lei9444/BotFramework-Co…
alanlong9278 Dec 30, 2019
b3a73b8
fix some comments
lei9444 Dec 31, 2019
a0fd9c3
Merge branch 'fixcheck' of https://github.com/lei9444/BotFramework-Co…
lei9444 Dec 31, 2019
8b6395f
Merge branch 'master' into fixcheck
lei9444 Dec 31, 2019
89998e0
move diagnostic path to shell
lei9444 Dec 31, 2019
9d7b8f9
Merge branch 'fixcheck' of https://github.com/lei9444/BotFramework-Co…
lei9444 Dec 31, 2019
512c567
fix unit test
lei9444 Dec 31, 2019
0ccc90d
update shared and indexers
lei9444 Jan 2, 2020
26a967d
fix spell error
lei9444 Jan 2, 2020
011e3ae
Merge branch 'master' into fixcheck
lei9444 Jan 6, 2020
c898ae0
Merge branch 'master' into fixcheck
cwhitten Jan 6, 2020
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
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License

import { parsePathToFocused } from '../../../src/utils/convertUtils';

describe('parsePathToFocused', () => {
it('should return focusedPath', () => {
expect(parsePathToFocused('')).toBe('');
expect(parsePathToFocused('main.triggers[0].actions[0]')).toBe('triggers[0].actions[0]');
expect(parsePathToFocused('main.triggers[0].actions[0].actions[1]')).toBe('triggers[0].actions[0].actions[1]');
expect(parsePathToFocused('main.triggers[0].actions[0].elseActions[1]')).toBe(
'triggers[0].actions[0].elseActions[1]'
);
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License

import { parsePathToSelected } from '../../src';
import { parsePathToSelected } from '../../../src/utils/convertUtils';

describe('parsePathToSelected', () => {
it('should return selected path', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License
import { PromptTab } from '@bfc/shared';

import { parseTypeToFragment, PromptTab } from './../../src';
import { parseTypeToFragment } from '../../../src/utils/convertUtils';

describe('parseTypeToFragment', () => {
it('should return corrent tab name', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { parsePathToSelected } from './parsePathToSelected';

export function parsePathToFocused(path: string): string {
//path is like main.trigers[0].actions[0]

const trigger = parsePathToSelected(path);

const list = path.split('.');

const matchActions = list.filter(x => x.startsWith('actions') || x.startsWith('elseActions'));

if (matchActions.length > 0) {
return trigger + '.' + matchActions.join('.');
}
return '';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { dialogGroups, DialogGroup, PromptTab } from '@bfc/shared';

export function parseTypeToFragment(type: string, property: string): string {
const inputTypes = dialogGroups[DialogGroup.INPUT].types;
const index = inputTypes.findIndex(t => t === type);
if (index >= 0) {
switch (property) {
case 'prompt':
return PromptTab.BOT_ASKS;
case 'property':
case 'choices':
case 'outputFormat':
return PromptTab.USER_INPUT;
default:
return PromptTab.OTHER;
}
}
return '';
}
2 changes: 1 addition & 1 deletion Composer/packages/client/src/utils/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import cloneDeep from 'lodash/cloneDeep';
import { navigate, NavigateOptions } from '@reach/router';
import { Diagnostic } from '@bfc/indexers';
import { parsePathToFocused, parsePathToSelected, parseTypeToFragment } from '@bfc/shared';

import { BreadcrumbItem, DesignPageLocation } from '../store/types';

import { parsePathToFocused, parsePathToSelected, parseTypeToFragment } from './convertUtils';
import { BASEPATH } from './../constants/index';
import { resolveToBasePath } from './fileUtil';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const arrayItem = css`
export const arrayItemField = css`
flex: 1;
display: flex;
min-width: 0;
`;

export const arrayItemInputFieldContainer = css`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.ObjectItemInline {
flex: 1;
min-width: 0;
}

.ObjectItemInline + .ObjectItemInline {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
// 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 { TextField } from 'office-ui-fabric-react/lib/TextField';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { IContextualMenuItem } from 'office-ui-fabric-react/lib/ContextualMenu';
import { NeutralColors, FontSizes, SharedColors } from '@uifabric/fluent-theme';
import { IAssignmentObject, OBISchema, MicrosoftAdaptiveDialog } from '@bfc/shared';
import { FieldProps } from '@bfcomposer/react-jsonschema-form';
import get from 'lodash/get';

import { BFDFieldProps } from '../../types';
import { swap, remove } from '../../utils';
import { TextWidget } from '../../widgets';

import {
field,
assignmentField,
assignmentItem,
assignmentItemContainer,
assignmentItemLabel,
assignmentItemValue,
assignmentItemValueLabel,
assignmentItemErrorMessage,
} from './styles';

interface AssignmentItemProps extends FieldProps<MicrosoftAdaptiveDialog> {
index: number;
assignment: IAssignmentObject;
hasMoveUp: boolean;
hasMoveDown: boolean;
onReorder: (a: number, b: number) => void;
onDelete: (idx: number) => void;
onEdit: (idx: number, value?: IAssignmentObject) => void;
}

interface AssignmentItemError {
property: string | JSX.Element | undefined;
value: string | JSX.Element | undefined;
}

const AssignmentItem: React.FC<AssignmentItemProps> = props => {
const {
assignment,
index,
onEdit,
hasMoveUp,
hasMoveDown,
onReorder,
onDelete,
schema,
idSchema,
uiSchema,
formContext,
} = props;
const [key, setKey] = useState(`${assignment.value}:${assignment.property}`);
const options = uiSchema['ui:options'];
const getSchema = (field: keyof IAssignmentObject): OBISchema => {
return get(schema, ['items', 'properties', field]);
};
const contextItems: IContextualMenuItem[] = [
{
key: 'moveUp',
text: 'Move Up',
iconProps: { iconName: 'CaretSolidUp' },
disabled: !hasMoveUp,
onClick: () => onReorder(index, index - 1),
},
{
key: 'moveDown',
text: 'Move Down',
iconProps: { iconName: 'CaretSolidDown' },
disabled: !hasMoveDown,
onClick: () => onReorder(index, index + 1),
},
{
key: 'remove',
text: 'Remove',
iconProps: { iconName: 'Cancel' },
onClick: () => onDelete(index),
},
];

const handleEdit = (field: 'value' | 'property') => (val?: string) => {
onEdit(index, { ...assignment, [field]: val });
};

const handleBlur = () => {
setKey(`${assignment.value}:${assignment.property}`);
if (!assignment.value && !assignment.property) {
onDelete(index);
}
};

const [errorMessages, setErrorMessages] = useState<AssignmentItemError>({ property: undefined, value: undefined });

const handleValidation = (field: 'value' | 'property') => (err?: JSX.Element | string) => {
setErrorMessages(errorMessages => ({ ...errorMessages, [field]: err }));
};
return (
<div css={[assignmentItemContainer(), assignmentItem]} key={key}>
<div css={assignmentItemValue}>
<TextWidget
onChange={handleEdit('property')}
value={assignment.property}
schema={getSchema('property')}
id={idSchema.property && idSchema.property.__id.replace('assignments_', `assignments_${index}_`)}
label={formatMessage('Property')}
formContext={formContext}
onBlur={handleBlur}
hiddenErrMessage={true}
onValidate={handleValidation('property')}
options={options}
/>
</div>
<div css={assignmentItemValue}>
<TextWidget
onChange={handleEdit('value')}
value={assignment.value}
schema={getSchema('value')}
id={idSchema.value && idSchema.value.__id.replace('assignments_', `assignments_${index}_`)}
label={formatMessage('Value')}
formContext={formContext}
onBlur={handleBlur}
hiddenErrMessage={true}
onValidate={handleValidation('value')}
options={options}
/>
</div>
<div>
<IconButton
menuProps={{ items: contextItems }}
menuIconProps={{ iconName: 'MoreVertical' }}
ariaLabel={formatMessage('Item Actions')}
styles={{ menuIcon: { color: NeutralColors.black, fontSize: FontSizes.size16 } }}
/>
</div>
<div css={assignmentItemErrorMessage}>{errorMessages && (errorMessages.property || errorMessages.value)}</div>
</div>
);
};

export const AssignmentsField: React.FC<BFDFieldProps> = props => {
const { formData = [], idSchema, onChange } = props;
const [newassignment, setNewassignment] = useState<IAssignmentObject>({ property: '', value: '' });
const [errorMsg, setErrorMsg] = useState<string>('');
const id = idSchema.__id;

const handleReorder = (aIdx: number, bIdx: number) => {
onChange(swap(formData, aIdx, bIdx));
};

const handleDelete = (idx: number) => {
onChange(remove(formData, idx));
};

const handleEdit = (idx, val) => {
const assignments = [...formData];
assignments[idx] = val;
onChange(assignments);
};

const handleNewassignmentEdit = (field: 'value' | 'property') => (_e: any, data?: string) => {
setNewassignment({ ...newassignment, [field]: data });
};

const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key.toLowerCase() === 'enter') {
e.preventDefault();

if (newassignment) {
if (newassignment.value) {
onChange([...formData, newassignment]);
setNewassignment({ property: '', value: '' });
setErrorMsg('');
} else {
setErrorMsg(formatMessage('value required'));
}
}
}
};

return (
<div>
<div css={[assignmentItemContainer('flex-start'), assignmentItemLabel]}>
<div css={[assignmentItemValue, assignmentItemValueLabel]}>{formatMessage('property')}</div>
<div css={[assignmentItemValue, assignmentItemValueLabel]}>{formatMessage('value')}</div>
</div>
<div css={assignmentField}>
{Array.isArray(formData) &&
formData.map((c, i) => (
<AssignmentItem
key={`${i}-${formData.length}`}
assignment={c}
index={i}
onEdit={handleEdit}
onReorder={handleReorder}
onDelete={handleDelete}
hasMoveDown={i !== formData.length - 1}
hasMoveUp={i !== 0}
{...props}
/>
))}
</div>
<div css={field}>
<div css={assignmentItemContainer('flex-start')} onKeyDown={handleKeyDown}>
<div css={assignmentItemValue}>
<TextField
id={`${id}-property`}
value={newassignment ? newassignment.property : ''}
onChange={handleNewassignmentEdit('property')}
placeholder={formatMessage('Property (named location to store information).')}
autoComplete="off"
/>
</div>
<div css={assignmentItemValue}>
<TextField
id={`${id}-value`}
value={newassignment ? newassignment.value : ''}
onChange={handleNewassignmentEdit('value')}
placeholder={formatMessage('New value or expression.')}
autoComplete="off"
errorMessage={errorMsg}
iconProps={{
iconName: 'ReturnKey',
style: { color: SharedColors.cyanBlue10, opacity: 0.6 },
}}
/>
</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>
</div>
</div>
);
};
Loading