feat: update
This commit is contained in:
parent
20481ca406
commit
6511dc8941
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.6 KiB |
@ -7,7 +7,6 @@
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
@ -25,7 +24,7 @@
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<script src="https://cdn-0.plantuml.com/synchro2.min.js"></script>
|
||||
<title>React App</title>
|
||||
<title>RingCentral@Workflow Hub</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
@ -23,7 +23,7 @@ export const AIBot: FC<{
|
||||
Intelligence Admin Portal</a>
|
||||
</Typography>
|
||||
<Box>
|
||||
<TextField label="AI Robot ID" onChange={handleChange} value={value}
|
||||
<TextField label="AI Robot ID" fullWidth onChange={handleChange} value={value}
|
||||
/>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
@ -40,7 +40,8 @@ const ChatMessageWrap = styled(Box)<{ isMe: boolean }>(({ isMe }) => ({
|
||||
marginTop: 4,
|
||||
marginBottom: 4,
|
||||
display: 'flex',
|
||||
justifyContent: isMe ? 'flex-end' : 'flex-start'
|
||||
justifyContent: isMe ? 'flex-end' : 'flex-start',
|
||||
color: isMe ? 'rgba(0, 0, 0, 0.87)' : 'white'
|
||||
}));
|
||||
|
||||
const ChatMessage = styled(Box)(() => ({
|
||||
|
203
src/Create.tsx
203
src/Create.tsx
@ -12,10 +12,8 @@ import Button from '@mui/material/Button';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import SendIcon from '@mui/icons-material/Send';
|
||||
import List from '@mui/material/List';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import { ChatItem } from "./ChatItem";
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { cloneDeep, uniqueId } from 'lodash';
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
||||
@ -29,7 +27,11 @@ import { AIBot } from "./AIBot";
|
||||
import { GlipSender } from "./GlipSender";
|
||||
import { ScriptBlock } from "./Script";
|
||||
import { message } from 'mui-message';
|
||||
import { isChatBot } from "./transform";
|
||||
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
||||
import InputAdornment from "@mui/material/InputAdornment";
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import { styled } from "@mui/material/styles";
|
||||
|
||||
const DefaultMessage = [
|
||||
'Hello! Please tell me what kind of workflow you want to generate!\n',
|
||||
@ -55,7 +57,7 @@ type PreValue = string | undefined | null
|
||||
const preValueObj: { bot: PreValue; script: PreValue; email: PreValue; glip: PreValue } = {
|
||||
bot: '',
|
||||
script: '',
|
||||
email: '',
|
||||
email: '{"to":"","subject":"","content":"${localData.Desc}"}',
|
||||
glip: ''
|
||||
};
|
||||
|
||||
@ -66,7 +68,48 @@ interface Message {
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const SupportedBlock = ['BotMessage', 'Chat', 'GlipSender', 'Script'];
|
||||
interface ActionWithStateName extends Action {
|
||||
stateName: string;
|
||||
}
|
||||
|
||||
const AntSwitch = styled(Switch)(({ theme }) => ({
|
||||
width: 28,
|
||||
height: 16,
|
||||
padding: 0,
|
||||
display: 'flex',
|
||||
'&:active': {
|
||||
'& .MuiSwitch-thumb': {
|
||||
width: 15,
|
||||
},
|
||||
'& .MuiSwitch-switchBase.Mui-checked': {
|
||||
transform: 'translateX(9px)',
|
||||
},
|
||||
},
|
||||
'& .MuiSwitch-switchBase': {
|
||||
padding: 2,
|
||||
'&.Mui-checked': {
|
||||
transform: 'translateX(12px)',
|
||||
color: '#fff',
|
||||
'& + .MuiSwitch-track': {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
'& .MuiSwitch-thumb': {
|
||||
boxShadow: '0 2px 4px 0 rgb(0 35 11 / 20%)',
|
||||
width: 12,
|
||||
height: 12,
|
||||
borderRadius: 6,
|
||||
transition: theme.transitions.create(['width'], {
|
||||
duration: 200,
|
||||
}),
|
||||
},
|
||||
'& .MuiSwitch-track': {
|
||||
borderRadius: 16 / 2,
|
||||
opacity: 1,
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
}));
|
||||
|
||||
export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
const { id } = useParams();
|
||||
@ -88,22 +131,16 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
const flowDefinition = useMemo<Definition | undefined>(() => DSL2Json(workflowContent), [workflowContent]);
|
||||
const previewImg = useMemo<string>(() => Json2Preview(flowDefinition), [flowDefinition]);
|
||||
const chatContentRef = useRef<HTMLUListElement>(null);
|
||||
const actions = useMemo<Array<Action & {
|
||||
const actions = useMemo<ActionWithStateName[]>(() => ((flowDefinition || {}).states || []).reduce<Array<Action & {
|
||||
stateName: string
|
||||
}>>(() => ((flowDefinition || {}).states || []).reduce<Array<Action & { stateName: string }>>((l, s) => {
|
||||
}>>((l, s) => {
|
||||
l.push(...s.actions.map(a => ({ ...a, stateName: s.name })));
|
||||
return l;
|
||||
}, []), [flowDefinition]);
|
||||
const hasEmailSender = useMemo(() => actions.some(a => a.actionType === "EmailSender"), [actions]);
|
||||
const botAddinAction = useMemo<Action & {
|
||||
stateName: string
|
||||
} | undefined>(() => actions.find(a => a.actionType === "Chat"), [actions]);
|
||||
const scriptAction = useMemo<Action & {
|
||||
stateName: string
|
||||
} | undefined>(() => actions.find(a => a.actionType === "Script"), [actions]);
|
||||
const glipSenderAction = useMemo<Action & {
|
||||
stateName: string
|
||||
} | undefined>(() => actions.find(a => a.actionType === "GlipSender"), [actions]);
|
||||
const emailSenderAction = useMemo<ActionWithStateName | undefined>(() => actions.find(a => a.actionType === "EmailSender"), [actions]);
|
||||
const botAddinAction = useMemo<ActionWithStateName | undefined>(() => actions.find(a => a.actionType === "Chat"), [actions]);
|
||||
const scriptAction = useMemo<ActionWithStateName | undefined>(() => actions.find(a => a.actionType === "Script"), [actions]);
|
||||
const glipSenderAction = useMemo<ActionWithStateName | undefined>(() => actions.find(a => a.actionType === "GlipSender"), [actions]);
|
||||
const [aibot, setAIBot] = useState('');
|
||||
const [script, setScript] = useState('');
|
||||
const [emailData, setEmailData] = useState<EmailValue>({
|
||||
@ -112,14 +149,11 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
content: '${localData.Desc}',
|
||||
});
|
||||
const [glipSenderData, setGlipSenderData] = useState({
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
message: ''
|
||||
});
|
||||
const [channelId, setChannelId] = useState('78394499078-4034902020');
|
||||
const [glipSenderData, setGlipSenderData] = useState('');
|
||||
const [isImageMode, setImageMode] = useState(true);
|
||||
const creatorId = '4034902020';
|
||||
const location = useLocation();
|
||||
const [teamLink, setTeamLink] = useState('');
|
||||
const debug = useMemo(() => {
|
||||
return (new URLSearchParams(location.search)).get('debug') === 'true';
|
||||
}, [location]);
|
||||
@ -148,9 +182,6 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
setChatInput(e.target.value);
|
||||
};
|
||||
|
||||
const handleClickChip = (text: string) => () => {
|
||||
setChatInput(s => s + text);
|
||||
};
|
||||
const handleSend = async () => {
|
||||
const rId = uniqueId('r');
|
||||
|
||||
@ -185,24 +216,15 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
useEffect(() => {
|
||||
if (glipSenderAction) {
|
||||
let actionValueString = glipSenderAction.message;
|
||||
let crtValueString = glipSenderData.message;
|
||||
if (actionValueString !== preValueObj.glip && crtValueString === preValueObj.glip) {
|
||||
setGlipSenderData({
|
||||
clientSecret: '',
|
||||
clientId: '',
|
||||
message: actionValueString || '',
|
||||
});
|
||||
if (actionValueString !== preValueObj.glip && glipSenderData === preValueObj.glip) {
|
||||
setGlipSenderData(actionValueString || '');
|
||||
preValueObj.glip = actionValueString || '';
|
||||
}
|
||||
} else {
|
||||
if (preValueObj.glip) {
|
||||
preValueObj.glip = '';
|
||||
setGlipSenderData({
|
||||
clientSecret: '',
|
||||
clientId: '',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
message: '${localData.Desc}'
|
||||
});
|
||||
setGlipSenderData('${localData.Desc}');
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -232,7 +254,35 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [botAddinAction]);
|
||||
|
||||
useEffect(() => {
|
||||
if (emailSenderAction) {
|
||||
const newValueStr = JSON.stringify({
|
||||
to: emailSenderAction.to || '',
|
||||
subject: emailSenderAction.subject || '',
|
||||
content: emailSenderAction.content || ''
|
||||
});
|
||||
const crtValueStr = JSON.stringify({
|
||||
to: emailData.to,
|
||||
subject: emailData.subject,
|
||||
content: emailData.content
|
||||
});
|
||||
if (newValueStr !== preValueObj.email && crtValueStr === preValueObj.email) {
|
||||
setEmailData({
|
||||
to: emailSenderAction.to || '',
|
||||
subject: emailSenderAction.subject || '',
|
||||
content: emailSenderAction.content || ''
|
||||
});
|
||||
preValueObj.email = newValueStr || '';
|
||||
}
|
||||
} else {
|
||||
setEmailData({
|
||||
to: '',
|
||||
subject: '',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
content: '${localData.Desc}',
|
||||
});
|
||||
}
|
||||
}, [emailSenderAction]);
|
||||
useEffect(() => {
|
||||
if (chatContentRef.current) {
|
||||
chatContentRef.current.scrollTop = chatContentRef.current.scrollHeight - chatContentRef.current.offsetHeight;
|
||||
@ -250,15 +300,7 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
setWorkflowContent('');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasEmailSender)
|
||||
setEmailData({
|
||||
to: '',
|
||||
subject: '',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
content: '${localData.Desc}',
|
||||
});
|
||||
}, [hasEmailSender]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const handleSubmit = async () => {
|
||||
if (!flowDefinition) return;
|
||||
@ -278,11 +320,14 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
}
|
||||
if (action.actionType === 'GlipSender') {
|
||||
// action.url = glipSenderData.url;
|
||||
action.message = glipSenderData.message || '${localData.Desc}';
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
action.message = glipSenderData || '${localData.Desc}';
|
||||
}
|
||||
});
|
||||
});
|
||||
console.log(Json2Yml(newJson));
|
||||
const channelId = (teamLink.replace(/[^\d]+/, '')) + '-' + creatorId;
|
||||
console.log(channelId);
|
||||
await axios.put(`/bot/workflow/${id}`, {
|
||||
name: formJson.name,
|
||||
content: Json2Yml(newJson)
|
||||
@ -291,7 +336,7 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
await axios.delete(`/bot/workflow/${id}/bind/${channelId}`);
|
||||
await axios.post(`/bot/workflow/${id}/bind`, { channelId });
|
||||
}
|
||||
message.success(`Saved! ${debug ? 'Back to List and go bind your channel!' : ''}`);
|
||||
message.success(`Publish Success! ${debug ? 'Back to List and go bind your channel!' : ''}`);
|
||||
setTimeout(() => {
|
||||
navigate(`/${debug ? '?debug=true' : ''}`);
|
||||
}, 3000);
|
||||
@ -356,6 +401,9 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
}
|
||||
}}
|
||||
autoFocus
|
||||
InputProps={{
|
||||
startAdornment: <InputAdornment position="start"><AutoAwesomeIcon color="primary"/></InputAdornment>
|
||||
}}
|
||||
variant="outlined"
|
||||
focused placeholder="Enter your goal ..."
|
||||
multiline maxRows={3}
|
||||
@ -372,21 +420,56 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Box sx={{ border: 1, height: 600, borderRadius: 1, p: 2, mt: 4, borderColor: 'rgba(255,255,255,0.23)' }}>
|
||||
{!previewImg ? <>👋 The flow chart will be previewed here! <br/>😻 Tell the AI robot what you want to
|
||||
do! </> :
|
||||
<img src={previewImg} style={{ width: '100%', height: '100%' }} alt="preview"/>}
|
||||
<Box sx={{
|
||||
border: 1,
|
||||
height: 600,
|
||||
borderRadius: 1,
|
||||
mt: 4,
|
||||
borderColor: 'rgba(255,255,255,0.23)',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
{!previewImg ?
|
||||
<div style={{ padding: 16 }}>👋 The flow chart will be previewed here! <br/>😻 Tell the AI robot what
|
||||
you want to
|
||||
do! </div> :
|
||||
(
|
||||
<>
|
||||
<Stack sx={{ p: 2 }} direction="row" spacing={1} alignItems="center" justifyContent="flex-end">
|
||||
<Typography variant="body2">Raw</Typography>
|
||||
<AntSwitch checked={isImageMode} onChange={(_, checked) => setImageMode(checked)}/>
|
||||
<Typography variant="body2">Image</Typography>
|
||||
</Stack>
|
||||
{isImageMode ?
|
||||
<img src={previewImg} style={{ maxWidth: '100%', maxHeight: '100%' }} alt="preview"/> :
|
||||
<pre style={{ height: 546, overflow: 'auto', marginTop: 0 }}><code style={{
|
||||
fontSize: 12,
|
||||
textAlign: 'left',
|
||||
display: 'block',
|
||||
padding: 16,
|
||||
}}>{workflowContent}</code></pre>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Divider sx={{ mt: 4, mb: 4 }}/>
|
||||
{!!scriptAction || hasEmailSender || !!botAddinAction ?
|
||||
{!!scriptAction || !!emailSenderAction || !!botAddinAction || !!glipSenderAction ?
|
||||
<Typography variant="subtitle2" sx={{ mb: 2 }}>
|
||||
Please fill in the following information related to your workflow nodes. 👇🏻👇🏻</Typography> : null}
|
||||
{hasEmailSender && <EmailSender value={emailData} onChange={setEmailData}/>}
|
||||
Please fill in the following information related to your workflow nodes. 👇🏻👇🏻 </Typography> : null}
|
||||
{!!emailSenderAction && <EmailSender value={emailData} onChange={setEmailData}/>}
|
||||
{!!botAddinAction && <AIBot name={botAddinAction.stateName} value={aibot} onChange={setAIBot}/>}
|
||||
{!!scriptAction && <ScriptBlock name={scriptAction.stateName} value={script} onChange={setScript}/>}
|
||||
{!!glipSenderAction && <GlipSender debug={debug} value={glipSenderData} onChange={setGlipSenderData}/>}
|
||||
{!!glipSenderAction &&
|
||||
<GlipSender debug={debug} teamLink={teamLink} id={id} edit={edit} value={glipSenderData}
|
||||
onChange={(value, isTeamLink) => {
|
||||
if (isTeamLink) {
|
||||
setTeamLink(value);
|
||||
} else {
|
||||
setGlipSenderData(value);
|
||||
}
|
||||
}}/>}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<div style={{ height: 80 }}></div>
|
||||
@ -404,7 +487,7 @@ export const Create: FC<{ edit?: boolean }> = ({ edit }) => {
|
||||
borderColor: 'divider',
|
||||
display: { xs: 'flex' }, justifyContent: "flex-end"
|
||||
}}>
|
||||
<Button variant="contained" style={{ width: 100 }} onClick={handleSubmit}>Save</Button>
|
||||
<Button variant="contained" style={{ width: 100 }} onClick={handleSubmit}>Publish</Button>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import MonacoEditor from 'react-monaco-editor';
|
||||
|
||||
export const Editor: React.FC<{ value: string; onChange: (value: string) => void }> = ({ value, onChange }) => {
|
||||
|
@ -24,15 +24,15 @@ export const EmailSender: FC<{
|
||||
<Typography variant="subtitle1" sx={{mb: 1}}>Email Sender</Typography>
|
||||
<Box>
|
||||
<TextField label="Send To" placeholder="Please enter your email address" type="email"
|
||||
value={value} name="to" fullWidth sx={{mb: 4}}
|
||||
value={value.to} name="to" fullWidth sx={{mb: 4}}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<TextField label="Subject" placeholder="Please enter your email subject"
|
||||
value={value} name="subject" fullWidth sx={{mb: 4}}
|
||||
value={value.subject} name="subject" fullWidth sx={{mb: 4}}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<TextField label="Content" placeholder="Please enter your email content"
|
||||
value={value} name="content" fullWidth sx={{mb: 4}}
|
||||
value={value.content} name="content" fullWidth sx={{mb: 4}}
|
||||
onChange={handleChange} maxRows={8} minRows={3} multiline
|
||||
/>
|
||||
</Box>
|
||||
|
@ -1,41 +1,94 @@
|
||||
import React, { ChangeEvent, FC, useEffect, useState } from 'react';
|
||||
import React, { ChangeEvent, FC, useState } from 'react';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import InputAdornment from "@mui/material/InputAdornment";
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Visibility from '@mui/icons-material/Visibility';
|
||||
import VisibilityOff from '@mui/icons-material/VisibilityOff';
|
||||
import { MenuItem, Select, SelectChangeEvent } from "@mui/material";
|
||||
|
||||
export const GlipSender: FC<{
|
||||
value: string;
|
||||
debug?: boolean
|
||||
value: { clientId: string; clientSecret: string; message: string };
|
||||
onChange: (value: {
|
||||
clientId: string; clientSecret: string; message: string
|
||||
}) => void
|
||||
}> = ({ value, debug, onChange }) => {
|
||||
edit?: boolean
|
||||
id?: string
|
||||
teamLink: string
|
||||
onChange: (value: string, isTeamLink?: boolean) => void
|
||||
}> = ({ value, id,teamLink, debug, edit, onChange }) => {
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange({
|
||||
...value,
|
||||
[e.target.name]: e.target.value
|
||||
});
|
||||
onChange(e.target.value);
|
||||
};
|
||||
const [showPassword, setShowPassword] = React.useState(edit ? false : true);
|
||||
|
||||
const handleClickShowPassword = () => setShowPassword((show) => !show);
|
||||
|
||||
const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const [senderType, setSenderType] = useState('default');
|
||||
const handleChangeType = (e: SelectChangeEvent) => {
|
||||
setSenderType(e.target.value);
|
||||
};
|
||||
|
||||
const handleChangeTeam = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(event.target.value, true)
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Paper sx={{ p: 2, mb: 2 }}>
|
||||
<Typography variant="subtitle1">GlipSender</Typography>
|
||||
<Typography variant="caption" component="div" sx={{ mb: 1 }}>
|
||||
WFL Hub will send messages via <a style={{ color: '#f50057' }}
|
||||
href="https://developers.ringcentral.com/guide/team-messaging/bots/walkthrough"
|
||||
target="_blank" rel="noreferrer">RingCentral Bot</a>, please fill in:
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" sx={{ mb: 1 }}>GlipSender</Typography>
|
||||
<Box>
|
||||
{!debug &&
|
||||
<>
|
||||
<TextField label="RingCentral Bot Client ID" fullWidth name="clientId" onChange={handleChange}
|
||||
value={value.clientId} sx={{ mb: 4 }}/>
|
||||
<TextField label="RingCentral Bot Client Secret" sx={{ mb: 4 }}
|
||||
value={value.clientSecret} name="clientSecret" fullWidth onChange={handleChange}
|
||||
<Select value={senderType} sx={{ mb: 1 }} onChange={handleChangeType}>
|
||||
<MenuItem value="default">Use built-in bot (only supports team message)</MenuItem>
|
||||
<MenuItem value="custom">Use custom bot</MenuItem>
|
||||
</Select>
|
||||
{senderType === 'default' ? <>
|
||||
<Typography sx={{ mb: 2 }} variant="caption" component="div">
|
||||
WFL Hub will send message via default bot <a style={{ color: '#f50057' }}>@David-Bot</a>
|
||||
</Typography>
|
||||
<TextField label="Team Link" fullWidth name="teamLink" id="teamLink" key="1" sx={{ mb: 4 }} value={teamLink}
|
||||
onChange={handleChangeTeam}
|
||||
defaultValue={edit ? 'https://app.ringcentral.com/l/messages/134751420422' : ''}/>
|
||||
</> :
|
||||
<>
|
||||
<Typography variant="caption" component="div" sx={{ mb: 2 }}>
|
||||
WFL Hub will send messages via your <a style={{ color: '#f50057' }}
|
||||
href="https://developers.ringcentral.com/guide/team-messaging/bots/walkthrough"
|
||||
target="_blank" rel="noreferrer">RingCentral Bot</a>, please
|
||||
fill in:
|
||||
</Typography>
|
||||
<TextField label="RingCentral Bot Client ID" fullWidth name="clientId" key="2" id="clientId" sx={{ mb: 4 }}
|
||||
defaultValue={edit ? '0w3wgTW5dkdfGjdseGDJ2y' : ''}/>
|
||||
<TextField label="RingCentral Bot Client Secret" sx={{ mb: 4 }} key="3" name="clientSecret" id="clientSecret"
|
||||
fullWidth
|
||||
defaultValue={edit ? '6oGJ8Nko0socCF6rzFqKsk7FbNyT33ouDebXsOhACDhp' : ''}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={handleClickShowPassword}
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
edge="end"
|
||||
>
|
||||
{showPassword ? <VisibilityOff/> : <Visibility/>}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</>}
|
||||
|
||||
</>}
|
||||
<TextField label="Message format" placeholder="Please enter your message format"
|
||||
value={value.message} name="message" fullWidth
|
||||
value={value} name="message" fullWidth
|
||||
onChange={handleChange} maxRows={5} minRows={2} multiline
|
||||
/>
|
||||
</Box>
|
||||
|
28
src/List.tsx
28
src/List.tsx
@ -39,6 +39,7 @@ interface Workflow {
|
||||
id: string;
|
||||
name: string;
|
||||
lastModifiedTime: string;
|
||||
emoji?: string;
|
||||
}
|
||||
|
||||
export const List = () => {
|
||||
@ -52,7 +53,10 @@ export const List = () => {
|
||||
total: number
|
||||
workflows: Workflow[]
|
||||
}>('/api/public/wf/config/v1/account/10086/workflows').then(({ data }) => {
|
||||
setList(data.workflows);
|
||||
setList(data.workflows.map(it => ({
|
||||
...it,
|
||||
emoji: getRandomEmoji()
|
||||
})));
|
||||
});
|
||||
}, []);
|
||||
const handleOpen = () => {
|
||||
@ -84,7 +88,7 @@ export const List = () => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(event.currentTarget);
|
||||
const formJson = Object.fromEntries((formData as any).entries());
|
||||
const channelId = formJson.channelId.trim();
|
||||
const channelId = `${formJson.groupId.trim()}-${formJson.creatorId.trim()}`;
|
||||
await axios.delete(`/bot/workflow/${showBindModal}/bind/${channelId}`);
|
||||
await axios.post(`/bot/workflow/${showBindModal}/bind`, { channelId });
|
||||
message.success('Success!');
|
||||
@ -105,7 +109,7 @@ export const List = () => {
|
||||
<CardActionArea>
|
||||
<CardContent style={{ height: 100 }}>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
{getRandomEmoji()} {item.name || 'My Workflow'}
|
||||
{item.emoji} {item.name || 'My Workflow'}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions
|
||||
@ -121,8 +125,8 @@ export const List = () => {
|
||||
<Button size="small" onClick={(e: any) => {
|
||||
e.preventDefault();
|
||||
handleOpenBind(item.id);
|
||||
}}>Bind</Button> :
|
||||
<Switch defaultChecked/>}
|
||||
}}>Bind</Button> : <Button size="small">Copy</Button>}
|
||||
{/*<Switch defaultChecked/>*/}
|
||||
</CardActions>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
@ -147,7 +151,6 @@ export const List = () => {
|
||||
margin="dense"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue="My workflow"
|
||||
label="Workflow Name"
|
||||
fullWidth
|
||||
focused
|
||||
@ -169,10 +172,17 @@ export const List = () => {
|
||||
<TextField
|
||||
required
|
||||
margin="dense"
|
||||
id="channelId" focused
|
||||
id="groupId" focused
|
||||
variant="outlined"
|
||||
label="Channel Id" fullWidth name="channelId"
|
||||
helperText="ChannelId is ${groupId}-${creatorId}"
|
||||
label="Group Id" fullWidth name="groupId"
|
||||
helperText="You can get team groupId from team link"
|
||||
/>
|
||||
<TextField
|
||||
required
|
||||
margin="dense"
|
||||
id="creatorId" focused
|
||||
variant="outlined"
|
||||
label="Creator Id" fullWidth name="creatorId"
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
|
@ -30,3 +30,7 @@ a {
|
||||
.MuiButton-contained:hover {
|
||||
background-color: rgb(118, 126, 168) !important;
|
||||
}
|
||||
|
||||
.Mui-focused .MuiOutlinedInput-notchedOutline {
|
||||
/*color: #aab5f1*/
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ export interface Definition {
|
||||
export function Json2Preview(definition?: Definition): string {
|
||||
if (!definition) return '';
|
||||
try {
|
||||
console.log(transformDSL(definition));
|
||||
return compress(transformDSL(definition), '/svg/');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Action, Definition, State } from "./loadYml";
|
||||
|
||||
const EVENT_COLOR = "#LightYellow";
|
||||
const HTTP_COLOR = "#Peru";
|
||||
const SCRIPT_COLOR = "#Olive;text:white";
|
||||
const BOT_COLOR = "#Blue;text:white";
|
||||
const EMAIL_SENDER_COLOR = "#Red;text:white";
|
||||
const CHAT_BOT_COLOR = "#Orange;text:white";
|
||||
const GLIP_COLOR = "#Pink;text:white";
|
||||
const DEFAULT_COLOR = '#Grey;text;white';
|
||||
const EVENT_COLOR = "#IndianRed";
|
||||
const HTTP_COLOR = "#Sienna";
|
||||
const SCRIPT_COLOR = "#Olive";
|
||||
const BOT_COLOR = "#RoyalBlue";
|
||||
const EMAIL_SENDER_COLOR = "#Crimson";
|
||||
const CHAT_BOT_COLOR = "#OrangeRed";
|
||||
const GLIP_COLOR = "#DeepPink";
|
||||
|
||||
const EVENT_NAME = ": Event";
|
||||
const HTTP_NAME = ": Http";
|
||||
@ -15,33 +14,28 @@ const SCRIPT_NAME = ": Script";
|
||||
const BOT_NAME = ": Chat";
|
||||
const EMAIL_SENDER_NAME = ": EmailSender";
|
||||
const GLIP_SENDER_NAME = ': GlipSender';
|
||||
const EXIT_NAME = ": Exit";
|
||||
|
||||
function isHttp(actions: Action[]): boolean {
|
||||
export function isHttp(actions: Action[]): boolean {
|
||||
return actions
|
||||
.some((action) => action.actionType === "HttpRequest");
|
||||
}
|
||||
|
||||
function isScript(actions: Action[]): boolean {
|
||||
export function isScript(actions: Action[]): boolean {
|
||||
return actions
|
||||
.some((action) => action.actionType === "Script");
|
||||
}
|
||||
|
||||
function isChat(actions: Action[]): boolean {
|
||||
export function isChat(actions: Action[]): boolean {
|
||||
return actions
|
||||
.some((action) => action.actionType === 'ChatBot');
|
||||
}
|
||||
|
||||
function isGlipSender(actions: Action[]): boolean {
|
||||
export function isGlipSender(actions: Action[]): boolean {
|
||||
return actions
|
||||
.some((action) => action.actionType === 'GlipSender');
|
||||
}
|
||||
|
||||
function isExit(actions: Action[]): boolean {
|
||||
return actions.some((action) => action.actionType === 'Exit');
|
||||
}
|
||||
|
||||
function isEmailSender(actions: Action[]): boolean {
|
||||
export function isEmailSender(actions: Action[]): boolean {
|
||||
return actions
|
||||
.some((action) => action.actionType === "EmailSender");
|
||||
}
|
||||
@ -188,8 +182,22 @@ export function transformDSL(definition: Definition): string {
|
||||
sb += drawStateLine(eventState, state) || '';
|
||||
}
|
||||
return `@startuml
|
||||
skinparam backgroundColor #242425
|
||||
skinparam state {
|
||||
FontColor white
|
||||
BackgroundColor DimGray
|
||||
BorderColor #AAB5F1
|
||||
ArrowColor #AAB5F1
|
||||
ArrowFontColor #AAB5F1
|
||||
}
|
||||
|
||||
skinparam activity {
|
||||
StartColor Silver
|
||||
EndColor Silver
|
||||
}
|
||||
|
||||
${sb}
|
||||
|
||||
@enduml
|
||||
`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user