Skip to content

Commit

Permalink
Merge branch 'main' into tachou/updateOrchCore
Browse files Browse the repository at this point in the history
  • Loading branch information
taicchoumsft committed Dec 9, 2020
2 parents 1bfd847 + ddc57f2 commit a55bc4e
Show file tree
Hide file tree
Showing 21 changed files with 223 additions and 56 deletions.
5 changes: 3 additions & 2 deletions Composer/cypress/integration/LuisDeploy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ context('Luis Deploy', () => {

it('can deploy luis success', () => {
cy.visitPage('Project Settings');
cy.findAllByTestId('rootLUISKey').type('12345678', { delay: 200 });
cy.findAllByTestId('rootLUISRegion').type('westus', { delay: 200 });
cy.findAllByTestId('rootLUISAuthoringKey').type('12345678', { delay: 200 });
cy.findAllByTestId('rootLUISRegion').click();
cy.findByText('westus').click();
cy.visitPage('User Input');
cy.url().should('contain', 'language-understanding/all');
cy.visitPage('Design');
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/client/config/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function getClientEnvironment(publicUrl) {
PUBLIC_URL: publicUrl,
GIT_SHA: getGitSha().toString().replace('\n', ''),
SDK_PACKAGE_VERSION: '4.11.0', // TODO: change this when Composer supports custom schema/custom runtime
COMPOSER_VERSION: '1.2.0',
COMPOSER_VERSION: '1.3.0-rc1',
LOCAL_PUBLISH_PATH:
process.env.LOCAL_PUBLISH_PATH || path.resolve(process.cwd(), '../../../extensions/localPublish/hostedBots'),
}
Expand Down
33 changes: 26 additions & 7 deletions Composer/packages/client/src/components/EditableField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { IIconProps } from 'office-ui-fabric-react/lib/Icon';

import { FieldConfig, useForm } from '../hooks/useForm';

const allowedNavigationKeys = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End'];

//------------------------
const defaultContainerStyle = (hasFocus, hasErrors) => css`
display: flex;
Expand All @@ -36,6 +39,17 @@ const defaultContainerStyle = (hasFocus, hasErrors) => css`
// turncat to show two line.
const maxCharacterNumbers = 120;

const isMultiLineText = (value?: string): boolean => {
if (!value) return false;
const valueTrimmed = value.trim();
return (
valueTrimmed.length > maxCharacterNumbers ||
valueTrimmed.includes('\r') ||
valueTrimmed.includes('\r\n') ||
valueTrimmed.includes('\n')
);
};

//------------------------
type IconProps = {
iconStyles?: Partial<IIconProps>;
Expand Down Expand Up @@ -122,13 +136,13 @@ const EditableField: React.FC<EditableFieldProps> = (props) => {
}, [value]);

useEffect(() => {
if (formData.value.length > maxCharacterNumbers) {
if (isMultiLineText(formData.value)) {
setMultiline(true);
return;
}

if (expanded || hasFocus) {
if (formData.value.length > maxCharacterNumbers) {
if (isMultiLineText(formData.value)) {
setMultiline(true);
}
}
Expand All @@ -142,7 +156,7 @@ const EditableField: React.FC<EditableFieldProps> = (props) => {
};

const handleChange = (_e: any, newValue?: string) => {
if (newValue && newValue?.length > maxCharacterNumbers) setMultiline(true);
if (isMultiLineText(newValue)) setMultiline(true);
updateField('value', newValue);
setHasBeenEdited(true);
onChange(newValue);
Expand Down Expand Up @@ -171,12 +185,17 @@ const EditableField: React.FC<EditableFieldProps> = (props) => {
fieldRef.current?.blur();
};

// single line, press Enter to submit
// multipe line, press Enter to submit, Shift+Enter get a new line,
// press Enter to submit, Shift+Enter get a new line,
const handleOnKeyDown = (e) => {
// This prevents host DetailsList's FocusZone from stealing the focus and consuming the navigation keys.
if (allowedNavigationKeys.includes(e.key)) {
e.stopPropagation();
}
const enterOnField = e.key === 'Enter' && hasFocus;
const multilineEnter = multiline ? !e.shiftKey : true;
if (enterOnField && multilineEnter) {
if (enterOnField && !multiline) {
setMultiline(true);
}
if (enterOnField && !e.shiftKey) {
handleCommit();
}
if (e.key === 'Escape') {
Expand Down
13 changes: 10 additions & 3 deletions Composer/packages/client/src/pages/botProject/PublishTargets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const publishTargetsHeader = css`
`;

const publishTargetsHeaderText = css`
width: 200px;
width: 300px;
font-size: ${FontSizes.medium};
font-weight: ${FontWeights.semibold};
border-bottom: 1px solid ${NeutralColors.gray30};
Expand All @@ -59,6 +59,9 @@ const publishTargetsItemText = css`
border-bottom: 1px solid ${NeutralColors.gray30};
padding-top: 10px;
padding-left: 10px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;

const addPublishProfile = {
Expand Down Expand Up @@ -212,8 +215,12 @@ export const PublishTargets: React.FC<PublishTargetsProps> = (props) => {
{publishTargets?.map((p, index) => {
return (
<div key={index} css={publishTargetsItem}>
<div css={publishTargetsItemText}>{p.name} </div>
<div css={publishTargetsItemText}>{p.type} </div>
<div css={publishTargetsItemText} title={p.name}>
{p.name}
</div>
<div css={publishTargetsItemText} title={p.type}>
{p.type}
</div>
<div css={publishTargetsEditButton}>
<ActionButton styles={editPublishProfile} onClick={async () => await onEdit(index, p)}>
{formatMessage('Edit')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ const TableView: React.FC<TableViewProps> = (props) => {
onBlur={(_id, value) => {
const newValue = value?.trim();
if (newValue) {
handleTemplateUpdate(item.name, { ...item, body: newValue });
// prefix with - to body
const fixedBody =
!newValue.startsWith('-') && !newValue.startsWith('[') ? `- ${newValue}` : newValue;
handleTemplateUpdate(item.name, { ...item, body: fixedBody });
}
}}
onChange={() => {}}
Expand Down Expand Up @@ -285,7 +288,13 @@ const TableView: React.FC<TableViewProps> = (props) => {
name={text}
value={text}
onBlur={(_id, value) => {
handleTemplateUpdate(item.name, { ...item, body: value });
const newValue = value?.trim();
if (newValue) {
// prefix with - to body
const fixedBody =
!newValue.startsWith('-') && !newValue.startsWith('[') ? `- ${newValue}` : newValue;
handleTemplateUpdate(item.name, { ...item, body: fixedBody });
}
}}
onChange={() => {}}
/>
Expand Down Expand Up @@ -315,7 +324,10 @@ const TableView: React.FC<TableViewProps> = (props) => {
onBlur={(_id, value) => {
const newValue = value?.trim();
if (newValue) {
handleTemplateUpdateDefaultLocale(item.name, { ...item, body: newValue });
// prefix with - to body
const fixedBody =
!newValue.startsWith('-') && !newValue.startsWith('[') ? `- ${newValue}` : newValue;
handleTemplateUpdateDefaultLocale(item.name, { ...item, body: fixedBody });
}
}}
onChange={() => {}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ const TableView: React.FC<TableViewProps> = (props) => {
onBlur={(_id, value) => {
const newValue = value?.trim();
if (newValue) {
handleIntentUpdate(item.fileId, item.name, { Name: item.name, Body: newValue });
const fixedBody = newValue.startsWith('-') ? newValue : `- ${newValue}`;
handleIntentUpdate(item.fileId, item.name, { Name: item.name, Body: fixedBody });
}
}}
onChange={() => {}}
Expand Down Expand Up @@ -273,7 +274,8 @@ const TableView: React.FC<TableViewProps> = (props) => {
onBlur={(_id, value) => {
const newValue = value?.trim().replace(/^#/, '');
if (newValue) {
handleIntentUpdate(item.fileId, item.name, { Name: item.name, Body: newValue });
const fixedBody = newValue.startsWith('-') ? newValue : `- ${newValue}`;
handleIntentUpdate(item.fileId, item.name, { Name: item.name, Body: fixedBody });
}
}}
onChange={() => {}}
Expand Down Expand Up @@ -304,9 +306,10 @@ const TableView: React.FC<TableViewProps> = (props) => {
onBlur={(_id, value) => {
const newValue = value?.trim().replace(/^#/, '');
if (newValue) {
const fixedBody = newValue.startsWith('-') ? newValue : `- ${newValue}`;
handleTemplateUpdateDefaultLocale(item.name, {
Name: item.name,
Body: newValue,
Body: fixedBody,
});
}
}}
Expand Down
18 changes: 14 additions & 4 deletions Composer/packages/client/src/pages/publish/BotStatusList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,14 @@ export const BotStatusList: React.FC<IBotStatusListProps> = (props) => {
};
const onRenderOption = (option?: IDropdownOption): JSX.Element | null => {
if (!option) return null;
return <div style={option.data && option.data.style}>{option.text}</div>;
const style = {
...(option.data && option.data.style),
width: '80%',
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
};
return <div style={style}>{option.text}</div>;
};
const onRenderStatus = (item: IBotStatus): JSX.Element | null => {
if (!item.status) {
Expand Down Expand Up @@ -167,8 +174,8 @@ export const BotStatusList: React.FC<IBotStatusListProps> = (props) => {
name: formatMessage('Publish target'),
className: 'publishTarget',
fieldName: 'target',
minWidth: 114,
maxWidth: 134,
minWidth: 180,
maxWidth: 200,
isRowHeader: true,
isResizable: true,
data: 'string',
Expand All @@ -178,7 +185,10 @@ export const BotStatusList: React.FC<IBotStatusListProps> = (props) => {
defaultSelectedKey={item.publishTarget}
options={publishTargetOptions(item)}
placeholder={formatMessage('Select a publish target')}
styles={{ root: { width: '134px' } }}
styles={{
root: { width: '100%' },
dropdownItems: { selectors: { '.ms-Button-flexContainer': { width: '100%' } } },
}}
onChange={(_, option?: IDropdownOption) => handleChangePublishTarget(item, option)}
onRenderOption={onRenderOption}
/>
Expand Down
13 changes: 11 additions & 2 deletions Composer/packages/client/src/pages/publish/Publish.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,23 @@ const Publish: React.FC<RouteComponentProps<{ projectId: string; targetName?: st
<ActionButton
data-testid="publishPage-Toolbar-Publish"
disabled={publishDisabled || selectedBots.length === 0}
styles={{ root: { fontSize: '16px' } }}
onClick={() => setPublishDialogHidden(false)}
>
<svg fill="none" height="15" viewBox="0 0 16 15" width="16" xmlns="http://www.w3.org/2000/svg">
<svg
css={{ margin: '0 4px' }}
fill="none"
height="15"
viewBox="0 0 16 15"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 4.28906V15H5V0H11.7109L16 4.28906ZM12 4H14.2891L12 1.71094V4ZM15 14V5H11V1H6V14H15ZM0 5H4V6H0V5ZM1 7H4V8H1V7ZM2 9H4V10H2V9Z"
fill={selectedBots.length > 0 && !publishDisabled ? '#0078D4' : 'rgb(161, 159, 157)'}
/>
</svg>
<span css={{ marginLeft: '8px' }}>{formatMessage('Publish selected bots')}</span>
<span css={{ margin: '0 4px' }}>{formatMessage('Publish selected bots')}</span>
</ActionButton>
),
},
Expand All @@ -163,6 +171,7 @@ const Publish: React.FC<RouteComponentProps<{ projectId: string; targetName?: st
const getUpdatedStatus = (target, botProjectId): NodeJS.Timeout => {
// TODO: this should use a backoff mechanism to not overload the server with requests
// OR BETTER YET, use a websocket events system to receive updates... (SOON!)
getPublishStatus(botProjectId, target);
return setInterval(async () => {
getPublishStatus(botProjectId, target);
}, publishStatusInterval);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
import { fireEvent, render } from '@botframework-composer/test-utils';

import { PullConfirmationDialog } from '../pullConfirmationDialog';

describe('<PullConfirmationDialog />', () => {
it('should render', async () => {
const { findByText } = render(<PullConfirmationDialog onConfirm={jest.fn()} onDismiss={jest.fn()} />);
await findByText(
'You are about to pull project files from the selected publish profiles. The current project will be overwritten by the pulled files, and will be saved as a backup automatically. You will be able to retrieve the backup anytime in the future.'
);
});

it('should call onConfirm()', () => {
const onConfirm = jest.fn();
const { getByTestId } = render(<PullConfirmationDialog onConfirm={onConfirm} onDismiss={jest.fn()} />);
fireEvent.click(getByTestId('pull-confirm-button'));

expect(onConfirm).toHaveBeenCalled();
});

it('should call onDismiss()', () => {
const onDismiss = jest.fn();
const { getByTestId } = render(<PullConfirmationDialog onConfirm={jest.fn()} onDismiss={onDismiss} />);
fireEvent.click(getByTestId('pull-cancel-button'));

expect(onDismiss).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/** @jsx jsx */
import { jsx } from '@emotion/core';
import formatMessage from 'format-message';
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react/lib/components/Button';
import { Dialog, DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
import React from 'react';

type PullConfirmationDialogProps = {
onConfirm: () => void;
onDismiss: () => void;
};

export const PullConfirmationDialog: React.FC<PullConfirmationDialogProps> = (props) => {
const { onConfirm, onDismiss } = props;

return (
<Dialog
dialogContentProps={{
title: formatMessage('Pull from selected profile'),
styles: {
content: {
fontSize: 16,
},
},
}}
hidden={false}
minWidth={480}
>
<p>
{formatMessage(
'You are about to pull project files from the selected publish profiles. The current project will be overwritten by the pulled files, and will be saved as a backup automatically. You will be able to retrieve the backup anytime in the future.'
)}
</p>
<p>{formatMessage('Do you want to proceed?')}</p>
<DialogFooter>
<DefaultButton data-testid="pull-cancel-button" text={formatMessage('Cancel')} onClick={onDismiss} />
<PrimaryButton data-testid="pull-confirm-button" text={formatMessage('Pull')} onClick={onConfirm} />
</DialogFooter>
</Dialog>
);
};
12 changes: 10 additions & 2 deletions Composer/packages/client/src/pages/publish/pullDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@ import { dispatcherState, locationState } from '../../recoilModel';

import { PullFailedDialog } from './pullFailedDialog';
import { PullStatus } from './pullStatus';
import { PullConfirmationDialog } from './pullConfirmationDialog';

type PullDialogProps = {
onDismiss: () => void;
projectId: string;
selectedTarget: PublishTarget | undefined;
};

type PullDialogStatus = 'connecting' | 'downloading' | 'error';
type PullDialogStatus = 'confirming' | 'connecting' | 'downloading' | 'error';

const CONNECTING_STATUS_DISPLAY_TIME = 2000;

export const PullDialog: React.FC<PullDialogProps> = (props) => {
const { onDismiss, projectId, selectedTarget } = props;
const [status, setStatus] = useState<PullDialogStatus>('connecting');
const [status, setStatus] = useState<PullDialogStatus>('confirming');
const [error, setError] = useState<string>('');
const { addNotification, reloadProject } = useRecoilValue(dispatcherState);
const botLocation = useRecoilValue(locationState(projectId));
Expand Down Expand Up @@ -83,7 +84,14 @@ export const PullDialog: React.FC<PullDialogProps> = (props) => {
onDismiss();
}, [onDismiss]);

const onConfirm = useCallback(() => {
setStatus('connecting');
}, []);

switch (status) {
case 'confirming':
return <PullConfirmationDialog onConfirm={onConfirm} onDismiss={onCancelOrDone} />;

case 'connecting':
return <PullStatus publishTarget={selectedTarget} state={'connecting'} />;

Expand Down
Loading

0 comments on commit a55bc4e

Please sign in to comment.