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

feature: new design for Connections setting pane #6724

Merged
merged 32 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
84f3510
remodel Adapters section into new design
beyackle Apr 5, 2021
e542c41
better formatting
beyackle Apr 6, 2021
aa6a76a
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 6, 2021
0b3a0b7
fix table formatting
beyackle Apr 6, 2021
6222fad
update l10n strings
beyackle Apr 6, 2021
d9e64d0
Update AdapterSection.tsx
beyackle Apr 6, 2021
c18a0b6
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 6, 2021
4707f1b
Update AdapterSection.tsx
beyackle Apr 6, 2021
153ae2f
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 7, 2021
b6c67a7
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 7, 2021
5a58937
Update AdapterSettings.test.tsx
beyackle Apr 7, 2021
3307f6c
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 7, 2021
7aa4a9d
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 8, 2021
baa3707
Merge branch 'beyackle/adapterRedesign' of https://github.com/microso…
beyackle Apr 8, 2021
f0e228b
Update en-US.json
beyackle Apr 8, 2021
89e06b4
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 8, 2021
f292369
Update en-US.json
beyackle Apr 8, 2021
a3e588f
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 8, 2021
1f74bda
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 8, 2021
95a760b
Update AdapterSettings.test.tsx
beyackle Apr 8, 2021
d49f77a
Merge branch 'beyackle/adapterRedesign' of https://github.com/microso…
beyackle Apr 8, 2021
9184b19
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 8, 2021
1d65484
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 12, 2021
9ca87be
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 13, 2021
342e8e3
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 13, 2021
462de01
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 13, 2021
55afb03
address PR comments
beyackle Apr 14, 2021
576ff54
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 14, 2021
fa33de4
Merge branch 'main' into beyackle/adapterRedesign
tonyanziano Apr 14, 2021
8fdef4b
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 15, 2021
80dd9dd
Merge branch 'main' into beyackle/adapterRedesign
cwhitten Apr 15, 2021
232e76a
Merge branch 'main' into beyackle/adapterRedesign
beyackle Apr 15, 2021
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 @@ -85,7 +85,7 @@ describe('ExternalAdapterSettings', () => {
initRecoilState
);

const link = getByText('the package manager');
const link = getByText(/from package manager/);

expect(link.attributes.getNamedItem('href')?.value).toEqual('plugin/package-manager/package-manager');
});
Expand All @@ -112,7 +112,7 @@ describe('ExternalAdapterSettings', () => {
});

