mirror of
https://github.com/sasjs/server.git
synced 2026-01-07 22:50:05 +00:00
chore: rename Web folder to web
This commit is contained in:
21
web/src/containers/SASjsDrive/index.tsx
Normal file
21
web/src/containers/SASjsDrive/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, { useState } from 'react'
|
||||
|
||||
import CssBaseline from '@mui/material/CssBaseline'
|
||||
import Box from '@mui/material/Box'
|
||||
|
||||
import Header from '../../components/header'
|
||||
import SideBar from './sideBar'
|
||||
import Main from './main'
|
||||
|
||||
const SASjsDrive = () => {
|
||||
const [selectedFilePath, setSelectedFilePath] = useState('')
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<CssBaseline />
|
||||
<SideBar setSelectedFilePath={setSelectedFilePath} />
|
||||
<Main selectedFilePath={selectedFilePath} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default SASjsDrive
|
||||
121
web/src/containers/SASjsDrive/main.tsx
Normal file
121
web/src/containers/SASjsDrive/main.tsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import axios from 'axios'
|
||||
|
||||
import Editor from '@monaco-editor/react'
|
||||
|
||||
import Box from '@mui/material/Box'
|
||||
import Paper from '@mui/material/Paper'
|
||||
import Stack from '@mui/material/Stack'
|
||||
import Button from '@mui/material/Button'
|
||||
import Toolbar from '@mui/material/Toolbar'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
|
||||
const Main = (props: any) => {
|
||||
const baseUrl = window.location.origin
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [fileContentBeforeEdit, setFileContentBeforeEdit] = useState('')
|
||||
const [fileContent, setFileContent] = useState('')
|
||||
const [editMode, setEditMode] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (props.selectedFilePath !== '') {
|
||||
setIsLoading(true)
|
||||
axios
|
||||
.get(`${baseUrl}/SASjsApi/files?filePath=${props.selectedFilePath}`)
|
||||
.then((res: any) => {
|
||||
setIsLoading(false)
|
||||
setFileContent(res.data.fileContent)
|
||||
})
|
||||
}
|
||||
}, [props.selectedFilePath])
|
||||
|
||||
const handleEditSaveBtnClick = () => {
|
||||
if (!editMode) {
|
||||
setFileContentBeforeEdit(fileContent)
|
||||
setEditMode(true)
|
||||
} else {
|
||||
setIsLoading(true)
|
||||
axios
|
||||
.post(`${baseUrl}/SASjsApi/files`, {
|
||||
filePath: props.selectedFilePath,
|
||||
fileContent: fileContent
|
||||
})
|
||||
.then((res) => {
|
||||
setIsLoading(false)
|
||||
setEditMode(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelExecuteBtnClick = () => {
|
||||
if (editMode) {
|
||||
setFileContent(fileContentBeforeEdit)
|
||||
setEditMode(false)
|
||||
} else {
|
||||
setIsLoading(true)
|
||||
axios
|
||||
.get(`${baseUrl}/SASjsExecutor/do?_program=${props.selectedFilePath}`)
|
||||
.then((res) => {
|
||||
setIsLoading(false)
|
||||
setEditMode(false)
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box component="main" sx={{ flexGrow: 1, p: 3 }}>
|
||||
<Toolbar />
|
||||
<Paper
|
||||
sx={{
|
||||
height: '75vh',
|
||||
padding: '10px',
|
||||
overflow: 'auto',
|
||||
position: 'relative'
|
||||
}}
|
||||
elevation={3}
|
||||
>
|
||||
{isLoading && (
|
||||
<CircularProgress
|
||||
style={{ position: 'absolute', left: '50%', top: '50%' }}
|
||||
/>
|
||||
)}
|
||||
{!isLoading && props?.selectedFilePath !== '' && !editMode && (
|
||||
<code style={{ whiteSpace: 'break-spaces' }}>{fileContent}</code>
|
||||
)}
|
||||
{!isLoading && props?.selectedFilePath !== '' && editMode && (
|
||||
<Editor
|
||||
height="95%"
|
||||
value={fileContent}
|
||||
onChange={(val) => {
|
||||
if (val) setFileContent(val)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Paper>
|
||||
<Stack
|
||||
spacing={3}
|
||||
direction="row"
|
||||
sx={{ justifyContent: 'center', marginTop: '20px' }}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleEditSaveBtnClick}
|
||||
disabled={isLoading || props?.selectedFilePath === ''}
|
||||
>
|
||||
{!editMode ? 'Edit' : 'Save'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleCancelExecuteBtnClick}
|
||||
disabled={isLoading || props?.selectedFilePath === ''}
|
||||
>
|
||||
{editMode ? 'Cancel' : 'Execute'}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Main
|
||||
105
web/src/containers/SASjsDrive/sideBar.tsx
Normal file
105
web/src/containers/SASjsDrive/sideBar.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import axios from 'axios'
|
||||
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
import Box from '@mui/material/Box'
|
||||
import Drawer from '@mui/material/Drawer'
|
||||
import Toolbar from '@mui/material/Toolbar'
|
||||
import ListItem from '@mui/material/ListItem'
|
||||
import ListItemText from '@mui/material/ListItemText'
|
||||
|
||||
import TreeView from '@mui/lab/TreeView'
|
||||
import TreeItem from '@mui/lab/TreeItem'
|
||||
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
|
||||
|
||||
interface TreeNode {
|
||||
name: string
|
||||
relativePath: string
|
||||
absolutePath: string
|
||||
children: Array<TreeNode>
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
root: {
|
||||
'& .MuiTreeItem-content': {
|
||||
width: 'auto'
|
||||
}
|
||||
},
|
||||
listItem: {
|
||||
padding: 0
|
||||
}
|
||||
}))
|
||||
|
||||
const drawerWidth = 240
|
||||
|
||||
const SideBar = (props: any) => {
|
||||
const baseUrl = window.location.origin
|
||||
const classes = useStyles()
|
||||
|
||||
const [directoryData, setDirectoryData] = useState<TreeNode | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(`${baseUrl}/SASjsApi/executor`).then((res: any) => {
|
||||
if (res.data && res.data?.status === 'success') {
|
||||
setDirectoryData(res.data.tree)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const handleSelect = (node: TreeNode) => {
|
||||
if (!node.children.length) {
|
||||
window.history.pushState(
|
||||
'',
|
||||
'',
|
||||
`${baseUrl}/SASjsDrive?filepath=${node.relativePath}`
|
||||
)
|
||||
props.setSelectedFilePath(node.relativePath)
|
||||
}
|
||||
}
|
||||
|
||||
const renderTree = (nodes: TreeNode) => (
|
||||
<TreeItem
|
||||
classes={{ root: classes.root }}
|
||||
key={nodes.relativePath}
|
||||
nodeId={nodes.relativePath}
|
||||
label={
|
||||
<ListItem
|
||||
className={classes.listItem}
|
||||
onClick={() => handleSelect(nodes)}
|
||||
>
|
||||
<ListItemText primary={nodes.name} />
|
||||
</ListItem>
|
||||
}
|
||||
>
|
||||
{Array.isArray(nodes.children)
|
||||
? nodes.children.map((node) => renderTree(node))
|
||||
: null}
|
||||
</TreeItem>
|
||||
)
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
sx={{
|
||||
width: drawerWidth,
|
||||
flexShrink: 0,
|
||||
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' }
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
<Box sx={{ overflow: 'auto' }}>
|
||||
<TreeView
|
||||
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||
defaultExpandIcon={<ChevronRightIcon />}
|
||||
>
|
||||
{directoryData && renderTree(directoryData)}
|
||||
</TreeView>
|
||||
</Box>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
|
||||
export default SideBar
|
||||
15
web/src/containers/SASjsStudio/index.tsx
Normal file
15
web/src/containers/SASjsStudio/index.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
|
||||
import CssBaseline from '@mui/material/CssBaseline'
|
||||
import Box from '@mui/material/Box'
|
||||
|
||||
const SASjsStudio = () => {
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }} className="main">
|
||||
<CssBaseline />
|
||||
<h2>This is container for SAS studio</h2>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default SASjsStudio
|
||||
Reference in New Issue
Block a user