Skip to content

Commit

Permalink
fix: clean LG/LU resources when deleting a Trigger (microsoft#2844)
Browse files Browse the repository at this point in the history
* pass shellApi as a params into hook

* clean trigger resources by using useTriggerApi
  • Loading branch information
yeze322 authored Apr 30, 2020
1 parent 6a5dfb0 commit 34d3e83
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 30 deletions.
7 changes: 6 additions & 1 deletion Composer/packages/client/src/pages/design/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PromptTab } from '@bfc/shared';
import { DialogFactory, SDKKinds, DialogInfo } from '@bfc/shared';
import { Link } from 'office-ui-fabric-react/lib/Link';
import { JsonEditor } from '@bfc/code-editor';
import { useTriggerApi } from '@bfc/extension';

import { LoadingSpinner } from '../../components/LoadingSpinner';
import { TestController } from '../../components/TestController';
Expand All @@ -28,6 +29,7 @@ import { ToolBar } from '../../components/ToolBar/index';
import { clearBreadcrumb } from '../../utils/navigation';
import undoHistory from '../../store/middlewares/undo/history';
import { navigateTo } from '../../utils';
import { useShell } from '../../shell';

import { VisualEditorAPI } from './FrameAPI';
import {
Expand Down Expand Up @@ -106,6 +108,8 @@ function DesignPage(props) {
const [dialogJsonVisible, setDialogJsonVisibility] = useState(false);
const [currentDialog, setCurrentDialog] = useState<DialogInfo>(dialogs[0]);
const [exportSkillModalVisible, setExportSkillModalVisible] = useState(false);
const shell = useShell('ProjectTree');
const triggerApi = useTriggerApi(shell.api);

useEffect(() => {
const currentDialog = dialogs.find(({ id }) => id === dialogId);
Expand Down Expand Up @@ -357,7 +361,8 @@ function DesignPage(props) {
}

async function handleDeleteTrigger(id, index) {
const content = deleteTrigger(dialogs, id, index);
const content = deleteTrigger(dialogs, id, index, trigger => triggerApi.deleteTrigger(id, trigger));

if (content) {
await updateDialog({ id, projectId, content });
const match = /\[(\d+)\]/g.exec(selected);
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/client/src/shell/useShell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useLuApi } from './luApi';

const FORM_EDITOR = 'PropertyEditor';

type EventSource = 'VisualEditor' | 'PropertyEditor';
type EventSource = 'VisualEditor' | 'PropertyEditor' | 'ProjectTree';

export function useShell(source: EventSource): { api: ShellApi; data: ShellData } {
const { state, actions } = useContext(StoreContext);
Expand Down
12 changes: 9 additions & 3 deletions Composer/packages/client/src/utils/dialogUtil.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { ConceptLabels, DialogGroup, SDKKinds, dialogGroups, DialogInfo, DialogFactory } from '@bfc/shared';
import { ConceptLabels, DialogGroup, SDKKinds, dialogGroups, DialogInfo, DialogFactory, ITrigger } from '@bfc/shared';
import get from 'lodash/get';
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
Expand Down Expand Up @@ -128,7 +128,12 @@ export function createSelectedPath(selected: number) {
return `triggers[${selected}]`;
}

export function deleteTrigger(dialogs: DialogInfo[], dialogId: string, index: number) {
export function deleteTrigger(
dialogs: DialogInfo[],
dialogId: string,
index: number,
callbackOnDeletedTrigger?: (trigger: ITrigger) => any
) {
let dialogCopy = getDialog(dialogs, dialogId);
if (!dialogCopy) return null;
const isRegEx = get(dialogCopy, 'content.recognizer.$kind', '') === regexRecognizerKey;
Expand All @@ -137,7 +142,8 @@ export function deleteTrigger(dialogs: DialogInfo[], dialogId: string, index: nu
dialogCopy = deleteRegExIntent(dialogCopy, regExIntent);
}
const triggers = get(dialogCopy, 'content.triggers');
triggers.splice(index, 1);
const removedTriggers = triggers.splice(index, 1);
callbackOnDeletedTrigger && callbackOnDeletedTrigger(removedTriggers[0]);
return dialogCopy.content;
}

Expand Down
1 change: 1 addition & 0 deletions Composer/packages/extensions/extension/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export * from './useShellApi';
export * from './useLgApi';
export * from './useLuApi';
export * from './useActionApi';
export * from './useTriggerApi';
export * from './useDialogApi';
export * from './useDialogEditApi';
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import {
deleteActions as destructActions,
FieldProcessorAsync,
walkAdaptiveActionList,
ShellApi,
} from '@bfc/shared';

import { useLgApi } from './useLgApi';
import { useLuApi } from './useLuApi';

export const useActionApi = () => {
const { createLgTemplate, readLgTemplate, deleteLgTemplates } = useLgApi();
const { createLuIntent, readLuIntent, deleteLuIntents } = useLuApi();
export const useActionApi = (shellApi: ShellApi) => {
const { createLgTemplate, readLgTemplate, deleteLgTemplates } = useLgApi(shellApi);
const { createLuIntent, readLuIntent, deleteLuIntents } = useLuApi(shellApi);

const luFieldName = '_lu';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { useShellApi } from './useShellApi';
import { ShellApi } from '@bfc/shared';

export const useDialogApi = () => {
const {
shellApi: { getDialog, saveDialog, createDialog },
} = useShellApi();
export const useDialogApi = (shellApi: ShellApi) => {
const { getDialog, saveDialog, createDialog } = shellApi;

return {
createDialog: () => createDialog([]),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { BaseSchema, DialogUtils } from '@bfc/shared';
import { BaseSchema, DialogUtils, ShellApi } from '@bfc/shared';

import { useActionApi } from './useActionApi';

Expand All @@ -14,8 +14,8 @@ export interface DialogApiContext {

const { appendNodesAfter, queryNodes, insertNodes, deleteNode, deleteNodes } = DialogUtils;

export function useDialogEditApi() {
const { constructActions, copyActions, deleteAction, deleteActions } = useActionApi();
export function useDialogEditApi(shellApi: ShellApi) {
const { constructActions, copyActions, deleteAction, deleteActions } = useActionApi(shellApi);

async function insertActions(
dialogId: string,
Expand Down
7 changes: 2 additions & 5 deletions Composer/packages/extensions/extension/src/hooks/useLgApi.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { LgTemplateRef, LgMetaData, BaseSchema, LgType } from '@bfc/shared';

import { useShellApi } from './useShellApi';
import { LgTemplateRef, LgMetaData, BaseSchema, LgType, ShellApi } from '@bfc/shared';

/**
* LG CRUD lib
*/
export const useLgApi = () => {
const { shellApi } = useShellApi();
export const useLgApi = (shellApi: ShellApi) => {
const { removeLgTemplates, getLgTemplates, updateLgTemplate } = shellApi;

const deleteLgTemplates = (lgFileId: string, lgTemplates: string[]) => {
Expand Down
7 changes: 2 additions & 5 deletions Composer/packages/extensions/extension/src/hooks/useLuApi.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { LuIntentSection, BaseSchema, LuMetaData, LuType } from '@bfc/shared';

import { useShellApi } from './useShellApi';
import { LuIntentSection, BaseSchema, LuMetaData, LuType, ShellApi } from '@bfc/shared';

/**
* LU CRUD API
*/
export const useLuApi = () => {
const { shellApi } = useShellApi();
export const useLuApi = (shellApi: ShellApi) => {
const { addLuIntent, removeLuIntent, getLuIntent } = shellApi;

const createLuIntent = async (
Expand Down
31 changes: 31 additions & 0 deletions Composer/packages/extensions/extension/src/hooks/useTriggerApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { ShellApi, SDKKinds } from '@bfc/shared';
import get from 'lodash/get';

import { useActionApi } from './useActionApi';
import { useLuApi } from './useLuApi';

export const useTriggerApi = (shellAPi: ShellApi) => {
const { deleteActions } = useActionApi(shellAPi);
const { deleteLuIntent } = useLuApi(shellAPi);

const deleteTrigger = (dialogId: string, trigger) => {
// Clean the lu resource on intent trigger
if (trigger.$kind === SDKKinds.OnIntent) {
const triggerIntent = get(trigger, 'intent', '');
deleteLuIntent(dialogId, triggerIntent);
}

// Clean action resources
const actions = get(trigger, 'actions');
if (!actions || !Array.isArray(actions)) return;

deleteActions(dialogId, actions);
};

return {
deleteTrigger,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { jsx } from '@emotion/core';
import { useContext, FC, useEffect, useState, useRef } from 'react';
import { MarqueeSelection, Selection } from 'office-ui-fabric-react/lib/MarqueeSelection';
import { SDKKinds, DialogUtils } from '@bfc/shared';
import { useDialogApi, useDialogEditApi, useActionApi } from '@bfc/extension';
import { useDialogApi, useDialogEditApi, useActionApi, useShellApi } from '@bfc/extension';
import get from 'lodash/get';

import { NodeEventTypes } from '../constants/NodeEventTypes';
Expand Down Expand Up @@ -41,6 +41,7 @@ export const ObiEditor: FC<ObiEditorProps> = ({
let divRef;

const { focusedId, focusedEvent, clipboardActions, dialogFactory } = useContext(NodeRendererContext);
const { shellApi } = useShellApi();
const {
insertAction,
insertActions,
Expand All @@ -50,9 +51,9 @@ export const ObiEditor: FC<ObiEditorProps> = ({
deleteSelectedAction,
deleteSelectedActions,
updateRecognizer,
} = useDialogEditApi();
const { createDialog, readDialog, updateDialog } = useDialogApi();
const { actionsContainLuIntent } = useActionApi();
} = useDialogEditApi(shellApi);
const { createDialog, readDialog, updateDialog } = useDialogApi(shellApi);
const { actionsContainLuIntent } = useActionApi(shellApi);

const trackActionChange = (actionPath: string) => {
const affectedPaths = DialogUtils.getParentPaths(actionPath);
Expand Down

0 comments on commit 34d3e83

Please sign in to comment.