Many fixes for frontend and backend related to Oauth2 and environment control

This commit is contained in:
Frikky
2023-11-24 12:03:20 +01:00
parent 8c6a39f658
commit 1fd46a7307
14 changed files with 494 additions and 302 deletions
+30 -29
View File
@@ -269,35 +269,8 @@ const EditWorkflow = (props) => {
/>
</div>
<div style={{display: "flex", marginTop: 10, }}>
<MuiChipsInput
style={{ flex: 1, maxHeight: 40, }}
InputProps={{
style: {
color: "white",
},
}}
placeholder="Tags"
color="primary"
fullWidth
value={newWorkflowTags}
onChange={(chip) => {
console.log("Chip: ", chip)
//newWorkflowTags.push(chip);
setNewWorkflowTags(chip);
}}
onAdd={(chip) => {
newWorkflowTags.push(chip);
setNewWorkflowTags(newWorkflowTags);
}}
onDelete={(chip, index) => {
console.log("Deleting: ", chip, index)
newWorkflowTags.splice(index, 1);
setNewWorkflowTags(newWorkflowTags);
setUpdate(Math.random());
}}
/>
{usecases !== null && usecases !== undefined && usecases.length > 0 ?
<FormControl style={{flex: 1, marginLeft: 5, }}>
<FormControl style={{flex: 1, marginRight: 5,}}>
<InputLabel htmlFor="grouped-select-usecase">Usecases</InputLabel>
<Select
defaultValue=""
@@ -350,6 +323,33 @@ const EditWorkflow = (props) => {
</Select>
</FormControl>
: null}
<MuiChipsInput
style={{ flex: 1, maxHeight: 120, overflow: "auto",}}
InputProps={{
style: {
color: "white",
},
}}
placeholder="Tags"
color="primary"
fullWidth
value={newWorkflowTags}
onChange={(chip) => {
console.log("Chip: ", chip)
//newWorkflowTags.push(chip);
setNewWorkflowTags(chip);
}}
onAdd={(chip) => {
newWorkflowTags.push(chip);
setNewWorkflowTags(newWorkflowTags);
}}
onDelete={(chip, index) => {
console.log("Deleting: ", chip, index)
newWorkflowTags.splice(index, 1);
setNewWorkflowTags(newWorkflowTags);
setUpdate(Math.random());
}}
/>
</div>
{showMoreClicked === true ?
@@ -365,7 +365,8 @@ const EditWorkflow = (props) => {
onChange={(e) => {
console.log("Data: ", e.target.value)
innerWorkflow.workflow_type = e.target.value
//innerWorkflow.workflow_type = e.target.value
innerWorkflow.status = e.target.value
setInnerWorkflow(innerWorkflow)
}}
>
+5 -2
View File
@@ -1352,14 +1352,17 @@ const Header = (props) => {
);
// <Divider style={{height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
return !isMobile ?
isLoggedIn ?
//
/*
!isLoggedIn ?
<div style={{minHeight: 68, maxHeight: 68, backgroundColor: theme.palette.backgroundColor, }}>
<BrowserView style={{position: "sticky", top: 0, }}>
{loginTextBrowser}
</BrowserView>
</div>
:
*/
return !isMobile ?
<AppBar
position="sticky"
color="transparent"
+36 -24
View File
@@ -112,8 +112,6 @@ const AuthenticationOauth2 = (props) => {
authenticationType.client_secret.length > 0
);
console.log("AUTH: ", authenticationType)
const [clientId, setClientId] = React.useState(defaultConfigSet ? authenticationType.client_id : "");
const [clientSecret, setClientSecret] = React.useState(defaultConfigSet ? authenticationType.client_secret : "");
@@ -125,7 +123,7 @@ const AuthenticationOauth2 = (props) => {
const [offlineAccess, setOfflineAccess] = React.useState(true);
const allscopes = authenticationType.scope !== undefined && authenticationType.scope !== null ? authenticationType.scope : [];
const [selectedScopes, setSelectedScopes] = React.useState(allscopes !== null && allscopes !== undefined ? allscopes.length > 0 && allscopes.length <= 3 ? [allscopes[0]] : [] : [])
const [selectedScopes, setSelectedScopes] = React.useState(allscopes !== null && allscopes !== undefined ? allscopes.length > 0 && allscopes.length <= 3 ? allscopes : [] : [])
const [manuallyConfigure, setManuallyConfigure] = React.useState(
defaultConfigSet ? false : true
@@ -303,6 +301,23 @@ const AuthenticationOauth2 = (props) => {
if ((authenticationType.redirect_uri === undefined || authenticationType.redirect_uri === null || authenticationType.redirect_uri.length === 0) && (authenticationType.token_uri !== undefined && authenticationType.token_uri !== null && authenticationType.token_uri.length > 0)) {
console.log("No redirect URI found, and token URI found. Assuming client credentials flow and saving directly in the database")
var tokenUri = authenticationType.token_uri;
if (oauthUrl !== undefined && oauthUrl !== null && oauthUrl.length > 0 && selectedApp !== undefined && selectedApp !== null) {
var same = false
for (var i = 0; i < selectedApp.authentication.parameters.length; i++) {
const param = selectedApp.authentication.parameters[i];
if (param.name === "url" && (param.value === oauthUrl || param.example === oauthUrl)) {
same = true
break
}
}
if (!same) {
tokenUri = oauthUrl
}
}
// Find app.configuration=true fields in the app.paramters
var parsedFields = [{
"key": "client_id",
@@ -318,7 +333,7 @@ const AuthenticationOauth2 = (props) => {
},
{
"key": "token_uri",
"value": authenticationType.token_uri,
"value": tokenUri,
}]
if (authenticationType.grant_type !== undefined && authenticationType.grant_type !== null && authenticationType.grant_type.length > 0) {
@@ -360,14 +375,14 @@ const AuthenticationOauth2 = (props) => {
"reference_workflow": workflowId,
}
setNewAppAuth(appAuthData)
setNewAppAuth(appAuthData, true)
// Wait 1 second, then get app auth with update
//
if (getAppAuthentication !== undefined) {
setTimeout(() => {
getAppAuthentication(true, true, true);
}, 1000)
}
//if (getAppAuthentication !== undefined) {
// setTimeout(() => {
// getAppAuthentication(true, true, true);
// }, 1000)
//}
return
}
@@ -397,8 +412,6 @@ const AuthenticationOauth2 = (props) => {
}
const authentication_url = authenticationType.token_uri;
//console.log("AUTH: ", authenticationType)
//console.log("SCOPES2: ", resources)
const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`;
const workflowId = workflow !== undefined ? workflow.id : "";
var state = `workflow_id%3D${workflowId}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`;
@@ -523,7 +536,6 @@ const AuthenticationOauth2 = (props) => {
}
const handleSubmitCheck = () => {
console.log("NEW AUTH: ", authenticationOption);
if (authenticationOption.label.length === 0) {
authenticationOption.label = `Auth for ${selectedApp.name}`;
//toast("Label can't be empty")
@@ -673,7 +685,7 @@ const AuthenticationOauth2 = (props) => {
)}
</Button>
if (authButtonOnly === true && (authenticationType.grant_type === undefined || authenticationType.grant_type === null || authenticationType.grant_type === "")) {
if (authButtonOnly === true && (authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null && authenticationType.redirect_uri.length > 0) && (authenticationType.token_uri !== undefined && authenticationType.token_uri !== null && authenticationType.token_uri.length > 0)) {
return autoAuthButton
}
@@ -777,10 +789,14 @@ const AuthenticationOauth2 = (props) => {
setOauthUrl(data.value);
}
const defaultValue = data.name === "url" && authenticationType.token_uri !== undefined && authenticationType.token_uri !== null && authenticationType.token_uri.length > 0 && (authenticationType.authorizationUrl === undefined || authenticationType.authorizationUrl === null || authenticationType.authorizationUrl.length === 0) ? authenticationType.token_uri : data.value === undefined || data.value === null ? "" : data.value
const fieldname = data.name === "url" && authenticationType.grant_type !== undefined && authenticationType.grant_type !== null && authenticationType.grant_type.length > 0 ? "Token URL" : data.name
return (
<div key={index} style={{ marginTop: 10 }}>
<LockOpenIcon style={{ marginRight: 10 }} />
<b>{data.name}</b>
<b>{fieldname}</b>
{data.schema !== undefined &&
data.schema !== null &&
@@ -793,6 +809,7 @@ const AuthenticationOauth2 = (props) => {
}}
defaultValue={"false"}
fullWidth
label={fieldname}
onChange={(e) => {
console.log("Value: ", e.target.value);
authenticationOption.fields[data.name] = e.target.value;
@@ -842,16 +859,11 @@ const AuthenticationOauth2 = (props) => {
: "text"
}
color="primary"
defaultValue={
data.value !== undefined && data.value !== null
? data.value
: ""
}
defaultValue={defaultValue}
placeholder={data.example}
onChange={(event) => {
authenticationOption.fields[data.name] =
event.target.value;
console.log("Setting oauth url");
authenticationOption.fields[data.name] = event.target.value;
console.log("Setting oauth url: ", event.target.value);
setOauthUrl(event.target.value);
//const [oauthUrl, setOauthUrl] = React.useState("")
}}
+8
View File
@@ -181,6 +181,8 @@ const ParsedAction = (props) => {
const [fieldCount, setFieldCount] = React.useState(0);
const [hiddenDescription, setHiddenDescription] = React.useState(true);
const [autoCompleting, setAutocompleting] = React.useState(false);
useEffect(() => {
if (setLastSaved !== undefined) {
@@ -2909,9 +2911,11 @@ const ParsedAction = (props) => {
marginLeft: 15,
paddingRight: 0,
}}
disabled={autoCompleting}
onClick={() => {
// aiSubmit(aiMsg, undefined, undefined, newSelectedAction)
aiSubmit("Fill based on previous values", undefined, undefined, selectedAction)
setAutocompleting(true)
}}
>
<Tooltip
@@ -2919,7 +2923,11 @@ const ParsedAction = (props) => {
title={"Autocompletes fields. Uses NAME of the action and previous values' results."}
placement="top"
>
{autoCompleting ?
<CircularProgress style={{height: 20, width: 20, }} />
:
<AutoFixHighIcon style={{ color: "rgba(255,255,255,0.7)", height: 24, }} />
}
</Tooltip>
</IconButton>
</div>
+15 -5
View File
@@ -315,16 +315,26 @@ const RuntimeDebugger = (props) => {
)
},
},
{ field: 'startTimestamp', headerName: 'Start time', width: 160, },
{ field: 'endTimestamp', headerName: 'End time', width: 160, },
{ field: 'startTimestamp', headerName: 'Start time (UTC)', width: 160, },
{ field: 'endTimestamp', headerName: 'End time (UTC)', width: 160, },
{
field: 'id',
headerName: 'Explore',
width: 65,
renderCell: (params) => (
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
<OpenInNewIcon fontSize="small" />
</Link>
<Tooltip arrow placement="right" title={
<Typography variant="body2" style={{whiteSpace: "pre-line", }}>
{params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ?
params.row.result
:
null
}
</Typography>
} >
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
<OpenInNewIcon fontSize="small" />
</Link>
</Tooltip>
),
},
]
+141 -129
View File
@@ -22,6 +22,7 @@ import { isMobile } from "react-device-detect"
import { NestedMenuItem } from "mui-nested-menu"
import { GetParsedPaths, FindJsonPath } from "../views/Apps.jsx";
import { SetJsonDotnotation } from "../views/AngularWorkflow.jsx";
import { vscodeDark, vscodeDarkInit } from '@uiw/codemirror-theme-vscode';
import {
FullscreenExit as FullscreenExitIcon,
@@ -82,6 +83,7 @@ const pythonFilters = [
{"name": "Handle JSON", "value": `{% python %}\nimport json\njsondata = json.loads(r"""$nodename""")\n{% endpython %}`, "example": ``},
]
/*
const shuffleTheme = createTheme({
theme: 'dark',
settings: {
@@ -110,6 +112,7 @@ const shuffleTheme = createTheme({
{ tag: t.attributeName, color: '#5c6166' },
],
});
*/
const CodeEditor = (props) => {
const {
@@ -547,7 +550,7 @@ const CodeEditor = (props) => {
var code_lines = localcodedata.split('\n')
for (var i = 0; i < code_lines.length; i++){
var current_code_line = code_lines[i]
// console.log(current_code_line)
console.log("Codeline: ", current_code_line)
var variable_occurence = current_code_line.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
@@ -609,9 +612,10 @@ const CodeEditor = (props) => {
const fixedVariable = fixVariable(variable_occurence[occ])
var correctVariable = availableVariables.includes(fixedVariable)
if(!correctVariable) {
console.log("Line: ", i, "ch: ", dollar_occurence[occ])
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: rgb(248, 106, 62, 0.9); padding-top: 2px; padding-bottom: 2px; color: white"})
}
else{
} else {
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; padding-top: 2px; padding-bottom: 2px; color: white"})
}
// console.log(correctVariables)
@@ -674,36 +678,33 @@ const CodeEditor = (props) => {
try {
for (var i = 0; i < found.length; i++) {
try {
// For found specifically, should replace .#\d with .# with regex
//found[i] = found[i].toLowerCase()
const fixedVariable = fixVariable(found[i])
//var correctVariable = availableVariables.includes(fixedVariable)
//
var valuefound = false
for (var j = 0; j < actionlist.length; j++) {
if(fixedVariable.slice(1,).toLowerCase() === actionlist[j].autocomplete.toLowerCase()){
valuefound = true
if(fixedVariable.slice(1,).toLowerCase() !== actionlist[j].autocomplete.toLowerCase()){
continue
}
try {
if (typeof actionlist[j].example === "object") {
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
valuefound = true
} else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) {
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
} else {
input = input.replace(found[i], actionlist[j].example, -1)
}
} catch (e) {
try {
if (typeof actionlist[j].example === "object") {
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
} else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) {
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
} else {
input = input.replace(found[i], actionlist[j].example, -1)
}
} else {
// Couldn't find the correct example value
} catch (e) {
input = input.replace(found[i], actionlist[j].example, -1)
}
}
//if (!valuefound) {
// console.log("Couldn't find value "+fixedVariable)
//}
if (!valuefound && availableVariables.includes(fixedVariable)) {
var shouldbreak = false
for (var k=0; k < actionlist.length; k++){
@@ -714,46 +715,48 @@ const CodeEditor = (props) => {
for (var key in parsedPaths) {
const fullpath = "$"+actionlist[k].autocomplete.toLowerCase()+parsedPaths[key].autocomplete
if (fullpath === fixedVariable) {
//if (actionlist[k].example === undefined) {
// actionlist[k].example = "TMP"
//}
if (fullpath !== fixedVariable) {
continue
}
var new_input = ""
try {
new_input = FindJsonPath(fullpath, actionlist[k].example)
} catch (e) {
console.log("ERR IN INPUT: ", e)
}
//if (actionlist[k].example === undefined) {
// actionlist[k].example = "TMP"
//}
//console.log("Got output for: ", fullpath, new_input, actionlist[k].example, typeof new_input)
var new_input = ""
try {
new_input = FindJsonPath(fullpath, actionlist[k].example)
} catch (e) {
console.log("ERR IN INPUT: ", e)
}
if (typeof new_input === "object") {
new_input = JSON.stringify(new_input)
console.log("Got output for: ", fullpath, new_input, actionlist[k].example, typeof new_input)
if (typeof new_input === "object") {
new_input = JSON.stringify(new_input)
} else {
if (typeof new_input === "string") {
new_input = new_input
} else {
if (typeof new_input === "string") {
new_input = new_input
} else {
console.log("NO TYPE? ", typeof new_input)
try {
new_input = new_input.toString()
} catch (e) {
new_input = ""
}
console.log("NO TYPE? ", typeof new_input)
try {
new_input = new_input.toString()
} catch (e) {
new_input = ""
}
}
//console.log("FOUND2: ", fixedVariable, actionlist[j].example)
input = input.replace(fixedVariable, new_input, -1)
input = input.replace(found[i], new_input, -1)
//} catch (e) {
// input = input.replace(found[i], actionlist[k].example)
//}
shouldbreak = true
break
}
//console.log("FOUND2: ", fixedVariable, actionlist[j].example)
input = input.replace(fixedVariable, new_input, -1)
input = input.replace(found[i], new_input, -1)
//} catch (e) {
// input = input.replace(found[i], actionlist[k].example)
//}
shouldbreak = true
break
}
if (shouldbreak) {
@@ -766,7 +769,7 @@ const CodeEditor = (props) => {
}
}
} catch (e) {
//console.log("Outer replace error: ", e)
console.log("Outer replace error: ", e)
}
}
@@ -895,7 +898,7 @@ const CodeEditor = (props) => {
aria-labelledby="draggable-code-modal"
disableBackdropClick={true}
disableEnforceFocus={true}
//style={{ pointerEvents: "none" }}
//style={{ pointerEvents: "none" }}
hideBackdrop={true}
open={expansionModalOpen}
onClose={() => {
@@ -964,6 +967,7 @@ const CodeEditor = (props) => {
}}
>
<div style={{display: "flex"}}>
{/*
<DialogTitle
id="draggable-dialog-title"
style={{
@@ -974,59 +978,9 @@ const CodeEditor = (props) => {
>
Code Editor
</DialogTitle>
<IconButton
style={{
marginLeft: isMobile ? "80%" : 350,
height: 50,
width: 50,
}}
onClick={() => {
}}
>
<Tooltip
color="primary"
title={"Test Liquid in the playground"}
placement="top"
>
<a
href="https://pwwang.github.io/liquidpy/playground/"
rel="norefferer"
target="_blank"
>
<ExtensionIcon style={{color: "rgba(255,255,255,0.7)"}}/>
</a>
</Tooltip>
</IconButton>
<IconButton
style={{
height: 50,
width: 50,
}}
disabled={isAiLoading}
onClick={() => {
autoFormat(localcodedata)
}}
>
<Tooltip
color="primary"
title={"Auto format data"}
placement="top"
>
{isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/>
:
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
}
</Tooltip>
</IconButton>
</div>
</div>
}
*/}
{ isFileEditor ? null :
<div style={{display: "flex"}}>
<div style={{display: "flex", maxHeight: 40, }}>
<Button
id="basic-button"
aria-haspopup="true"
@@ -1035,7 +989,7 @@ const CodeEditor = (props) => {
variant="outlined"
color="secondary"
style={{
textTransform: "none",
textTransform: "none",
width: 100,
}}
onClick={(event) => {
@@ -1143,9 +1097,9 @@ const CodeEditor = (props) => {
variant="outlined"
color="secondary"
style={{
textTransform: "none",
textTransform: "none",
width: 130,
marginLeft: 170,
marginLeft: 20,
}}
onClick={(event) => {
setMenuPosition({
@@ -1393,28 +1347,86 @@ const CodeEditor = (props) => {
</Menu>
</div>
}
<span style={{
<IconButton
style={{
marginLeft: isMobile ? "80%" : 30,
height: 50,
width: 50,
}}
onClick={() => {
}}
>
<Tooltip
color="primary"
title={"Test Liquid in the playground"}
placement="top"
>
<a
href="https://pwwang.github.io/liquidpy/playground/"
rel="norefferer"
target="_blank"
>
<ExtensionIcon style={{color: "rgba(255,255,255,0.7)"}}/>
</a>
</Tooltip>
</IconButton>
<IconButton
style={{
height: 50,
width: 50,
}}
disabled={isAiLoading}
onClick={() => {
autoFormat(localcodedata)
}}
>
<Tooltip
color="primary"
title={"Auto format data"}
placement="top"
>
{isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/>
:
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
}
</Tooltip>
</IconButton>
</div>
</div>
}
<div style={{
borderRadius: theme.palette.borderRadius,
position: "relative",
paddingTop: 0,
minHeight: 548,
overflow: "hidden",
}}>
<CodeMirror
theme={vscodeDark}
value={localcodedata}
height={isFileEditor ? 450 : 525}
height={isFileEditor ? 450 : 500}
width={isFileEditor ? 650 : 600}
style={{
maxWidth: isFileEditor ? 450 : 500,
maxWidth: isFileEditor ? 450 : 600,
maxHeight: 548,
minHeight: 548,
wordBreak: "break-word",
marginTop: 0,
paddingTop: 0,
backgroundColor: "rgba(40,40,40,1)",
minHeight: 470,
paddingBottom: 10,
overflow: "hidden",
}}
onCursorActivity = {(value) => {
// console.log(value.getCursor())
console.log("CURSOR: ", value.getCursor())
setCurrentCharacter(value.getCursor().ch)
setCurrentLine(value.getCursor().line)
// console.log(value.getCursor().ch, value.getCursor().line)
findIndex(value.getCursor().line, value.getCursor().ch)
highlight_variables(value)
}}
onChange={(value, viewUpdate) => {
@@ -1422,20 +1434,19 @@ const CodeEditor = (props) => {
setlocalcodedata(value)
expectedOutput(value)
highlight_variables(value)
//if(value.display.input.prevInput.startsWith('$') || value.display.input.prevInput.endsWith('$')){
// setEditorPopupOpen(true)
//}
}}
extensions={[]}//indentWithTab]}
theme={shuffleTheme}
options={{
styleSelectedText: true,
keyMap: 'sublime',
mode: validation === true ? "json" : "python",
lineWrapping: linewrap,
theme: vscodeDark,
}}
/>
</span>
</div>
{/*editorPopupOpen ?
<Paper
@@ -1550,13 +1561,14 @@ const CodeEditor = (props) => {
</div>
</div>
<div style={{flex: 1, marginLeft: 25, }}>
<div style={{flex: 1, marginLeft: 5, borderLeft: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, }}>
{isFileEditor ? null :
<div>
{isMobile ? null :
<DialogTitle
style={{
paddingLeft: 10,
paddingTop: 0,
display: "flex",
}}
>
@@ -1564,7 +1576,7 @@ const CodeEditor = (props) => {
Expected Output
</span>
<IconButton disabled={executing} color="primary" style={{border: `1px solid ${theme.palette.primary.main}`, marginLeft: 100, padding: 8}} variant="contained" onClick={() => {
<IconButton disabled={executing} color="secondary" style={{border: `1px solid ${theme.palette.primary.main}`, marginLeft: 250, padding: 8}} variant="contained" onClick={() => {
executeSingleAction(expOutput)
}}>
<Tooltip title="Try it! This runs the Shuffle Tools 'repeat back to me' or 'execute python' action with what you see in the expected output window. Commonly used to test your Python scripts or Liquid filters, not requiring the full workflow to run again." placement="top">
@@ -1613,8 +1625,8 @@ const CodeEditor = (props) => {
borderRadius: theme.palette.borderRadius,
maxHeight: 500,
minHeight: 500,
minWidth: 500,
maxWidth: 500,
minWidth: 580,
maxWidth: 580,
overflow: "auto",
whiteSpace: "pre-wrap",
}}