Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
29 changes: 25 additions & 4 deletions Composer/cypress/integration/LUPage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,30 @@ context('check language understanding page', () => {
});

it('can open language understanding page', () => {
cy.visit(Cypress.env('COMPOSER_URL') + '/language-understanding/ToDoLuisBot');
cy.get('[data-testid="LUEditor"]').within(() => {
cy.getByText('ToDoLuisBot.lu').should('exist');
});
cy.visit(Cypress.env('COMPOSER_URL') + '/language-understanding');

// left nav tree
cy.contains('ToDoLuisBot');
cy.contains('All');

cy.get('.toggleEditMode button').as('switchButton');

// all multiple file, edit mode button is disabled.
cy.get('@switchButton').should('be.disabled');

// by default is table view
cy.get('[data-testid="LUEditor"] [data-testid="table-view"]').should('exist');

// nav to ToDoLuisBot.main dialog
cy.get('.dialogNavTree button[title="ToDoLuisBot"]').click();
cy.wait(300);

// goto edit-mode
cy.get('@switchButton').click();
cy.get('[data-testid="LUEditor"] .monaco-editor').should('exist');

// back to all table view
cy.get('.dialogNavTree button[title="All"]').click();
cy.get('[data-testid="LUEditor"] [data-testid="table-view"]').should('exist');
});
});
17 changes: 8 additions & 9 deletions Composer/cypress/integration/LuisDeploy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
context('Luis Deploy', () => {
beforeEach(() => {
cy.server();
cy.route('GET', '/api/launcher/connect', 'OK');
cy.route('POST', '/api/launcher/sync', 'OK');

cy.visit(Cypress.env('COMPOSER_URL'));
cy.openBot('ToDoLuisBot');
Expand All @@ -11,30 +13,27 @@ context('Luis Deploy', () => {
it('can deploy luis success', () => {
cy.visit(Cypress.env('COMPOSER_URL') + '/language-understanding/ToDoLuisBot');
cy.get('[data-testid="LUEditor"]').within(() => {
cy.getByText('ToDoLuisBot.lu').should('exist');
cy.getByText('ToDoLuisBot').should('exist');
});

cy.route('POST', '/api/projects/opened/luFiles/publish', 'fixture:luPublish/success').as('publish');

cy.getByText('Publish to Luis').click();
cy.getByText('Connect').click();
cy.get('[data-testid="ProjectNameInput"]').type('MyProject');
cy.get('[data-testid="EnvironmentInput"]').type('composer');
cy.get('[data-testid="AuthoringKeyInput"]').type('0d4991873f334685a9686d1b48e0ff48');
cy.getByText('Publish').click();
cy.wait('@publish')
.its('status')
.should('be', 200);
cy.getByText('Return').should('exist');

cy.getByText('Return').click();
cy.getByText('Reload').should('exist');
cy.getByText('Test in Emulator').should('exist');

cy.route({
method: 'POST',
url: '/api/projects/opened/luFiles/publish',
status: 400,
response: 'fixture:luPublish/error',
});
cy.getByText('Publish to Luis').click();
cy.getByText('Reload').click();
cy.getByText('Try again').click();
cy.get('[data-testid="AuthoringKeyInput"]').type('no-id');
cy.getByText('Publish').click();
});
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const bottomLinks = [
export function App() {
const { state, actions } = useContext(Store);
const [sideBarExpand, setSideBarExpand] = useState('');
const { botStatus, luFiles, luStatus } = state;
const { botName, botStatus, luFiles, luStatus } = state;
const { connectBot, reloadBot, setStorageExplorerStatus, publishLuis } = actions;
useEffect(() => {
actions.fetchProject();
Expand Down Expand Up @@ -161,6 +161,7 @@ export function App() {
</nav>
<div css={rightPanel}>
<ToolBar
botName={botName}
botStatus={botStatus}
connectBot={connectBot}
reloadBot={reloadBot}
Expand Down
13 changes: 7 additions & 6 deletions Composer/packages/client/src/components/ToolBar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { PropTypes } from 'prop-types';
import formatMessage from 'format-message';

import { getDefaultLuisConfig } from '../../utils/luisUtil';
import LuisStorage from '../../utils/luisStorage';

import { headerSub, bot, botButton, actionButton, calloutLabel, calloutDescription, calloutContainer } from './styles';
import { OpenStatus, LuisConfig, Text } from './../../constants';
Expand Down Expand Up @@ -41,21 +41,21 @@ export const ToolBar = props => {
const [calloutVisible, setCalloutVisible] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const botActionRef = useRef(null);
const { botStatus, openStorageExplorer, onPublish, reloadBot, connectBot, luFiles, luStatus } = props;
const { botName, botStatus, openStorageExplorer, onPublish, reloadBot, connectBot, luFiles, luStatus } = props;
const connected = botStatus === 'connected';

function handleClick() {
const config = getDefaultLuisConfig();
const config = LuisStorage.get(botName);
const files = luFiles.filter(f => !!f.content);
const updated =
luStatus.length !== luFiles.length ||
!luStatus.every(item => {
if (item.status === 1) return true;
return false;
}) ||
config[LuisConfig.AUTHORINGKEY] === '';
config[LuisConfig.AUTHORING_KEY] === '';
if (files.length !== 0 && updated) {
if (config[LuisConfig.AUTHORINGKEY] === '') {
if (config[LuisConfig.AUTHORING_KEY] === '') {
setModalOpen(true);
return;
} else {
Expand All @@ -81,7 +81,7 @@ export const ToolBar = props => {

async function handleLoadBot() {
setFetchState(STATE.RELOADING);
await (connected ? reloadBot() : connectBot());
await (connected ? reloadBot(botName) : connectBot(botName));
setFetchState(STATE.SUCCESS);
}

Expand Down Expand Up @@ -178,6 +178,7 @@ export const ToolBar = props => {
handlePublish(config);
setModalOpen(false);
}}
botName={botName}
/>
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { dialog, dialogModal } from './../../pages/language-understanding/styles
import { PublishLuis } from './../../pages/language-understanding/publish-luis-modal';

export function PublishLuisDialog(props) {
const { isOpen, onDismiss, onPublish } = props;
const { isOpen, onDismiss, onPublish, botName } = props;

return (
<Dialog
Expand All @@ -24,7 +24,7 @@ export function PublishLuisDialog(props) {
styles: dialogModal,
}}
>
<PublishLuis onPublish={onPublish} onDismiss={onDismiss} />
<PublishLuis onPublish={onPublish} onDismiss={onDismiss} botName={botName} />
</Dialog>
);
}
Expand Down
13 changes: 7 additions & 6 deletions Composer/packages/client/src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ export const ActionTypes = {
};

export const Tips = {
PROJECTNAME: formatMessage(
PROJECT_NAME: formatMessage(
'Create a name for the project which will be used to name the application: (projectname-environment-LUfilename)'
),
ENVIRONMENT: formatMessage(
'When multiple people are working with models you want to be able to work with models independently from each other tied to the source control.'
),
AUTHORINGKAY: formatMessage('An authoring key is created automatically when you create a LUIS account.'),
AUTHORINGREGION: formatMessage('Authoring region to use [westus,westeurope,australiaeast]'),
DEFAULTLANGUAGE: formatMessage(
AUTHORING_KEY: formatMessage('An authoring key is created automatically when you create a LUIS account.'),
AUTHORING_REGION: formatMessage('Authoring region to use [westus,westeurope,australiaeast]'),
DEFAULT_LANGUAGE: formatMessage(
'Configures default language model to use if there is no culture code in the file name (Default:en-us)'
),
};
Expand All @@ -94,9 +94,10 @@ export const Text = {
};

export const LuisConfig = {
AUTHORINGKEY: 'authoringKey',
STORAGE_KEY: 'luisConfig',
AUTHORING_KEY: 'authoringKey',
ENVIRONMENT: 'environment',
PROJECTNAME: 'name',
PROJECT_NAME: 'name',
};

export const FileTypes = {
Expand Down
19 changes: 16 additions & 3 deletions Composer/packages/client/src/pages/language-generation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { jsx } from '@emotion/core';
import { debounce } from 'lodash';
import { useContext, Fragment, useEffect, useRef, useState, useMemo } from 'react';
import formatMessage from 'format-message';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
import { Nav } from 'office-ui-fabric-react/lib/Nav';
import { navigate } from '@reach/router';

import { OpenAlertModal } from '../../components/Modal/Alert';
import { Store } from '../../store/index';
import { ContentHeaderStyle, ContentStyle, flexContent, actionButton } from '../language-understanding/styles';

Expand All @@ -19,6 +21,7 @@ export const LGPage = props => {
const { lgFiles, dialogs } = state;
const [textMode, setTextMode] = useState(false);
const [newContent, setNewContent] = useState(null);
const [lgFile, setLgFile] = useState(null);

const subPath = props['*'];

Expand All @@ -27,8 +30,10 @@ export const LGPage = props => {

// for now, one bot only have one lg file by default.
// all dialog share one lg file.
const lgFile = useMemo(() => {
return lgFiles.length ? lgFiles[0] : null;
useEffect(() => {
if (lgFiles.length) {
setLgFile({ ...lgFiles[0] });
}
}, [lgFiles]);

const navLinks = useMemo(() => {
Expand Down Expand Up @@ -74,21 +79,29 @@ export const LGPage = props => {
if (!activeDialog && subPath && dialogs.length) {
navigate('/language-generation');
}
});

setNewContent(null);
}, [activePath, dialogs, lgFiles]);

function onSelect(id) {
if (newContent) {
OpenAlertModal(formatMessage('You have unsaved changes on this page!'));
return;
}
if (id === '_all') {
navigate(`/language-generation`);
} else {
navigate(`/language-generation/${id}`);
}
setTextMode(false); // back to table view
}

function onChange(newContent) {
setNewContent(newContent);
}

function discardChanges() {
setLgFile({ ...lgFiles[0] });
setNewContent(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,12 @@ export default function TableView(props) {
<DetailsList
componentRef={listRef}
items={templates}
compact={false}
styles={{
root: {
overflowX: 'hidden',
},
}}
className="table-view-list"
columns={getTableColums()}
getKey={item => item.Name}
layoutMode={DetailsListLayoutMode.justified}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import { Fragment } from 'react';
import { useMemo } from 'react';
import { PropTypes } from 'prop-types';
import lodash from 'lodash';
import { LuEditor } from 'code-editor';

import FormEditor from './form-editor';
import TableView from './table-view';
import { contentEditor } from './styles';

Content.propTypes = {
file: PropTypes.object,
onChange: PropTypes.func,
textMode: PropTypes.bool,
activeDialog: PropTypes.object,
onEdit: PropTypes.func,
};

export default function Content(props) {
const luFile = props.file;
const onChange = props.onChange;
const textMode = props.textMode;
const activeDialog = props.activeDialog;
const onEdit = props.onEdit;

// performance optimization, component update should only trigger by luFile change.
const memoizedEditor = useMemo(() => {
const textContent = lodash.isEmpty(luFile) === false ? luFile.content : '';
return <LuEditor value={textContent} onChange={onChange} />;
}, [luFile]);

return lodash.isEmpty(luFile) === false ? (
textMode ? (
<div css={contentEditor}>
<LuEditor value={luFile.content} onChange={onChange} />
</div>
) : (
<FormEditor file={luFile} onChange={onChange} />
)
) : (
<Fragment />
return (
<div css={contentEditor}>
{textMode ? memoizedEditor : <TableView activeDialog={activeDialog} onEdit={onEdit} onChange={onChange} />}
</div>
);
}

This file was deleted.

Loading