Skip to content

Commit

Permalink
chore: refactor lg page route & url (#1756)
Browse files Browse the repository at this point in the history
* refactor url

* refactor with router

* update link

* update navigation

* clean up

* update e2e test

* use type LgTemplate

* redirect to /common

* refine type and code style

* clean up

* refine route, optional chain

* clean up

Co-authored-by: Andy Brown <asbrown002@gmail.com>
  • Loading branch information
zhixzhan and a-b-r-o-w-n authored Dec 20, 2019
1 parent de790f3 commit 52c46aa
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 187 deletions.
4 changes: 0 additions & 4 deletions Composer/cypress/integration/LGPage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,5 @@ context('LG Page', () => {

// nav to Main dialog
cy.get('.dialogNavTree a[title="__TestTodoSample.Main"]').click();
// cy.wait(300);

// dialog filter, edit mode button is disabled.
cy.get('@switchButton').should('be.disabled');
});
});
1 change: 0 additions & 1 deletion Composer/cypress/integration/NotificationPage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ context('Notification Page', () => {
});

cy.findAllByText('Bot Responses').should('exist');
cy.get('@switchButton').should('be.disabled');
});

it('can show lu syntax error ', () => {
Expand Down
128 changes: 84 additions & 44 deletions Composer/packages/client/src/pages/language-generation/code-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,101 @@

/* eslint-disable react/display-name */
import React, { useState, useEffect, useMemo, useContext, useCallback } from 'react';
import { LgEditor, LGOption } from '@bfc/code-editor';
import { LgEditor } from '@bfc/code-editor';
import get from 'lodash/get';
import debounce from 'lodash/debounce';
import isEmpty from 'lodash/isEmpty';
import { LgFile } from '@bfc/indexers';
import { editor } from '@bfcomposer/monaco-editor/esm/vs/editor/editor.api';
import { lgIndexer, Diagnostic, combineMessage, isValid } from '@bfc/indexers';
import { lgIndexer, combineMessage, isValid } from '@bfc/indexers';
import { RouteComponentProps } from '@reach/router';
import querystring from 'query-string';

import { StoreContext } from '../../store';
import * as lgUtil from '../../utils/lgUtil';

const { check } = lgIndexer;

interface CodeEditorProps {
file: LgFile;
template: lgUtil.Template | null;
line: number;
}

const lspServerPath = '/lg-language-server';

export default function CodeEditor(props: CodeEditorProps) {
const { actions } = useContext(StoreContext);
const { file, template, line } = props;
interface CodeEditorProps extends RouteComponentProps<{}> {
fileId: string;
}

const CodeEditor: React.FC<CodeEditorProps> = props => {
const { actions, state } = useContext(StoreContext);
const { lgFiles } = state;
const { fileId } = props;
const file = lgFiles?.find(({ id }) => id === 'common');
const [diagnostics, setDiagnostics] = useState(get(file, 'diagnostics', []));
const [content, setContent] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [lgEditor, setLgEditor] = useState<editor.IStandaloneCodeEditor | null>(null);

const fileId = file && file.id;
const search = props.location?.search ?? '';
const searchTemplateName = querystring.parse(search).t;
const templateId = Array.isArray(searchTemplateName)
? searchTemplateName[0]
: typeof searchTemplateName === 'string'
? searchTemplateName
: undefined;
const template = templateId && file ? file.templates.find(({ name }) => name === templateId) : undefined;

const hash = props.location?.hash ?? '';
const hashLine = querystring.parse(hash).L;
const line = Array.isArray(hashLine) ? +hashLine[0] : typeof hashLine === 'string' ? +hashLine : undefined;

const inlineMode = !!template;

useEffect(() => {
// reset content with file.content's initial state
if (isEmpty(file)) return;
const value = template ? get(template, 'body', '') : get(file, 'content', '');
if (!file || isEmpty(file)) return;
const value = template ? template.body : file.content;
setContent(value);
}, [fileId, template]);
}, [fileId, templateId]);

useEffect(() => {
const isInvalid = !isValid(diagnostics);
const text = isInvalid ? combineMessage(diagnostics) : '';
const currentDiagnostics =
inlineMode && template
? diagnostics.filter(d => {
return (
d.range &&
template.range &&
d.range.start.line >= template.range.startLineNumber &&
d.range.end.line <= template.range.endLineNumber
);
})
: diagnostics;

const isInvalid = !isValid(currentDiagnostics);
const text = isInvalid ? combineMessage(currentDiagnostics) : '';
setErrorMsg(text);
}, [diagnostics]);

const editorDidMount = (lgEditor: editor.IStandaloneCodeEditor) => {
setLgEditor(lgEditor);
};

useEffect(() => {
if (lgEditor) {
lgEditor.revealLine(line);
if (lgEditor && line !== undefined) {
window.requestAnimationFrame(() => {
lgEditor.revealLine(line);
lgEditor.focus();
lgEditor.setPosition({ lineNumber: line, column: 1 });
});
}
}, [lgEditor]);
}, [line, lgEditor]);

const updateLgTemplate = useMemo(
() =>
debounce((body: string) => {
const templateName = get(template, 'name');
if (!templateName) return;
if (!file || !template) return;
const { name, parameters } = template;
const payload = {
file,
templateName,
templateName: name,
template: {
name: templateName,
parameters: get(template, 'parameters'),
name,
parameters,
body,
},
};
Expand All @@ -75,8 +109,10 @@ export default function CodeEditor(props: CodeEditorProps) {
const updateLgFile = useMemo(
() =>
debounce((content: string) => {
if (!file) return;
const { id } = file;
const payload = {
id: file.id,
id,
content,
};
actions.updateLgFile(payload);
Expand All @@ -87,36 +123,38 @@ export default function CodeEditor(props: CodeEditorProps) {
const _onChange = useCallback(
value => {
setContent(value);

let diagnostics: Diagnostic[] = [];
if (!file) return;
const { id } = file;
if (inlineMode) {
const content = get(file, 'content', '');
const templateName = get(template, 'name', '');
if (!template) return;
const { name, parameters } = template;
const { content } = file;
try {
const newContent = lgUtil.updateTemplate(content, templateName, {
name: templateName,
parameters: get(template, 'parameters'),
const newContent = lgUtil.updateTemplate(content, name, {
name,
parameters,
body: value,
});
diagnostics = check(newContent, fileId);
setDiagnostics(check(newContent, id));
updateLgTemplate(value);
} catch (error) {
setErrorMsg(error.message);
}
} else {
diagnostics = check(value, fileId);
setDiagnostics(check(value, id));
updateLgFile(value);
}
setDiagnostics(diagnostics);
},
[file, template]
);

const lgOption: LGOption = {
inline: inlineMode,
content: get(file, 'content', ''),
template: template ? template : undefined,
};
const lgOption = template
? {
inline: inlineMode,
content: file?.content ?? '',
template,
}
: undefined;

return (
<LgEditor
Expand All @@ -130,7 +168,7 @@ export default function CodeEditor(props: CodeEditorProps) {
lineNumbersMinChars: false,
}}
hidePlaceholder={inlineMode}
editorDidMount={setLgEditor}
editorDidMount={editorDidMount}
value={content}
errorMsg={errorMsg}
lgOption={lgOption}
Expand All @@ -140,4 +178,6 @@ export default function CodeEditor(props: CodeEditorProps) {
onChange={_onChange}
/>
);
}
};

export default CodeEditor;
Loading

0 comments on commit 52c46aa

Please sign in to comment.