Skip to content

Commit

Permalink
Merge branch 'main' into tachou/orchUpdatePackage
Browse files Browse the repository at this point in the history
  • Loading branch information
taicchoumsft authored Apr 6, 2021
2 parents b8c89cb + da58480 commit 6caffda
Show file tree
Hide file tree
Showing 42 changed files with 742 additions and 371 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"NODE_ENV": "development",
"DEBUG": "composer*",
"COMPOSER_DEV_TOOLS": "true",
"COMPOSER_ENABLE_ONEAUTH": "false"
"COMPOSER_ENABLE_ONEAUTH": "true"
},
"outputCapture": "std",
"preLaunchTask": "electron: build",
Expand Down
24 changes: 7 additions & 17 deletions Composer/cypress/integration/CreateNewBot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,15 @@ context('Creating a new bot', () => {
});

it('can create a new bot', () => {
cy.findByTestId('Create from scratch').click();
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(3000);
cy.findByTestId('@microsoft/generator-bot-empty').click();
cy.findByTestId('NextStepButton').click();
cy.enterTextAndSubmit('NewDialogName', '__TestNewProject', 'SubmitNewBotBtn');
cy.enterTextAndSubmit('NewDialogName', 'TestNewProject3', 'SubmitNewBotBtn');
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(150000);
cy.findByTestId('ProjectTree').within(() => {
cy.findAllByText('__TestNewProject').should('exist');
});
});