it('sets settings on an adapter', async () => {
const { getByTestId, getByLabelText, getByText, queryByTestId } = renderWithRecoilAndCustomDispatchers(
const { getByTestId, getByLabelText, queryByTestId } = renderWithRecoilAndCustomDispatchers(
<ExternalAdapterSettings projectId={PROJECT_ID} />,
initRecoilState
);
Expand All @@ -123,8 +123,9 @@ describe('ExternalAdapterSettings', () => {
});

await act(async () => {
const modal = getByTestId('adapterModal');
await userEvent.type(getByLabelText('Example Name'), 'test text 12345', { delay: 50 });
userEvent.click(getByText('Create'));
userEvent.click(within(modal).getByText('Configure'));
});

const modal = queryByTestId('adapterModal');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, { useEffect, useState, Fragment } from 'react';
import { jsx } from '@emotion/core';
import formatMessage from 'format-message';
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { Link } from 'office-ui-fabric-react/lib/Link';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
Expand All @@ -29,12 +28,10 @@ import { getTokenFromCache, isShowAuthDialog, userShouldProvideTokens } from '..
import httpClient from '../../../utils/httpUtil';
import { dispatcherState } from '../../../recoilModel';
import {
tableHeaderRow,
tableRow,
tableRowItem,
tableColumnHeader,
labelContainer,
customerLabel,
unknownIconStyle,
errorContainer,
errorIcon,
errorTextStyle,
Expand Down Expand Up @@ -420,17 +417,6 @@ export const ABSChannels: React.FC<RuntimeSettingsProps> = (props) => {
}
};

const onRenderLabel = (props) => {
return (
<div css={labelContainer}>
<div css={customerLabel}> {props.label} </div>
<TooltipHost content={props.label}>
<Icon iconName="Unknown" styles={unknownIconStyle(props.required)} />
</TooltipHost>
</div>
);
};

/* Copied from BotStatusList.tx */
const renderDropdownOption = (option?: IDropdownOption): JSX.Element | null => {
if (!option) return null;
Expand Down Expand Up @@ -527,12 +513,12 @@ export const ABSChannels: React.FC<RuntimeSettingsProps> = (props) => {
const absTableRow = (channel: string, name: string, link: string) => (
<div key={channel} css={tableRow}>
<div css={tableRowItem(columnSizes[0])}>{name}</div>
<div css={tableRowItem(columnSizes[1])}>
<div css={tableRowItem(columnSizes[1])}>{absTableToggle(channel)}</div>
<div css={tableRowItem(columnSizes[2])}>
<Link href={link} target="_docs">
{formatMessage('Learn more')}
</Link>
</div>
<div css={tableRowItem(columnSizes[2])}>{absTableToggle(channel)}</div>
</div>
);

Expand Down Expand Up @@ -562,16 +548,14 @@ export const ABSChannels: React.FC<RuntimeSettingsProps> = (props) => {
/>
<div>
<Dropdown
label={formatMessage('Publish profile to configure:')}
options={publishTargetOptions}
placeholder={formatMessage('Choose publishing profile')}
placeholder={formatMessage('Select publishing profile')}
styles={{
root: { display: 'flex', alignItems: 'center', marginBottom: 10 },
label: { width: 200 },
dropdown: { width: 300 },
}}
onChange={onSelectProfile}
onRenderLabel={onRenderLabel}
onRenderOption={renderDropdownOption}
/>

Expand All @@ -585,14 +569,13 @@ export const ABSChannels: React.FC<RuntimeSettingsProps> = (props) => {
return { key: p.subscriptionId ?? '', text: p.displayName ?? 'Unnamed' };
}) ?? []
}
placeholder={formatMessage('Choose subscription')}
placeholder={formatMessage('Select publishing profile')}
styles={{
root: { display: 'flex', alignItems: 'center', marginBottom: 10 },
label: { width: 200 },
dropdown: { width: 300 },
}}
onChange={onChangeSubscription}
onRenderLabel={onRenderLabel}
/>
)}
{isLoading && <LoadingSpinner />}
Expand All @@ -604,10 +587,10 @@ export const ABSChannels: React.FC<RuntimeSettingsProps> = (props) => {
)}
{currentResource && channelStatus && (
<Fragment>
<div css={tableRow}>
<div css={tableHeaderRow}>
<div css={tableColumnHeader(columnSizes[0])}>{formatMessage('Name')}</div>
<div css={tableColumnHeader(columnSizes[1])}>{formatMessage('Documentation')}</div>
<div css={tableColumnHeader(columnSizes[2])}>{formatMessage('Enabled')}</div>
<div css={tableColumnHeader(columnSizes[1])}>{formatMessage('Enabled')}</div>
<div css={tableColumnHeader(columnSizes[2])}>{formatMessage('Documentation')}</div>
</div>
{absTableRow(CHANNELS.TEAMS, formatMessage('MS Teams'), teamsHelpLink)}
{absTableRow(CHANNELS.WEBCHAT, formatMessage('Web Chat'), webchatHelpLink)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
import { jsx } from '@emotion/core';
import { useEffect, useRef } from 'react';
import formatMessage from 'format-message';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip';
import { Stack } from 'office-ui-fabric-react/lib/Stack';

import { CollapsableWrapper } from '../../../components/CollapsableWrapper';
import { title, subtitle, sectionHeader } from '../styles';
import { title, subtitle } from '../styles';

import ExternalAdapterSettings from './ExternalAdapterSettings';
import ABSChannels from './ABSChannels';
Expand All @@ -18,17 +17,6 @@ type Props = {
scrollToSectionId?: string;
};

const renderSectionHeader = (name: string, tooltip?: string) => (
<div css={sectionHeader}>
{name}
{tooltip != null && (
<TooltipHost content={tooltip} styles={{ root: { paddingLeft: '4px' } }}>
<Icon iconName="Unknown" />
</TooltipHost>
)}
</div>
);

const AdapterSection = ({ projectId, scrollToSectionId }: Props) => {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
Expand All @@ -39,12 +27,25 @@ const AdapterSection = ({ projectId, scrollToSectionId }: Props) => {

return (
<div ref={containerRef}>
<CollapsableWrapper title={formatMessage('Adapters')} titleStyle={title}>
<div css={subtitle}>{formatMessage('Connect your bot to other messaging services.')}</div>
{renderSectionHeader(formatMessage('Azure Bot Service channels'), '(description of ABS channels)')}
<ABSChannels projectId={projectId} />
{renderSectionHeader(formatMessage('External service adapters'), '(description of external adapters)')}
<ExternalAdapterSettings projectId={projectId} />
<CollapsableWrapper title={formatMessage('Connections')} titleStyle={title}>
<Stack
tokens={{
padding: '6px 0',
}}
>
<div css={title}>{formatMessage('Azure connections')}</div>
<div css={subtitle}>
{formatMessage(
'Connect your bot to Microsoft Teams and WebChat, or enable speech. Connections are added per bot (typically to the root bot, if your project contains multiple bots), as well as per publishing profile. Select a publishing profile to view, add, and enable Azure connections.'
)}
</div>
<ABSChannels projectId={projectId} />
</Stack>
<Stack>
<div css={title}>{formatMessage('External connections')}</div>
<div css={subtitle}>{formatMessage('Find and install more external services in the package manager.')}</div>
<ExternalAdapterSettings projectId={projectId} />
</Stack>
</CollapsableWrapper>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ type Props = {
adapterKey: string;
packageName: string;
isOpen: boolean;
isFirstTime: boolean; // true if the user clicked Configure to get here, false if it's from the Edit menu
onClose: () => void;
projectId: string;
schema: JSONSchema7;
Expand All @@ -45,7 +44,7 @@ function makeDefault(schema: JSONSchema7) {
}

const AdapterModal = (props: Props) => {
const { isOpen, onClose, schema, uiSchema, projectId, adapterKey, packageName, isFirstTime } = props;
const { isOpen, onClose, schema, uiSchema, projectId, adapterKey, packageName } = props;

const [value, setValue] = useState(props.value ?? makeDefault(schema));
const { setSettings } = useRecoilValue(dispatcherState);
Expand Down Expand Up @@ -114,7 +113,7 @@ const AdapterModal = (props: Props) => {
onClose();
}}
>
{isFirstTime ? formatMessage('Create') : formatMessage('Confirm')}
{formatMessage('Configure')}
</PrimaryButton>
</DialogFooter>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,13 @@ import formatMessage from 'format-message';
import { useRecoilValue } from 'recoil';
import { BotSchemas, DialogSetting } from '@bfc/shared';
import { Link } from 'office-ui-fabric-react/lib/Link';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { TooltipHost, DirectionalHint } from 'office-ui-fabric-react/lib/Tooltip';
import { SharedColors } from '@uifabric/fluent-theme';
import { JSONSchema7 } from '@botframework-composer/types';
import { AdapterRecord } from '@botframework-composer/types/src';

import { useRouterCache } from '../../../utils/hooks';
import { schemasState, settingsState, dispatcherState } from '../../../recoilModel';
import { subtitle, tableRow, tableRowItem, tableColumnHeader, columnSizes } from '../styles';
import { subtitle, tableHeaderRow, tableRow, tableRowItem, tableColumnHeader, columnSizes } from '../styles';

import AdapterModal, { hasRequired } from './ExternalAdapterModal';

Expand All @@ -28,6 +24,11 @@ type Props = {
projectId: string;
};

type Package = {
key: string;
packageName?: string;
};

const ExternalAdapterSettings = (props: Props) => {
const { projectId } = props;

Expand All @@ -41,40 +42,29 @@ const ExternalAdapterSettings = (props: Props) => {
const { definitions: schemaDefinitions } = schemas?.sdk?.content ?? {};
const uiSchemas = schemas?.ui?.content ?? {};

const [currentModalProps, setModalProps] = useState<
{ key: string; packageName: string; firstTime: boolean } | undefined
>();
const [currentModalProps, setModalProps] = useState<Package | undefined>();

const onModalOpen = (pkg: Package) => () => {
setModalProps(pkg);
};

const openModal = (key?: string, firstTime?: boolean, packageName?: string) => {
if (key == null || packageName == null || firstTime == null) {
setModalProps(undefined);
} else {
setModalProps({ key, packageName, firstTime });
}
const onModalClose = () => {
setModalProps(undefined);
};

if (schemaDefinitions == null) return null;

const externalServices = (schemas: (JSONSchema7 & { key: string; packageName?: string; firstTime?: boolean })[]) => (
const externalServices = (schemas: (JSONSchema7 & Package)[]) => (
<div role="table">
<div css={subtitle}>
{formatMessage.rich('Install more adapters in <a>the package manager</a>.', {
a: ({ children }) => (
<Link key="subtitle-link" href={packageManagerLink}>
{children}
</Link>
),
})}
</div>
<div css={tableRow} role="row">
<div css={tableHeaderRow} role="row">
<div css={tableColumnHeader(columnSizes[0])} role="columnheader">
{formatMessage('Name')}
</div>
<div css={tableColumnHeader(columnSizes[1])} role="columnheader">
{formatMessage('Configured')}
{formatMessage('Enabled')}
</div>
<div css={tableColumnHeader(columnSizes[2])} role="columnheader">
{formatMessage('Enabled')}
{formatMessage('Configuration')}
</div>
</div>

Expand All @@ -93,23 +83,6 @@ const ExternalAdapterSettings = (props: Props) => {
{title}
</div>
<div css={tableRowItem(columnSizes[1])} role="cell">
{keyConfigured ? (
<Icon
aria-label={formatMessage('Configured')}
iconName="CheckMark"
styles={{ root: { color: SharedColors.green10, fontSize: '18px' } }}
/>
) : (
<Link
key={key}
ariaLabel={formatMessage('Configure {title}', { title })}
onClick={() => openModal(key, true, packageName)}
>
{formatMessage('Configure')}
</Link>
)}
</div>
<div css={tableRowItem(columnSizes[2])} role="cell">
<Toggle
ariaLabel={formatMessage('{title} connection', { title })}
checked={keyEnabled}
Expand All @@ -134,31 +107,11 @@ const ExternalAdapterSettings = (props: Props) => {
}}
/>
</div>
<TooltipHost content={formatMessage('Actions')} directionalHint={DirectionalHint.rightCenter}>
<IconButton
ariaLabel={formatMessage('Actions')}
className="dialog-more-btn"
data-testid="dialogMoreButton"
menuIconProps={{ iconName: 'MoreVertical' }}
menuProps={{
items: [
{
key: 'edit',
text: formatMessage('Edit'),
iconProps: { iconName: 'Edit' },
onClick: () => openModal(key, false, packageName),
},
],
}}
role="cell"
styles={{ root: { paddingTop: '10px', paddingBottom: '10px' } }}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.stopPropagation();
}
}}
/>
</TooltipHost>
<div css={tableRowItem(columnSizes[2])} role="cell">
<Link key={key} onClick={onModalOpen({ key, packageName })}>
{formatMessage('Configure')}
</Link>
</div>
</div>
);
})}
Expand All @@ -176,19 +129,25 @@ const ExternalAdapterSettings = (props: Props) => {
return (
<Fragment>
<div data-testid="adapterSettings">{externalServices(adapterSchemas)}</div>
<div key={'subtitle'} css={subtitle}>
{formatMessage.rich('<a>Add from package manager</a>.', {
a: ({ children }) => (
<Link key="link" href={packageManagerLink}>
{children}
</Link>
),
})}
</div>
{currentKey != null && currentPackageName != null && schemaDefinitions[currentKey] != null && (
<AdapterModal
isOpen
adapterKey={currentKey}
isFirstTime={currentModalProps?.firstTime ?? false}
packageName={currentPackageName}
projectId={projectId}
schema={schemaDefinitions[currentKey]}
uiSchema={uiSchemas?.[currentKey]?.form}
value={currentSettings[currentPackageName]}
onClose={() => {
openModal(undefined);
}}
onClose={onModalClose}
/>
)}
</Fragment>
Expand Down
Loading