-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Create workflow applications that support template selection #2377
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,11 +38,7 @@ | |
<el-radio-group v-model="applicationForm.type" class="card__radio"> | ||
<el-row :gutter="16"> | ||
<el-col :span="12"> | ||
<el-card | ||
shadow="never" | ||
class="mb-16" | ||
:class="applicationForm.type === 'SIMPLE' ? 'active' : ''" | ||
> | ||
<el-card shadow="never" :class="applicationForm.type === 'SIMPLE' ? 'active' : ''"> | ||
<el-radio value="SIMPLE" size="large"> | ||
<p class="mb-4">{{ $t('views.application.simple') }}</p> | ||
<el-text type="info">{{ | ||
|
@@ -52,11 +48,7 @@ | |
</el-card> | ||
</el-col> | ||
<el-col :span="12"> | ||
<el-card | ||
shadow="never" | ||
class="mb-16" | ||
:class="isWorkFlow(applicationForm.type) ? 'active' : ''" | ||
> | ||
<el-card shadow="never" :class="isWorkFlow(applicationForm.type) ? 'active' : ''"> | ||
<el-radio value="WORK_FLOW" size="large"> | ||
<p class="mb-4">{{ $t('views.application.workflow') }}</p> | ||
<el-text type="info">{{ | ||
|
@@ -68,6 +60,35 @@ | |
</el-row> | ||
</el-radio-group> | ||
</el-form-item> | ||
<el-form-item | ||
:label="$t('views.document.upload.template')" | ||
v-if="applicationForm.type === 'WORK_FLOW'" | ||
> | ||
<div class="w-full"> | ||
<el-row :gutter="16"> | ||
<el-col :span="12"> | ||
<el-card | ||
class="radio-card cursor" | ||
shadow="never" | ||
@click="selectedType('blank')" | ||
:class="appTemplate === 'blank' ? 'active' : ''" | ||
> | ||
{{ $t('views.application.applicationForm.form.appTemplate.blankApp') }} | ||
</el-card> | ||
</el-col> | ||
<el-col :span="12"> | ||
<el-card | ||
class="radio-card cursor" | ||
shadow="never" | ||
:class="appTemplate === 'assistant' ? 'active' : ''" | ||
@click="selectedType('assistant')" | ||
> | ||
{{ $t('views.application.applicationForm.form.appTemplate.assistantApp') }} | ||
</el-card> | ||
</el-col> | ||
</el-row> | ||
</div> | ||
</el-form-item> | ||
</el-form> | ||
<template #footer> | ||
<span class="dialog-footer"> | ||
|
@@ -89,6 +110,7 @@ import type { FormInstance, FormRules } from 'element-plus' | |
import applicationApi from '@/api/application' | ||
import { MsgSuccess, MsgAlert } from '@/utils/message' | ||
import { isWorkFlow } from '@/utils/application' | ||
import { baseNodes } from '@/workflow/common/data' | ||
import { t } from '@/locales' | ||
const router = useRouter() | ||
const emit = defineEmits(['refresh']) | ||
|
@@ -106,6 +128,12 @@ const optimizationPrompt = | |
'<data></data>' + | ||
t('views.application.applicationForm.dialog.defaultPrompt2') | ||
|
||
const workflowDefault = ref<any>({ | ||
edges: [], | ||
nodes: baseNodes | ||
}) | ||
const appTemplate = ref('blank') | ||
|
||
const applicationFormRef = ref() | ||
|
||
const loading = ref(false) | ||
|
@@ -207,6 +235,11 @@ const submitHandle = async (formEl: FormInstance | undefined) => { | |
if (!formEl) return | ||
await formEl.validate((valid) => { | ||
if (valid) { | ||
if (isWorkFlow(applicationForm.value.type) && appTemplate.value === 'blank') { | ||
workflowDefault.value.nodes[0].properties.node_data.desc = applicationForm.value.desc | ||
workflowDefault.value.nodes[0].properties.node_data.name = applicationForm.value.name | ||
applicationForm.value['work_flow'] = workflowDefault.value | ||
} | ||
applicationApi.postApplication(applicationForm.value, loading).then((res) => { | ||
MsgSuccess(t('common.createSuccess')) | ||
if (isWorkFlow(applicationForm.value.type)) { | ||
|
@@ -220,6 +253,18 @@ const submitHandle = async (formEl: FormInstance | undefined) => { | |
}) | ||
} | ||
|
||
function selectedType(type: string) { | ||
appTemplate.value = type | ||
} | ||
|
||
defineExpose({ open }) | ||
</script> | ||
<style lang="scss" scope></style> | ||
<style lang="scss" scope> | ||
.radio-card { | ||
line-height: 22px; | ||
&.active { | ||
border-color: var(--el-color-primary); | ||
color: var(--el-color-primary); | ||
} | ||
} | ||
</style> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The provided code looks mostly well-structured, but there are a few improvements and considerations that could be made:
Here's an optimized version of the code: <script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import applicationApi from '@/api/application'
import { MsgSuccess, MsgAlert } from '@/utils/message'
import { isWorkFlow } from '@/utils/application'
import { baseNodes } from '@/workflow/common/data'
import { t } from '@/locales'
const router = useRouter()
const emit = defineEmits(['refresh'])
const optimizationPrompt =
'<data></data>' +
t('views.application.applicationForm.dialog.defaultPrompt2')
// Initial state
const workflowDefault = ref<any>({
edges: [],
nodes: [...baseNodes] // Include necessary data properties here
})
const appTemplate = ref<string>('blank')
let selectedAppTemplateId = '-1' // Temporary ID placeholder
onMounted(() => {
// Initialize any needed values or fetch additional data here
})
const applicationFormRef = ref<FormInstance>()
const loading = ref<boolean>(false)
// Validation rules
const rules: FormRules = {
name: [{ required: true }],
}
const submitHandle = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
if (
isWorkFlow(applicationForm.value.type) &&
appTemplate.value.toLowerCase() === 'blank'
) {
handleBlankWorkflow(appTemplate.value)
workflowDefault.value.nodes[0].properties.node_data.desc = applicationForm.value.desc
workflowDefault.value.nodes[0].properties.node_data.name = applicationForm.value.name
applicationForm.value['work_flow'] = workflowDefault.value
}
try {
await applicationApi.postApplication(applicationForm.value, loading)
MsgSuccess(t('common.createSuccess', null, 'en-US'))
loadNewDataOnSuccess()
} catch (error) {
console.error(error)
MsgAlert(t('msg.alert.submitError'), null, 'en-US')}
} else {
console.log("Validation failed")
}
})
}
function handleBlankWorkflow(type: string) {
selectedAppTemplateId = 'template-' + Math.random().toString(36).substr(2, 4)
let node = workflowDefault.value.nodes.find(node => node.id === "-1")!
node.properties.node_data.template_id = selectedAppTemplateId!;
}
function selectedType(newType: string) {
appTemplate.value = newType;
}
defineExpose({ open });
</script>
<style lang="scss" scoped>
.radio-card {
width: auto; /* Make sure cards fit their contents */
padding: 20px;
cursor: pointer;
&.active {
border-color: var(--el-color-primary);
color: var(--el-color-primary);
.node_name_label {
font-weight: bold;
}
.node_desc_label {
text-decoration: underline;
}
}
}
</style> Key Changes:
These changes aim to make the code cleaner, easier to understand, and more flexible for future development. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,10 @@ import { t } from '@/locales' | |
export const startNode = { | ||
id: WorkflowType.Start, | ||
type: WorkflowType.Start, | ||
x: 180, | ||
y: 720, | ||
x: 480, | ||
y: 3340, | ||
properties: { | ||
height: 200, | ||
height: 364, | ||
stepName: t('views.applicationWorkflow.nodes.startNode.label'), | ||
config: { | ||
fields: [ | ||
|
@@ -20,29 +20,45 @@ export const startNode = { | |
{ | ||
value: 'time', | ||
label: t('views.applicationWorkflow.nodes.startNode.currentTime') | ||
}, | ||
{ | ||
value: 'history_context', | ||
label: t('views.application.applicationForm.form.historyRecord.label') | ||
}, | ||
{ | ||
value: 'chat_id', | ||
label: t('chat.chatId') | ||
} | ||
] | ||
} | ||
}, | ||
fields: [{ label: t('views.applicationWorkflow.nodes.startNode.question'), value: 'question' }], | ||
globalFields: [ | ||
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' } | ||
], | ||
showNode: true | ||
} | ||
} | ||
export const baseNode = { | ||
id: WorkflowType.Base, | ||
type: WorkflowType.Base, | ||
x: 200, | ||
y: 270, | ||
x: 360, | ||
y: 2761.3875, | ||
text: '', | ||
properties: { | ||
width: 420, | ||
height: 200, | ||
height: 728.375, | ||
stepName: t('views.applicationWorkflow.nodes.baseNode.label'), | ||
input_field_list: [], | ||
node_data: { | ||
name: '', | ||
desc: '', | ||
// @ts-ignore | ||
prologue: t('views.application.applicationForm.form.defaultPrologue') | ||
prologue: t('views.application.applicationForm.form.defaultPrologue'), | ||
tts_type: 'BROWSER' | ||
}, | ||
config: {} | ||
config: {}, | ||
showNode: true, | ||
user_input_config: { title: t('chat.userInput') }, | ||
user_input_field_list: [] | ||
} | ||
} | ||
/** | ||
|
@@ -246,9 +262,7 @@ export const variableAssignNode = { | |
height: 252, | ||
properties: { | ||
stepName: t('views.applicationWorkflow.nodes.variableAssignNode.label'), | ||
config: { | ||
|
||
} | ||
config: {} | ||
} | ||
} | ||
|
||
|
@@ -415,7 +429,7 @@ export const nodeDict: any = { | |
[WorkflowType.TextToSpeechNode]: textToSpeechNode, | ||
[WorkflowType.SpeechToTextNode]: speechToTextNode, | ||
[WorkflowType.ImageGenerateNode]: imageGenerateNode, | ||
[WorkflowType.VariableAssignNode]: variableAssignNode, | ||
[WorkflowType.VariableAssignNode]: variableAssignNode | ||
} | ||
export function isWorkFlow(type: string | undefined) { | ||
return type === 'WORK_FLOW' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code appears to have several areas for enhancement and correction: Corrections:
Suggestions:
Here is a revised version with corrected and optimized suggestions incorporated: import { t } from '@/locales'
export const startNode = {
id: WorkflowType.Start,
type: WorkflowType.Start,
x: 480,
y: 3340,
properties: {
height: 364,
stepName: t('views.applicationWorkflow.nodes.startNode.label'),
config: {
fields: [
{ value: 'time', label: t('views.applicationWorkflow.nodes.startNode.currentTime') },
{ value: 'history_record', label: t('view.application.workflow.nodes.startNode.history.record') },
{ value: 'chat_id', label: t('chat.chatId') }
]
},
showNode: true
}
}
export const baseNode = {
id: WorkflowType.Base,
type: WorkflowType.Base,
x: 360,
y: 2761.3875,
text: '',
properties: {
width: 420,
height: 728.375,
stepName: t('views.applicationWorkflow.nodes.baseNode.label'),
input_field_list: [],
node_data: {
name: '',
desc: '',
prologue: t('views.application.applicationForm.form.defaultPrologue'),
tts_type: 'BROWSER'
},
showNode: true,
user_input_config: { title: t('chat.userInput') },
user_input_field_list: []
}
}
/**
* Definition for various nodes in the workflow
*/
export const nodeDict: any = {
[WorkflowType.TextInput]:textInputNode,
[WorkflowType.SpeechRecognition]:speechRecognitionNode,
[WorkflowType.ImageGeneration]:imageGenerationNode,
[WorkflowType.TextToSpeech]:textToSpeechNode,
[WorkflowType.SpeechToText]:speechToTextNode,
[WorkflowType.VariableAssignment]:variableAssignmentNode,
[WorkflowType.UserInterpretation]:userInterpreterNode
}
export function isWorkflow(type: string | undefined) : boolean {
return typeof type === "string" && ["WORKFLOW", "CUSTOM_WORKFLOW"].includes(type)
} This changes include addressing misconfigurations in fields data, ensuring consistency in naming conventions, improving error handling in the |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks clean, but there is a minor punctuation issue in the
reasoningContent
tooltip text:tooltip: 'Please set the thinking label based on the model\'s return,
should be corrected to:
tooltip: "Please set the thinking label based on the model's return,"
Make this change to ensure proper formatting. No other irregularities or issues were found.