it('can create a bot from the ToDo template', () => {
cy.findByTestId('Create from template').click();
cy.findByTestId('TodoSample').click({ force: true });
cy.findByTestId('NextStepButton').click();
cy.enterTextAndSubmit('NewDialogName', '__TestNewProject2', 'SubmitNewBotBtn');
cy.findByTestId('ProjectTree').within(() => {
cy.findAllByText('__TestNewProject2').should('exist');
cy.findByText('addtodo').should('exist');
cy.findByText('cleartodos').should('exist');
cy.findByText('deletetodo').should('exist');
cy.findByText('showtodos').should('exist');
cy.findAllByText('TestNewProject3').should('exist');
});
});
});
2 changes: 0 additions & 2 deletions Composer/cypress/integration/HomePage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ context('Home Page ', () => {
it('can open buttons in home page', () => {
cy.findByTestId('LeftNav-CommandBarButtonHome').click();
cy.findByTestId('homePage-Toolbar-New').click();
cy.findByText('Create bot from template or scratch?').should('exist');
cy.findByText('Cancel').should('exist');
cy.findByText('Cancel').click();
cy.findByTestId('homePage-Toolbar-Open').click();
cy.findByText('Select a Bot').should('exist');
cy.findByText('Cancel').should('exist');
cy.findByText('Cancel').click();
cy.findByTestId('homePage-body-New').click();
cy.findByText('Create bot from template or scratch?').should('exist');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ context('Navigate Url', () => {
cy.visit('/home');
});

it('should open Create From Scratch/Template window from a url', () => {
it('should open Select Template window from a url', () => {
cy.visit('/projects/create');
cy.get('[data-testid="Create from scratch"]').should('be.visible');
cy.get('[data-testid="Create from template"]').should('be.visible');
cy.findAllByTestId('dotnetFeed').should('exist');
});

it('should open Define Conversations window from a url', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('<CreationFlow/>', () => {
onboardingAddCoachMarkRef: jest.fn(),
fetchRecentProjects: jest.fn(),
fetchTemplates: jest.fn(),
fetchTemplatesV2: jest.fn(),
setCreationFlowStatus: jest.fn(),
navTo: jest.fn(),
saveTemplateId: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ describe('<CreateOptionsV2/>', () => {
id: 'generator-conversational-core',
index: 0,
name: 'conversational-core',
dotnetSupport: { webAppSupported: true, functionsSupported: true },
nodeSupport: { webAppSupported: true, functionsSupported: true },
package: {
packageName: 'generator-conversational-core',
packageSource: 'npm',
Expand All @@ -44,10 +46,10 @@ describe('<CreateOptionsV2/>', () => {

it('should save conversational core template id', async () => {
const component = renderComponent();
const conversationalCoreBot = await component.findByText('conversational-core');
const conversationalCoreBot = await component.findByTestId('generator-conversational-core');
fireEvent.click(conversationalCoreBot);
const nextButton = await component.findByText('Next');
fireEvent.click(nextButton);
expect(handleCreateNextMock).toBeCalledWith('generator-conversational-core');
expect(handleCreateNextMock).toBeCalledWith('generator-conversational-core', 'dotnet');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('<CreationFlowV2/>', () => {
onboardingAddCoachMarkRef: jest.fn(),
fetchRecentProjects: jest.fn(),
fetchTemplates: jest.fn(),
fetchTemplatesV2: jest.fn(),
setCreationFlowStatus: jest.fn(),
navTo: jest.fn(),
saveTemplateId: jest.fn(),
Expand Down Expand Up @@ -71,7 +72,7 @@ describe('<CreationFlowV2/>', () => {
</RecoilRoot>
);

navigate('create/generator-conversational-core');
navigate('create/dotnet/generator-conversational-core');
const node = await findByText('OK');

act(() => {
Expand All @@ -94,8 +95,13 @@ describe('<CreationFlowV2/>', () => {
eTag: undefined,
preserveRoot: undefined,
qnqKbUrls: undefined,
runtimeType: 'webapp',
templateDir: undefined,
urlSuffix: undefined,
profile: undefined,
qnaKbUrls: undefined,
runtimeLanguage: 'dotnet',
source: undefined,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import { DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
import { BotTemplate } from '@bfc/shared';
import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { RouteComponentProps, navigate } from '@reach/router';
import { useRecoilValue } from 'recoil';
import querystring from 'query-string';
import axios from 'axios';

import { DialogCreationCopy } from '../../constants';
import { featureFlagsState } from '../../recoilModel';
import { getAliasFromPayload } from '../../utils/electronUtil';

import { CreateBot } from './CreateBot';
Expand All @@ -34,11 +32,8 @@ export function CreateOptions(props: CreateOptionsProps) {
const [option, setOption] = useState('Create');
const [isOpenCreateModal, setIsOpenCreateModal] = useState(false);
const { templates, onDismiss, onNext, onJumpToOpenModal } = props;
const featureFlags = useRecoilValue(featureFlagsState);
useEffect(() => {
if (featureFlags.NEW_CREATION_FLOW?.enabled) {
navigate(`/v2/projects/create${props?.location?.search}`);
}
navigate(`/v2/projects/create${props?.location?.search}`);
});

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ import Path from 'path';
import React, { useEffect, useRef, Fragment } from 'react';
import { RouteComponentProps, Router, navigate } from '@reach/router';
import { useRecoilValue } from 'recoil';
import { csharpFeedKey } from '@bfc/shared';

import { CreationFlowStatus, feedDictionary } from '../../constants';
import { CreationFlowStatus, firstPartyTemplateFeed } from '../../constants';
import {
dispatcherState,
creationFlowStatusState,
storagesState,
focusedStorageFolderState,
currentProjectIdState,
userSettingsState,
featureFlagsState,
templateProjectsState,
} from '../../recoilModel';
import Home from '../../pages/home/Home';
Expand All @@ -33,7 +31,6 @@ type CreationFlowProps = RouteComponentProps<{}>;

const CreationFlow: React.FC<CreationFlowProps> = (props: CreationFlowProps) => {
const {
fetchTemplates,
fetchTemplatesV2,
fetchRecentProjects,
fetchStorages,
Expand All @@ -51,7 +48,6 @@ const CreationFlow: React.FC<CreationFlowProps> = (props: CreationFlowProps) =>
} = useRecoilValue(dispatcherState);

const templateProjects = useRecoilValue(templateProjectsState);
const featureFlags = useRecoilValue(featureFlagsState);
const creationFlowStatus = useRecoilValue(creationFlowStatusState);
const projectId = useRecoilValue(currentProjectIdState);
const storages = useRecoilValue(storagesState);
Expand All @@ -78,7 +74,7 @@ const CreationFlow: React.FC<CreationFlowProps> = (props: CreationFlowProps) =>
}
await fetchStorages();
fetchRecentProjects();
featureFlags.NEW_CREATION_FLOW?.enabled ? fetchTemplatesV2([feedDictionary[csharpFeedKey]]) : fetchTemplates();
fetchTemplatesV2([firstPartyTemplateFeed]);
};

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
/** @jsx jsx */
import { jsx, css } from '@emotion/core';
import { useState, Fragment, useEffect, useMemo } from 'react';
import find from 'lodash/find';
import formatMessage from 'format-message';
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
Expand All @@ -17,18 +16,18 @@ import {
CheckboxVisibility,
DetailsRow,
} from 'office-ui-fabric-react/lib/DetailsList';
import { BotTemplate, QnABotTemplateId } from '@bfc/shared';
import { BotTemplate } from '@bfc/shared';
import { DialogWrapper, DialogTypes, LoadingSpinner } from '@bfc/ui-shared';
import { NeutralColors } from '@uifabric/fluent-theme';
import { WindowLocation } from '@reach/router';
import { IPivotItemProps, Pivot, PivotItem } from 'office-ui-fabric-react/lib/Pivot';
import { Link } from 'office-ui-fabric-react/lib/Link';
import { FontIcon } from 'office-ui-fabric-react/lib/Icon';
import { csharpFeedKey } from '@botframework-composer/types';
import { csharpFeedKey, nodeFeedKey } from '@botframework-composer/types';
import { useRecoilState, useRecoilValue } from 'recoil';

import msftIcon from '../../../images/msftIcon.svg';
import { DialogCreationCopy, feedDictionary } from '../../../constants';
import { DialogCreationCopy } from '../../../constants';
import { creationFlowTypeState, fetchReadMePendingState, selectedTemplateReadMeState } from '../../../recoilModel';
import TelemetryClient from '../../../telemetry/TelemetryClient';

Expand Down Expand Up @@ -112,15 +111,13 @@ const optionKeys = {
const templateRequestUrl =
'https://github.com/microsoft/botframework-components/issues/new?assignees=&labels=needs-triage%2C+feature-request&template=-net-sdk-feature-request.md&title=[NewTemplateRequest]';

const defaultTemplateId = '@microsoft/generator-microsoft-bot-empty';

// -------------------- CreateOptions -------------------- //
type CreateBotProps = {
isOpen: boolean;
templates: BotTemplate[];
location?: WindowLocation | undefined;
onDismiss: () => void;
onNext: (templateName: string, urlData?: string) => void;
onNext: (templateName: string, templateLanguage: string, urlData?: string) => void;
fetchTemplates: (feedUrls?: string[]) => Promise<void>;
fetchReadMe: (moduleName: string) => {};
};
Expand All @@ -129,9 +126,11 @@ export function CreateBotV2(props: CreateBotProps) {
const [option] = useState(optionKeys.createFromTemplate);
const [disabled] = useState(false);
const { isOpen, templates, onDismiss, onNext } = props;
const [currentTemplateId, setCurrentTemplateId] = useState(defaultTemplateId);
const [emptyBotKey, setEmptyBotKey] = useState('');
const [selectedFeed, setSelectedFeed] = useState<{ props: IPivotItemProps }>({ props: { itemKey: csharpFeedKey } });
const [currentTemplateId, setCurrentTemplateId] = useState('');
const [selectedProgLang, setSelectedProgLang] = useState<{ props: IPivotItemProps }>({
props: { itemKey: csharpFeedKey },
});
const [displayedTemplates, setDisplayedTemplates] = useState<BotTemplate[]>([]);
const [readMe] = useRecoilState(selectedTemplateReadMeState);
const fetchReadMePending = useRecoilValue(fetchReadMePendingState);
const creationFlowType = useRecoilValue(creationFlowTypeState);
Expand All @@ -140,6 +139,7 @@ export function CreateBotV2(props: CreateBotProps) {
return new Selection({
onSelectionChanged: () => {
const t = selectedTemplate.getSelection()[0] as BotTemplate;

if (t) {
setCurrentTemplateId(t.id);
}
Expand All @@ -148,21 +148,13 @@ export function CreateBotV2(props: CreateBotProps) {
}, []);

const handleJumpToNext = () => {
let routeToTemplate = emptyBotKey;
if (option === optionKeys.createFromTemplate) {
routeToTemplate = currentTemplateId;
}

if (option === optionKeys.createFromQnA) {
routeToTemplate = QnABotTemplateId;
}

TelemetryClient.track('CreateNewBotProjectNextButton', { template: routeToTemplate });
TelemetryClient.track('CreateNewBotProjectNextButton', { template: currentTemplateId });
const runtimeLanguage = selectedProgLang?.props?.itemKey ?? csharpFeedKey;

if (location?.search) {
onNext(routeToTemplate, location.search);
onNext(currentTemplateId, runtimeLanguage, location.search);
} else {
onNext(routeToTemplate);
onNext(currentTemplateId, runtimeLanguage);
}
};

Expand Down Expand Up @@ -200,27 +192,32 @@ export function CreateBotV2(props: CreateBotProps) {
};

const getTemplate = (): BotTemplate | undefined => {
const currentTemplate = templates.find((t) => {
return t.id === currentTemplateId;
const currentTemplate = displayedTemplates.find((t) => {
return t?.id === currentTemplateId;
});
return currentTemplate;
};

useEffect(() => {
if (templates.length > 1) {
const emptyBotTemplate = find(templates, ['id', defaultTemplateId]);
if (emptyBotTemplate) {
setCurrentTemplateId(emptyBotTemplate.id);
setEmptyBotKey(emptyBotTemplate.id);
}
const itemKey = selectedProgLang.props.itemKey;
if (itemKey === csharpFeedKey) {
const newTemplates = templates.filter((template) => {
return template.dotnetSupport;
});
setDisplayedTemplates(newTemplates);
} else if (itemKey === nodeFeedKey) {
const newTemplates = templates.filter((template) => {
return template.nodeSupport;
});
setDisplayedTemplates(newTemplates);
}
}, [templates]);
}, [templates, selectedProgLang]);

useEffect(() => {
if (selectedFeed?.props?.itemKey) {
props.fetchTemplates([feedDictionary[selectedFeed.props.itemKey]]);
if (displayedTemplates?.[0]?.id) {
setCurrentTemplateId(displayedTemplates[0].id);
}
}, [selectedFeed]);
}, [displayedTemplates]);

useEffect(() => {
if (currentTemplateId) {
Expand All @@ -238,11 +235,12 @@ export function CreateBotV2(props: CreateBotProps) {
defaultSelectedKey={csharpFeedKey}
onLinkClick={(item) => {
if (item) {
setSelectedFeed(item);
setSelectedProgLang(item);
}
}}
>
<PivotItem headerText="C#" itemKey={csharpFeedKey}></PivotItem>
<PivotItem data-testid="dotnetFeed" headerText="C#" itemKey={csharpFeedKey}></PivotItem>
<PivotItem data-testid="nodeFeed" headerText="Node" itemKey={nodeFeedKey}></PivotItem>
</Pivot>
<div css={pickerContainer}>
<div css={detailListContainer} data-is-scrollable="true" id="templatePickerContainer">
Expand All @@ -256,7 +254,7 @@ export function CreateBotV2(props: CreateBotProps) {
compact={false}
getKey={(item) => item.name}
isHeaderVisible={false}
items={templates}
items={displayedTemplates}
layoutMode={DetailsListLayoutMode.justified}
selection={selectedTemplate}
selectionMode={disabled ? SelectionMode.none : SelectionMode.single}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { CreateBotV2 } from './CreateBot';
type CreateOptionsProps = {
templates: BotTemplate[];
onDismiss: () => void;
onNext: (data: string) => void;
onNext: (templateName: string, templateLanguage: string, urlData?: string) => void;
onJumpToOpenModal: (search?: string) => void;
fetchTemplates: (feedUrls?: string[]) => Promise<void>;
fetchReadMe: (moduleName: string) => {};
Expand Down
Loading

0 comments on commit 6caffda

Please sign in to comment.