Skip to content

Commit

Permalink
Merge pull request #225 from botpress/robgordon-dev-2099-semi-deep-sk…
Browse files Browse the repository at this point in the history
…ills-copy

fix(copy): copying skill makes clone but uses same cms content
  • Loading branch information
rob-gordon committed Jan 11, 2022
2 parents a87e08e + b957b5b commit 79d728e
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 24 deletions.
40 changes: 37 additions & 3 deletions packages/studio-ui/src/web/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import axios from 'axios'
import * as sdk from 'botpress/sdk'
import { FlowPoint, FlowView, NodeProblem } from 'common/typings'
import _ from 'lodash'
import nanoid from 'nanoid'
import { createAction } from 'redux-actions'
import { copyName } from '~/util/flows'

import { getDeletedFlows, getDirtyFlows, getModifiedFlows, getNewFlows } from '../reducers/selectors'

Expand Down Expand Up @@ -117,7 +119,6 @@ const wrapAction = (
errorAction = errorSaveFlows
) => (payload?: any) => (dispatch, getState) => {
dispatch(requestAction(payload))
// eslint-disable-next-line @typescript-eslint/no-floating-promises
asyncCallback(payload, getState(), dispatch)
.then(() => dispatch(receiveAction()))
.catch(err => dispatch(errorAction(err)))
Expand Down Expand Up @@ -191,7 +192,40 @@ export const removeFlowNode: (element: any) => void = wrapAction(requestRemoveFl
}
})

export const pasteFlowNode: ({ x, y }) => void = wrapAction(requestPasteFlowNode, async (payload, state, dispatch) => {
export const pasteFlowNode = (payload: { x: number; y: number }) => async (dispatch, getState) => {
const state = getState()
const skills = state.flows.buffer.nodes.filter(node => node.skill)
const nonSkills = state.flows.buffer.nodes.filter(node => !node.skill)
const currentFlowNodeNames = state.flows.flowsByName[state.flows.currentFlow].nodes.map(({ name }) => name)

// Create new flows for all skills
for (const node of skills) {
let { skillData } = state.flows.flowsByName[node.flow]
const randomId = nanoid(10)
skillData = { ...skillData, randomId }
const { moduleName } = _.find(state.skills.installed, { id: node.skill })
const { data } = await axios.post(
`${window.API_PATH}/studio/modules/${moduleName}/skill/${node.skill}/generateFlow?botId=${window.BOT_ID}&isOneFlow=${window.USE_ONEFLOW}`,
skillData
)
dispatch(
requestInsertNewSkill({
skillId: node.skill,
data: skillData,
location: payload,
generatedFlow: data.flow,
transitions: data.transitions,
nodeName: copyName(currentFlowNodeNames, node.name)
})
)
const flows = getState().flows
const flowsByName = flows.flowsByName
const newFlowKey = Object.keys(flowsByName).find(key => flowsByName[key].skillData?.randomId === randomId)
await FlowsAPI.createFlow(flows, newFlowKey)
}

// Paste non-skills
dispatch(requestPasteFlowNode({ ...payload, nodes: nonSkills }))
await updateCurrentFlow(payload, state)
dispatch(refreshFlowsLinks())

Expand All @@ -200,7 +234,7 @@ export const pasteFlowNode: ({ x, y }) => void = wrapAction(requestPasteFlowNode
await onTriggerEvent('create', node.conditions, state)
}
}
})
}
export const pasteFlowNodeElement = wrapAction(requestPasteFlowNodeElement, updateCurrentFlow)

// actions that do not modify flow
Expand Down
27 changes: 6 additions & 21 deletions packages/studio-ui/src/web/reducers/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
updateFlowProblems
} from '~/actions'
import { hashCode, prettyId } from '~/util'
import { copyName } from '~/util/flows'

export interface FlowReducer {
currentFlow?: string
Expand Down Expand Up @@ -183,23 +184,6 @@ const popHistory = stackName => state => {
}
}

const copyName = (siblingNames, nameToCopy) => {
const copies = siblingNames.filter(name => name.startsWith(`${nameToCopy}-copy`))

if (!copies.length) {
return `${nameToCopy}-copy`
}

let i = 1
while (true) {
if (!copies.find(name => name === `${nameToCopy}-copy-${i}`)) {
return `${nameToCopy}-copy-${i}`
} else {
i += 1
}
}
}

const doRenameFlow = ({ currentName, newName, flows }) =>
flows.reduce((obj, f) => {
if (f.name === currentName) {
Expand Down Expand Up @@ -534,7 +518,7 @@ reducer = reduceReducers(
id: `skill-${flowRandomId}`,
type: 'skill-call',
skill: skillId,
name: `${skillId}-${flowRandomId}`,
name: payload.nodeName ?? `${skillId}-${flowRandomId}`,
flow: flowName,
next: payload.transitions || [],
onEnter: null,
Expand Down Expand Up @@ -741,14 +725,15 @@ reducer = reduceReducers(
}
},

[requestPasteFlowNode]: (state, { payload: { x, y } }) => {
if (!state.buffer.nodes?.length) {
[requestPasteFlowNode]: (state, { payload: { x, y, nodes } }) => {
const nodesToPaste = nodes || state.buffer.nodes
if (!nodesToPaste?.length) {
return state
}

const currentFlow = state.flowsByName[state.currentFlow]
const siblingNames = currentFlow.nodes.map(({ name }) => name)
const newNodes = _.cloneDeep(state.buffer.nodes).map(node => {
const newNodes = _.cloneDeep(nodesToPaste).map(node => {
const newNodeId = prettyId()
const newName = copyName(siblingNames, node.name)
return { ...node, id: newNodeId, newName, lastModified: new Date() }
Expand Down
9 changes: 9 additions & 0 deletions packages/studio-ui/src/web/util/flows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function copyName(siblings: string[], nameToCopy: string): string {
const getName = (i: number) => `${nameToCopy}-copy${i > 0 ? `-${i}` : ''}`
let i = 0,
name = getName(i)
while (siblings.includes(name)) {
name = getName(++i)
}
return name
}

0 comments on commit 79d728e

Please sign in to comment.