diff --git a/Composer/packages/client/src/shell/lgApi.ts b/Composer/packages/client/src/shell/lgApi.ts index 858e28c4d7..ea3ff9d0ea 100644 --- a/Composer/packages/client/src/shell/lgApi.ts +++ b/Composer/packages/client/src/shell/lgApi.ts @@ -4,7 +4,6 @@ import { useContext, useEffect, useState } from 'react'; import { LgFile } from '@bfc/shared'; import throttle from 'lodash/throttle'; -import mapValues from 'lodash/mapValues'; import * as lgUtil from '../utils/lgUtil'; import { State, BoundActionHandlers } from '../store/types'; @@ -13,76 +12,81 @@ import { StoreContext } from '../store'; const createThrottledFunc = fn => throttle(fn, 1000, { leading: true, trailing: true }); function createLgApi(state: State, actions: BoundActionHandlers, lgFileResolver: (id: string) => LgFile | undefined) { - const api = { - getLgTemplates: id => { - if (id === undefined) throw new Error('must have a file id'); - const focusedDialogId = state.focusPath.split('#').shift() || id; - const file = lgFileResolver(focusedDialogId); - if (!file) throw new Error(`lg file ${id} not found`); - return file.templates; - }, - - updateLgTemplate: async (id: string, templateName: string, templateBody: string) => { - const file = lgFileResolver(id); - if (!file) throw new Error(`lg file ${id} not found`); - if (!templateName) throw new Error(`templateName is missing or empty`); - const template = { name: templateName, body: templateBody, parameters: [] }; - - const projectId = state.projectId; - - lgUtil.checkSingleLgTemplate(template); - - await actions.updateLgTemplate({ - file, - projectId, - templateName, - template, - }); - }, + const getLgTemplates = id => { + if (id === undefined) throw new Error('must have a file id'); + const focusedDialogId = state.focusPath.split('#').shift() || id; + const file = lgFileResolver(focusedDialogId); + if (!file) throw new Error(`lg file ${id} not found`); + return file.templates; + }; - copyLgTemplate: async (id, fromTemplateName, toTemplateName) => { - const file = lgFileResolver(id); - if (!file) throw new Error(`lg file ${id} not found`); - if (!fromTemplateName || !toTemplateName) throw new Error(`templateName is missing or empty`); + const updateLgTemplate = async (id: string, templateName: string, templateBody: string) => { + const file = lgFileResolver(id); + if (!file) throw new Error(`lg file ${id} not found`); + if (!templateName) throw new Error(`templateName is missing or empty`); + const template = { name: templateName, body: templateBody, parameters: [] }; - const projectId = state.projectId; + const projectId = state.projectId; - return actions.copyLgTemplate({ - file, - projectId, - fromTemplateName, - toTemplateName, - }); - }, - - removeLgTemplate: async (id, templateName) => { - const file = lgFileResolver(id); - if (!file) throw new Error(`lg file ${id} not found`); - if (!templateName) throw new Error(`templateName is missing or empty`); - const projectId = state.projectId; - - return actions.removeLgTemplate({ - file, - projectId, - templateName, - }); - }, - - removeLgTemplates: async (id, templateNames) => { - const file = lgFileResolver(id); - if (!file) throw new Error(`lg file ${id} not found`); - if (!templateNames) throw new Error(`templateName is missing or empty`); - const projectId = state.projectId; - - return actions.removeLgTemplates({ - file, - projectId, - templateNames, - }); - }, + lgUtil.checkSingleLgTemplate(template); + + await actions.updateLgTemplate({ + file, + projectId, + templateName, + template, + }); }; - return mapValues(api, fn => createThrottledFunc(fn)); + const copyLgTemplate = async (id, fromTemplateName, toTemplateName) => { + const file = lgFileResolver(id); + if (!file) throw new Error(`lg file ${id} not found`); + if (!fromTemplateName || !toTemplateName) throw new Error(`templateName is missing or empty`); + + const projectId = state.projectId; + + return actions.copyLgTemplate({ + file, + projectId, + fromTemplateName, + toTemplateName, + }); + }; + + const removeLgTemplate = async (id, templateName) => { + const file = lgFileResolver(id); + if (!file) throw new Error(`lg file ${id} not found`); + if (!templateName) throw new Error(`templateName is missing or empty`); + const projectId = state.projectId; + + return actions.removeLgTemplate({ + file, + projectId, + templateName, + }); + }; + + const removeLgTemplates = async (id, templateNames) => { + const file = lgFileResolver(id); + if (!file) throw new Error(`lg file ${id} not found`); + if (!templateNames) throw new Error(`templateName is missing or empty`); + const projectId = state.projectId; + + return actions.removeLgTemplates({ + file, + projectId, + templateNames, + }); + }; + + return { + addLgTemplate: updateLgTemplate, + getLgTemplates, + updateLgTemplate: createThrottledFunc(updateLgTemplate), + removeLgTemplate, + removeLgTemplates, + copyLgTemplate, + }; } export function useLgApi() { @@ -97,7 +101,9 @@ export function useLgApi() { return () => { Object.keys(newApi).forEach(apiName => { - newApi[apiName].flush(); + if (typeof newApi[apiName].flush === 'function') { + newApi[apiName].flush(); + } }); }; }, [projectId, focusPath]); diff --git a/Composer/packages/client/src/shell/luApi.ts b/Composer/packages/client/src/shell/luApi.ts index 286e11958e..72ccb8f48a 100644 --- a/Composer/packages/client/src/shell/luApi.ts +++ b/Composer/packages/client/src/shell/luApi.ts @@ -4,61 +4,65 @@ import { useContext, useEffect, useState } from 'react'; import { LuFile, LuIntentSection } from '@bfc/shared'; import throttle from 'lodash/throttle'; -import mapValues from 'lodash/mapValues'; import * as luUtil from '../utils/luUtil'; import { State, BoundActionHandlers } from '../store/types'; import { StoreContext } from '../store'; -const createThrottledFunc = fn => throttle(fn, 0, { leading: true, trailing: true }); +const createThrottledFunc = fn => throttle(fn, 1000, { leading: true, trailing: true }); function createLuApi(state: State, actions: BoundActionHandlers, luFileResolver: (id: string) => LuFile | undefined) { - const api = { - addLuIntent: async (id: string, intentName: string, intent: LuIntentSection) => { - const file = luFileResolver(id); - if (!file) throw new Error(`lu file ${id} not found`); - if (!intentName) throw new Error(`intentName is missing or empty`); - - const content = luUtil.addIntent(file.content, intent); - const projectId = state.projectId; - return await actions.updateLuFile({ id: file.id, projectId, content }); - }, - updateLuIntent: async (id: string, intentName: string, intent: LuIntentSection) => { - const file = luFileResolver(id); - if (!file) throw new Error(`lu file ${id} not found`); - if (!intentName) throw new Error(`intentName is missing or empty`); - - const content = luUtil.updateIntent(file.content, intentName, intent); - const projectId = state.projectId; - return await actions.updateLuFile({ id: file.id, projectId, content }); - }, - - removeLuIntent: async (id: string, intentName: string) => { - const file = luFileResolver(id); - if (!file) throw new Error(`lu file ${id} not found`); - if (!intentName) throw new Error(`intentName is missing or empty`); - - const content = luUtil.removeIntent(file.content, intentName); - const projectId = state.projectId; - return await actions.updateLuFile({ id: file.id, projectId, content }); - }, - - getLuIntents: (id: string): LuIntentSection[] => { - if (id === undefined) throw new Error('must have a file id'); - const focusedDialogId = state.focusPath.split('#').shift() || id; - const file = luFileResolver(focusedDialogId); - if (!file) throw new Error(`lu file ${id} not found`); - return file.intents; - }, - - getLuIntent: (id: string, intentName: string): LuIntentSection | undefined => { - const file = luFileResolver(id); - if (!file) throw new Error(`lu file ${id} not found`); - return file.intents.find(({ Name }) => Name === intentName); - }, + const addLuIntent = async (id: string, intentName: string, intent: LuIntentSection) => { + const file = luFileResolver(id); + if (!file) throw new Error(`lu file ${id} not found`); + if (!intentName) throw new Error(`intentName is missing or empty`); + + const content = luUtil.addIntent(file.content, intent); + const projectId = state.projectId; + return await actions.updateLuFile({ id: file.id, projectId, content }); + }; + + const updateLuIntent = async (id: string, intentName: string, intent: LuIntentSection) => { + const file = luFileResolver(id); + if (!file) throw new Error(`lu file ${id} not found`); + if (!intentName) throw new Error(`intentName is missing or empty`); + + const content = luUtil.updateIntent(file.content, intentName, intent); + const projectId = state.projectId; + return await actions.updateLuFile({ id: file.id, projectId, content }); + }; + + const removeLuIntent = async (id: string, intentName: string) => { + const file = luFileResolver(id); + if (!file) throw new Error(`lu file ${id} not found`); + if (!intentName) throw new Error(`intentName is missing or empty`); + + const content = luUtil.removeIntent(file.content, intentName); + const projectId = state.projectId; + return await actions.updateLuFile({ id: file.id, projectId, content }); + }; + + const getLuIntents = (id: string): LuIntentSection[] => { + if (id === undefined) throw new Error('must have a file id'); + const focusedDialogId = state.focusPath.split('#').shift() || id; + const file = luFileResolver(focusedDialogId); + if (!file) throw new Error(`lu file ${id} not found`); + return file.intents; }; - return mapValues(api, fn => createThrottledFunc(fn)); + const getLuIntent = (id: string, intentName: string): LuIntentSection | undefined => { + const file = luFileResolver(id); + if (!file) throw new Error(`lu file ${id} not found`); + return file.intents.find(({ Name }) => Name === intentName); + }; + + return { + addLuIntent, + getLuIntents, + getLuIntent, + updateLuIntent: createThrottledFunc(updateLuIntent), + removeLuIntent, + }; } export function useLuApi() { @@ -73,7 +77,9 @@ export function useLuApi() { return () => { Object.keys(newApi).forEach(apiName => { - newApi[apiName].flush(); + if (typeof newApi[apiName].flush === 'function') { + newApi[apiName].flush(); + } }); }; }, [projectId, focusPath]);