mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 19:00:59 +03:00
Initial push
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { forwardRef } from 'react'
|
||||
// third-party
|
||||
import { motion, useCycle } from 'framer-motion'
|
||||
|
||||
// ==============================|| ANIMATION BUTTON ||============================== //
|
||||
|
||||
const AnimateButton = forwardRef(function AnimateButton({ children, type, direction, offset, scale }, ref) {
|
||||
let offset1
|
||||
let offset2
|
||||
switch (direction) {
|
||||
case 'up':
|
||||
case 'left':
|
||||
offset1 = offset
|
||||
offset2 = 0
|
||||
break
|
||||
case 'right':
|
||||
case 'down':
|
||||
default:
|
||||
offset1 = 0
|
||||
offset2 = offset
|
||||
break
|
||||
}
|
||||
|
||||
const [x, cycleX] = useCycle(offset1, offset2)
|
||||
const [y, cycleY] = useCycle(offset1, offset2)
|
||||
|
||||
switch (type) {
|
||||
case 'rotate':
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{
|
||||
repeat: Infinity,
|
||||
repeatType: 'loop',
|
||||
duration: 2,
|
||||
repeatDelay: 0
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
case 'slide':
|
||||
if (direction === 'up' || direction === 'down') {
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
animate={{ y: y !== undefined ? y : '' }}
|
||||
onHoverEnd={() => cycleY()}
|
||||
onHoverStart={() => cycleY()}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<motion.div ref={ref} animate={{ x: x !== undefined ? x : '' }} onHoverEnd={() => cycleX()} onHoverStart={() => cycleX()}>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
|
||||
case 'scale':
|
||||
default:
|
||||
if (typeof scale === 'number') {
|
||||
scale = {
|
||||
hover: scale,
|
||||
tap: scale
|
||||
}
|
||||
}
|
||||
return (
|
||||
<motion.div ref={ref} whileHover={{ scale: scale?.hover }} whileTap={{ scale: scale?.tap }}>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
AnimateButton.propTypes = {
|
||||
children: PropTypes.node,
|
||||
offset: PropTypes.number,
|
||||
type: PropTypes.oneOf(['slide', 'scale', 'rotate']),
|
||||
direction: PropTypes.oneOf(['up', 'down', 'left', 'right']),
|
||||
scale: PropTypes.oneOfType([PropTypes.number, PropTypes.object])
|
||||
}
|
||||
|
||||
AnimateButton.defaultProps = {
|
||||
type: 'scale',
|
||||
offset: 10,
|
||||
direction: 'right',
|
||||
scale: {
|
||||
hover: 1,
|
||||
tap: 0.9
|
||||
}
|
||||
}
|
||||
|
||||
export default AnimateButton
|
||||
@@ -0,0 +1,11 @@
|
||||
import { styled } from '@mui/material/styles'
|
||||
import { Button } from '@mui/material'
|
||||
|
||||
export const StyledButton = styled(Button)(({ theme, color = 'primary' }) => ({
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette[color].main,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette[color].main,
|
||||
backgroundImage: `linear-gradient(rgb(0 0 0/10%) 0 0)`
|
||||
}
|
||||
}))
|
||||
@@ -0,0 +1,11 @@
|
||||
import { styled } from '@mui/material/styles'
|
||||
import { Fab } from '@mui/material'
|
||||
|
||||
export const StyledFab = styled(Fab)(({ theme, color = 'primary' }) => ({
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette[color].main,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette[color].main,
|
||||
backgroundImage: `linear-gradient(rgb(0 0 0/10%) 0 0)`
|
||||
}
|
||||
}))
|
||||
@@ -0,0 +1,95 @@
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
// material-ui
|
||||
import { styled, useTheme } from '@mui/material/styles'
|
||||
import { Box, Grid, Chip, Typography } from '@mui/material'
|
||||
|
||||
// project imports
|
||||
import MainCard from 'ui-component/cards/MainCard'
|
||||
import SkeletonChatflowCard from 'ui-component/cards/Skeleton/ChatflowCard'
|
||||
|
||||
const CardWrapper = styled(MainCard)(({ theme }) => ({
|
||||
background: theme.palette.card.main,
|
||||
color: theme.darkTextPrimary,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
background: theme.palette.card.hover,
|
||||
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 20%)'
|
||||
}
|
||||
}))
|
||||
|
||||
// ===========================|| CONTRACT CARD ||=========================== //
|
||||
|
||||
const ItemCard = ({ isLoading, data, images, onClick }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
const chipSX = {
|
||||
height: 24,
|
||||
padding: '0 6px'
|
||||
}
|
||||
|
||||
const activeChatflowSX = {
|
||||
...chipSX,
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.success.dark
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<SkeletonChatflowCard />
|
||||
) : (
|
||||
<CardWrapper border={false} content={false} onClick={onClick}>
|
||||
<Box sx={{ p: 2.25 }}>
|
||||
<Grid container direction='column'>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Typography sx={{ fontSize: '1.5rem', fontWeight: 500 }}>{data.name}</Typography>
|
||||
</div>
|
||||
<Grid sx={{ mt: 1, mb: 1 }} container direction='row'>
|
||||
{data.deployed && (
|
||||
<Grid item>
|
||||
<Chip label='Deployed' sx={activeChatflowSX} />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
{images && (
|
||||
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 10 }}>
|
||||
{images.map((img) => (
|
||||
<div
|
||||
key={img}
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
marginRight: 5,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: 'white'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
style={{ width: '100%', height: '100%', padding: 5, objectFit: 'contain' }}
|
||||
alt=''
|
||||
src={img}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
</CardWrapper>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
ItemCard.propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
data: PropTypes.object,
|
||||
images: PropTypes.array,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default ItemCard
|
||||
@@ -0,0 +1,79 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
import { Card, CardContent, CardHeader, Divider, Typography } from '@mui/material'
|
||||
|
||||
// constant
|
||||
const headerSX = {
|
||||
'& .MuiCardHeader-action': { mr: 0 }
|
||||
}
|
||||
|
||||
// ==============================|| CUSTOM MAIN CARD ||============================== //
|
||||
|
||||
const MainCard = forwardRef(function MainCard(
|
||||
{
|
||||
border = true,
|
||||
boxShadow,
|
||||
children,
|
||||
content = true,
|
||||
contentClass = '',
|
||||
contentSX = {},
|
||||
darkTitle,
|
||||
secondary,
|
||||
shadow,
|
||||
sx = {},
|
||||
title,
|
||||
...others
|
||||
},
|
||||
ref
|
||||
) {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Card
|
||||
ref={ref}
|
||||
{...others}
|
||||
sx={{
|
||||
border: border ? '1px solid' : 'none',
|
||||
borderColor: theme.palette.primary[200] + 75,
|
||||
':hover': {
|
||||
boxShadow: boxShadow ? shadow || '0 2px 14px 0 rgb(32 40 45 / 8%)' : 'inherit'
|
||||
},
|
||||
...sx
|
||||
}}
|
||||
>
|
||||
{/* card header and action */}
|
||||
{!darkTitle && title && <CardHeader sx={headerSX} title={title} action={secondary} />}
|
||||
{darkTitle && title && <CardHeader sx={headerSX} title={<Typography variant='h3'>{title}</Typography>} action={secondary} />}
|
||||
|
||||
{/* content & header divider */}
|
||||
{title && <Divider />}
|
||||
|
||||
{/* card content */}
|
||||
{content && (
|
||||
<CardContent sx={contentSX} className={contentClass}>
|
||||
{children}
|
||||
</CardContent>
|
||||
)}
|
||||
{!content && children}
|
||||
</Card>
|
||||
)
|
||||
})
|
||||
|
||||
MainCard.propTypes = {
|
||||
border: PropTypes.bool,
|
||||
boxShadow: PropTypes.bool,
|
||||
children: PropTypes.node,
|
||||
content: PropTypes.bool,
|
||||
contentClass: PropTypes.string,
|
||||
contentSX: PropTypes.object,
|
||||
darkTitle: PropTypes.bool,
|
||||
secondary: PropTypes.oneOfType([PropTypes.node, PropTypes.string, PropTypes.object]),
|
||||
shadow: PropTypes.string,
|
||||
sx: PropTypes.object,
|
||||
title: PropTypes.oneOfType([PropTypes.node, PropTypes.string, PropTypes.object])
|
||||
}
|
||||
|
||||
export default MainCard
|
||||
@@ -0,0 +1,32 @@
|
||||
// material-ui
|
||||
import { Card, CardContent, Grid } from '@mui/material'
|
||||
import Skeleton from '@mui/material/Skeleton'
|
||||
|
||||
// ==============================|| SKELETON - BRIDGE CARD ||============================== //
|
||||
|
||||
const ChatflowCard = () => (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Grid container direction='column'>
|
||||
<Grid item>
|
||||
<Grid container justifyContent='space-between'>
|
||||
<Grid item>
|
||||
<Skeleton variant='rectangular' width={44} height={44} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Skeleton variant='rectangular' width={34} height={34} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Skeleton variant='rectangular' sx={{ my: 2 }} height={40} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Skeleton variant='rectangular' height={30} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
export default ChatflowCard
|
||||
@@ -0,0 +1,39 @@
|
||||
import { createPortal } from 'react-dom'
|
||||
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material'
|
||||
import useConfirm from 'hooks/useConfirm'
|
||||
import { StyledButton } from 'ui-component/button/StyledButton'
|
||||
|
||||
const ConfirmDialog = () => {
|
||||
const { onConfirm, onCancel, confirmState } = useConfirm()
|
||||
const portalElement = document.getElementById('portal')
|
||||
|
||||
const component = confirmState.show ? (
|
||||
<Dialog
|
||||
fullWidth
|
||||
maxWidth='xs'
|
||||
open={confirmState.show}
|
||||
onClose={onCancel}
|
||||
aria-labelledby='alert-dialog-title'
|
||||
aria-describedby='alert-dialog-description'
|
||||
>
|
||||
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
|
||||
{confirmState.title}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText sx={{ color: 'black' }} id='alert-dialog-description'>
|
||||
{confirmState.description}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel}>{confirmState.cancelButtonName}</Button>
|
||||
<StyledButton variant='contained' onClick={onConfirm}>
|
||||
{confirmState.confirmButtonName}
|
||||
</StyledButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
) : null
|
||||
|
||||
return createPortal(component, portalElement)
|
||||
}
|
||||
|
||||
export default ConfirmDialog
|
||||
@@ -0,0 +1,61 @@
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Button, Dialog, DialogActions, DialogContent, OutlinedInput, DialogTitle } from '@mui/material'
|
||||
import { StyledButton } from 'ui-component/button/StyledButton'
|
||||
|
||||
const SaveChatflowDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
|
||||
const portalElement = document.getElementById('portal')
|
||||
|
||||
const [chatflowName, setChatflowName] = useState('')
|
||||
const [isReadyToSave, setIsReadyToSave] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (chatflowName) setIsReadyToSave(true)
|
||||
else setIsReadyToSave(false)
|
||||
}, [chatflowName])
|
||||
|
||||
const component = show ? (
|
||||
<Dialog
|
||||
open={show}
|
||||
fullWidth
|
||||
maxWidth='xs'
|
||||
onClose={onCancel}
|
||||
aria-labelledby='alert-dialog-title'
|
||||
aria-describedby='alert-dialog-description'
|
||||
>
|
||||
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
|
||||
{dialogProps.title}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<OutlinedInput
|
||||
sx={{ mt: 1 }}
|
||||
id='chatflow-name'
|
||||
type='text'
|
||||
fullWidth
|
||||
placeholder='My New Chatflow'
|
||||
value={chatflowName}
|
||||
onChange={(e) => setChatflowName(e.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel}>{dialogProps.cancelButtonName}</Button>
|
||||
<StyledButton disabled={!isReadyToSave} variant='contained' onClick={() => onConfirm(chatflowName)}>
|
||||
{dialogProps.confirmButtonName}
|
||||
</StyledButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
) : null
|
||||
|
||||
return createPortal(component, portalElement)
|
||||
}
|
||||
|
||||
SaveChatflowDialog.propTypes = {
|
||||
show: PropTypes.bool,
|
||||
dialogProps: PropTypes.object,
|
||||
onCancel: PropTypes.func,
|
||||
onConfirm: PropTypes.func
|
||||
}
|
||||
|
||||
export default SaveChatflowDialog
|
||||
@@ -0,0 +1,61 @@
|
||||
import { useState } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
import { Popper, FormControl, TextField, Box, Typography } from '@mui/material'
|
||||
import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete'
|
||||
import { styled } from '@mui/material/styles'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const StyledPopper = styled(Popper)({
|
||||
boxShadow: '0px 8px 10px -5px rgb(0 0 0 / 20%), 0px 16px 24px 2px rgb(0 0 0 / 14%), 0px 6px 30px 5px rgb(0 0 0 / 12%)',
|
||||
borderRadius: '10px',
|
||||
[`& .${autocompleteClasses.listbox}`]: {
|
||||
boxSizing: 'border-box',
|
||||
'& ul': {
|
||||
padding: 10,
|
||||
margin: 10
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const Dropdown = ({ name, value, options, onSelect }) => {
|
||||
const customization = useSelector((state) => state.customization)
|
||||
const findMatchingOptions = (options = [], value) => options.find((option) => option.name === value)
|
||||
const getDefaultOptionValue = () => ''
|
||||
let [internalValue, setInternalValue] = useState(value ?? 'choose an option')
|
||||
|
||||
return (
|
||||
<FormControl sx={{ mt: 1, width: '100%' }} size='small'>
|
||||
<Autocomplete
|
||||
id={name}
|
||||
size='small'
|
||||
options={options || []}
|
||||
value={findMatchingOptions(options, internalValue) || getDefaultOptionValue()}
|
||||
onChange={(e, selection) => {
|
||||
const value = selection ? selection.name : ''
|
||||
setInternalValue(value)
|
||||
onSelect(value)
|
||||
}}
|
||||
PopperComponent={StyledPopper}
|
||||
renderInput={(params) => <TextField {...params} value={internalValue} />}
|
||||
renderOption={(props, option) => (
|
||||
<Box component='li' {...props}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<Typography variant='h5'>{option.label}</Typography>
|
||||
{option.description && (
|
||||
<Typography sx={{ color: customization.isDarkMode ? '#9e9e9e' : '' }}>{option.description}</Typography>
|
||||
)}
|
||||
</div>
|
||||
</Box>
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
)
|
||||
}
|
||||
|
||||
Dropdown.propTypes = {
|
||||
name: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
options: PropTypes.array,
|
||||
onSelect: PropTypes.func
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Editor from 'react-simple-code-editor'
|
||||
import { highlight, languages } from 'prismjs/components/prism-core'
|
||||
import 'prismjs/components/prism-clike'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-json'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import './prism-dark.css'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
export const DarkCodeEditor = ({ value, placeholder, type, style, onValueChange, onMouseUp, onBlur }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Editor
|
||||
value={value}
|
||||
placeholder={placeholder}
|
||||
highlight={(code) => highlight(code, type === 'json' ? languages.json : languages.js)}
|
||||
padding={10}
|
||||
onValueChange={onValueChange}
|
||||
onMouseUp={onMouseUp}
|
||||
onBlur={onBlur}
|
||||
style={{
|
||||
...style,
|
||||
background: theme.palette.codeEditor.main
|
||||
}}
|
||||
textareaClassName='editor__textarea'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
DarkCodeEditor.propTypes = {
|
||||
value: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
onValueChange: PropTypes.func,
|
||||
onMouseUp: PropTypes.func,
|
||||
onBlur: PropTypes.func
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Editor from 'react-simple-code-editor'
|
||||
import { highlight, languages } from 'prismjs/components/prism-core'
|
||||
import 'prismjs/components/prism-clike'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-json'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import './prism-light.css'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
export const LightCodeEditor = ({ value, placeholder, type, style, onValueChange, onMouseUp, onBlur }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Editor
|
||||
value={value}
|
||||
placeholder={placeholder}
|
||||
highlight={(code) => highlight(code, type === 'json' ? languages.json : languages.js)}
|
||||
padding={10}
|
||||
onValueChange={onValueChange}
|
||||
onMouseUp={onMouseUp}
|
||||
onBlur={onBlur}
|
||||
style={{
|
||||
...style,
|
||||
background: theme.palette.card.main
|
||||
}}
|
||||
textareaClassName='editor__textarea'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
LightCodeEditor.propTypes = {
|
||||
value: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
onValueChange: PropTypes.func,
|
||||
onMouseUp: PropTypes.func,
|
||||
onBlur: PropTypes.func
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
pre[class*='language-'],
|
||||
code[class*='language-'] {
|
||||
color: #d4d4d4;
|
||||
font-size: 13px;
|
||||
text-shadow: none;
|
||||
font-family: Menlo, Monaco, Consolas, 'Andale Mono', 'Ubuntu Mono', 'Courier New', monospace;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*='language-']::selection,
|
||||
code[class*='language-']::selection,
|
||||
pre[class*='language-'] *::selection,
|
||||
code[class*='language-'] *::selection {
|
||||
text-shadow: none;
|
||||
background: #264f78;
|
||||
}
|
||||
|
||||
@media print {
|
||||
pre[class*='language-'],
|
||||
code[class*='language-'] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
pre[class*='language-'] {
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
background: #1e1e1e;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*='language-'] {
|
||||
padding: 0.1em 0.3em;
|
||||
border-radius: 0.3em;
|
||||
color: #db4c69;
|
||||
background: #1e1e1e;
|
||||
}
|
||||
/*********************************************************
|
||||
* Tokens
|
||||
*/
|
||||
.namespace {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.token.doctype .token.doctype-tag {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.doctype .token.name {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog {
|
||||
color: #6a9955;
|
||||
}
|
||||
|
||||
.token.punctuation,
|
||||
.language-html .language-css .token.punctuation,
|
||||
.language-html .language-javascript .token.punctuation {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.inserted,
|
||||
.token.unit {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.deleted {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.language-css .token.string.url {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.token.operator.arrow {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.atrule {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.token.atrule .token.rule {
|
||||
color: #c586c0;
|
||||
}
|
||||
|
||||
.token.atrule .token.url {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.atrule .token.url .token.function {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.token.atrule .token.url .token.punctuation {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.keyword.module,
|
||||
.token.keyword.control-flow {
|
||||
color: #c586c0;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.function .token.maybe-class-name {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.token.regex {
|
||||
color: #d16969;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.class-name,
|
||||
.token.maybe-class-name {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
|
||||
.token.console {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.parameter {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.interpolation {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.punctuation.interpolation-punctuation {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.variable,
|
||||
.token.imports .token.maybe-class-name,
|
||||
.token.exports .token.maybe-class-name {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: #d7ba7d;
|
||||
}
|
||||
|
||||
.token.escape {
|
||||
color: #d7ba7d;
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.tag .token.punctuation {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.token.cdata {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.token.attr-name {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.attr-value,
|
||||
.token.attr-value .token.punctuation {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.token.attr-value .token.punctuation.attr-equals {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.namespace {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
/*********************************************************
|
||||
* Language Specific
|
||||
*/
|
||||
|
||||
pre[class*='language-javascript'],
|
||||
code[class*='language-javascript'],
|
||||
pre[class*='language-jsx'],
|
||||
code[class*='language-jsx'],
|
||||
pre[class*='language-typescript'],
|
||||
code[class*='language-typescript'],
|
||||
pre[class*='language-tsx'],
|
||||
code[class*='language-tsx'] {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
pre[class*='language-css'],
|
||||
code[class*='language-css'] {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
pre[class*='language-html'],
|
||||
code[class*='language-html'] {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.language-regex .token.anchor {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.language-html .token.punctuation {
|
||||
color: #808080;
|
||||
}
|
||||
/*********************************************************
|
||||
* Line highlighting
|
||||
*/
|
||||
pre[class*='language-'] > code[class*='language-'] {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.line-highlight.line-highlight {
|
||||
background: #f7ebc6;
|
||||
box-shadow: inset 5px 0 0 #f7d87c;
|
||||
z-index: 0;
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
color: #90a4ae;
|
||||
background: #fafafa;
|
||||
font-family: Roboto Mono, monospace;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
code[class*='language-']::-moz-selection,
|
||||
pre[class*='language-']::-moz-selection,
|
||||
code[class*='language-'] ::-moz-selection,
|
||||
pre[class*='language-'] ::-moz-selection {
|
||||
background: #cceae7;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
code[class*='language-']::selection,
|
||||
pre[class*='language-']::selection,
|
||||
code[class*='language-'] ::selection,
|
||||
pre[class*='language-'] ::selection {
|
||||
background: #cceae7;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*='language-'] {
|
||||
white-space: normal;
|
||||
border-radius: 0.2em;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
pre[class*='language-'] {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
margin: 0.5em 0;
|
||||
padding: 1.25em 1em;
|
||||
}
|
||||
|
||||
.language-css > code,
|
||||
.language-sass > code,
|
||||
.language-scss > code {
|
||||
color: #f76d47;
|
||||
}
|
||||
|
||||
[class*='language-'] .namespace {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.token.atrule {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.attr-name {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.attr-value {
|
||||
color: #f6a434;
|
||||
}
|
||||
|
||||
.token.attribute {
|
||||
color: #f6a434;
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.builtin {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.cdata {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.char {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.class {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.class-name {
|
||||
color: #6182b8;
|
||||
}
|
||||
|
||||
.token.comment {
|
||||
color: #aabfc9;
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.deleted {
|
||||
color: #e53935;
|
||||
}
|
||||
|
||||
.token.doctype {
|
||||
color: #aabfc9;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: #e53935;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.hexcode {
|
||||
color: #f76d47;
|
||||
}
|
||||
|
||||
.token.id {
|
||||
color: #7c4dff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
color: #7c4dff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.number {
|
||||
color: #f76d47;
|
||||
}
|
||||
|
||||
.token.operator {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.prolog {
|
||||
color: #aabfc9;
|
||||
}
|
||||
|
||||
.token.property {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.pseudo-class {
|
||||
color: #f6a434;
|
||||
}
|
||||
|
||||
.token.pseudo-element {
|
||||
color: #f6a434;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #39adb5;
|
||||
}
|
||||
|
||||
.token.regex {
|
||||
color: #6182b8;
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: #e53935;
|
||||
}
|
||||
|
||||
.token.string {
|
||||
color: #f6a434;
|
||||
}
|
||||
|
||||
.token.symbol {
|
||||
color: #7c4dff;
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: #e53935;
|
||||
}
|
||||
|
||||
.token.unit {
|
||||
color: #f76d47;
|
||||
}
|
||||
|
||||
.token.url {
|
||||
color: #e53935;
|
||||
}
|
||||
|
||||
.token.variable {
|
||||
color: #e53935;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
import MuiAvatar from '@mui/material/Avatar'
|
||||
|
||||
// ==============================|| AVATAR ||============================== //
|
||||
|
||||
const Avatar = ({ color, outline, size, sx, ...others }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
const colorSX = color && !outline && { color: theme.palette.background.paper, bgcolor: `${color}.main` }
|
||||
const outlineSX = outline && {
|
||||
color: color ? `${color}.main` : `primary.main`,
|
||||
bgcolor: theme.palette.background.paper,
|
||||
border: '2px solid',
|
||||
borderColor: color ? `${color}.main` : `primary.main`
|
||||
}
|
||||
let sizeSX = {}
|
||||
switch (size) {
|
||||
case 'badge':
|
||||
sizeSX = {
|
||||
width: theme.spacing(3.5),
|
||||
height: theme.spacing(3.5)
|
||||
}
|
||||
break
|
||||
case 'xs':
|
||||
sizeSX = {
|
||||
width: theme.spacing(4.25),
|
||||
height: theme.spacing(4.25)
|
||||
}
|
||||
break
|
||||
case 'sm':
|
||||
sizeSX = {
|
||||
width: theme.spacing(5),
|
||||
height: theme.spacing(5)
|
||||
}
|
||||
break
|
||||
case 'lg':
|
||||
sizeSX = {
|
||||
width: theme.spacing(9),
|
||||
height: theme.spacing(9)
|
||||
}
|
||||
break
|
||||
case 'xl':
|
||||
sizeSX = {
|
||||
width: theme.spacing(10.25),
|
||||
height: theme.spacing(10.25)
|
||||
}
|
||||
break
|
||||
case 'md':
|
||||
sizeSX = {
|
||||
width: theme.spacing(7.5),
|
||||
height: theme.spacing(7.5)
|
||||
}
|
||||
break
|
||||
default:
|
||||
sizeSX = {}
|
||||
}
|
||||
|
||||
return <MuiAvatar sx={{ ...colorSX, ...outlineSX, ...sizeSX, ...sx }} {...others} />
|
||||
}
|
||||
|
||||
Avatar.propTypes = {
|
||||
className: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
outline: PropTypes.bool,
|
||||
size: PropTypes.string,
|
||||
sx: PropTypes.object
|
||||
}
|
||||
|
||||
export default Avatar
|
||||
@@ -0,0 +1,184 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
import { Box, Card, Divider, Grid, Typography } from '@mui/material'
|
||||
import MuiBreadcrumbs from '@mui/material/Breadcrumbs'
|
||||
|
||||
// project imports
|
||||
import config from 'config'
|
||||
import { gridSpacing } from 'store/constant'
|
||||
|
||||
// assets
|
||||
import { IconTallymark1 } from '@tabler/icons'
|
||||
import AccountTreeTwoToneIcon from '@mui/icons-material/AccountTreeTwoTone'
|
||||
import HomeIcon from '@mui/icons-material/Home'
|
||||
import HomeTwoToneIcon from '@mui/icons-material/HomeTwoTone'
|
||||
|
||||
const linkSX = {
|
||||
display: 'flex',
|
||||
color: 'grey.900',
|
||||
textDecoration: 'none',
|
||||
alignContent: 'center',
|
||||
alignItems: 'center'
|
||||
}
|
||||
|
||||
// ==============================|| BREADCRUMBS ||============================== //
|
||||
|
||||
const Breadcrumbs = ({ card, divider, icon, icons, maxItems, navigation, rightAlign, separator, title, titleBottom, ...others }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
const iconStyle = {
|
||||
marginRight: theme.spacing(0.75),
|
||||
marginTop: `-${theme.spacing(0.25)}`,
|
||||
width: '1rem',
|
||||
height: '1rem',
|
||||
color: theme.palette.secondary.main
|
||||
}
|
||||
|
||||
const [main, setMain] = useState()
|
||||
const [item, setItem] = useState()
|
||||
|
||||
// set active item state
|
||||
const getCollapse = (menu) => {
|
||||
if (menu.children) {
|
||||
menu.children.filter((collapse) => {
|
||||
if (collapse.type && collapse.type === 'collapse') {
|
||||
getCollapse(collapse)
|
||||
} else if (collapse.type && collapse.type === 'item') {
|
||||
if (document.location.pathname === config.basename + collapse.url) {
|
||||
setMain(menu)
|
||||
setItem(collapse)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
navigation?.items?.map((menu) => {
|
||||
if (menu.type && menu.type === 'group') {
|
||||
getCollapse(menu)
|
||||
}
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
// item separator
|
||||
const SeparatorIcon = separator
|
||||
const separatorIcon = separator ? <SeparatorIcon stroke={1.5} size='1rem' /> : <IconTallymark1 stroke={1.5} size='1rem' />
|
||||
|
||||
let mainContent
|
||||
let itemContent
|
||||
let breadcrumbContent = <Typography />
|
||||
let itemTitle = ''
|
||||
let CollapseIcon
|
||||
let ItemIcon
|
||||
|
||||
// collapse item
|
||||
if (main && main.type === 'collapse') {
|
||||
CollapseIcon = main.icon ? main.icon : AccountTreeTwoToneIcon
|
||||
mainContent = (
|
||||
<Typography component={Link} to='#' variant='subtitle1' sx={linkSX}>
|
||||
{icons && <CollapseIcon style={iconStyle} />}
|
||||
{main.title}
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
// items
|
||||
if (item && item.type === 'item') {
|
||||
itemTitle = item.title
|
||||
|
||||
ItemIcon = item.icon ? item.icon : AccountTreeTwoToneIcon
|
||||
itemContent = (
|
||||
<Typography
|
||||
variant='subtitle1'
|
||||
sx={{
|
||||
display: 'flex',
|
||||
textDecoration: 'none',
|
||||
alignContent: 'center',
|
||||
alignItems: 'center',
|
||||
color: 'grey.500'
|
||||
}}
|
||||
>
|
||||
{icons && <ItemIcon style={iconStyle} />}
|
||||
{itemTitle}
|
||||
</Typography>
|
||||
)
|
||||
|
||||
// main
|
||||
if (item.breadcrumbs !== false) {
|
||||
breadcrumbContent = (
|
||||
<Card
|
||||
sx={{
|
||||
border: 'none'
|
||||
}}
|
||||
{...others}
|
||||
>
|
||||
<Box sx={{ p: 2, pl: card === false ? 0 : 2 }}>
|
||||
<Grid
|
||||
container
|
||||
direction={rightAlign ? 'row' : 'column'}
|
||||
justifyContent={rightAlign ? 'space-between' : 'flex-start'}
|
||||
alignItems={rightAlign ? 'center' : 'flex-start'}
|
||||
spacing={1}
|
||||
>
|
||||
{title && !titleBottom && (
|
||||
<Grid item>
|
||||
<Typography variant='h3' sx={{ fontWeight: 500 }}>
|
||||
{item.title}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item>
|
||||
<MuiBreadcrumbs
|
||||
sx={{ '& .MuiBreadcrumbs-separator': { width: 16, ml: 1.25, mr: 1.25 } }}
|
||||
aria-label='breadcrumb'
|
||||
maxItems={maxItems || 8}
|
||||
separator={separatorIcon}
|
||||
>
|
||||
<Typography component={Link} to='/' color='inherit' variant='subtitle1' sx={linkSX}>
|
||||
{icons && <HomeTwoToneIcon sx={iconStyle} />}
|
||||
{icon && <HomeIcon sx={{ ...iconStyle, mr: 0 }} />}
|
||||
{!icon && 'Dashboard'}
|
||||
</Typography>
|
||||
{mainContent}
|
||||
{itemContent}
|
||||
</MuiBreadcrumbs>
|
||||
</Grid>
|
||||
{title && titleBottom && (
|
||||
<Grid item>
|
||||
<Typography variant='h3' sx={{ fontWeight: 500 }}>
|
||||
{item.title}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
{card === false && divider !== false && <Divider sx={{ borderColor: theme.palette.primary.main, mb: gridSpacing }} />}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return breadcrumbContent
|
||||
}
|
||||
|
||||
Breadcrumbs.propTypes = {
|
||||
card: PropTypes.bool,
|
||||
divider: PropTypes.bool,
|
||||
icon: PropTypes.bool,
|
||||
icons: PropTypes.bool,
|
||||
maxItems: PropTypes.number,
|
||||
navigation: PropTypes.object,
|
||||
rightAlign: PropTypes.bool,
|
||||
separator: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
||||
title: PropTypes.bool,
|
||||
titleBottom: PropTypes.bool
|
||||
}
|
||||
|
||||
export default Breadcrumbs
|
||||
@@ -0,0 +1,22 @@
|
||||
import logo from 'assets/images/flowise_logo.png'
|
||||
import logoDark from 'assets/images/flowise_logo_dark.png'
|
||||
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
// ==============================|| LOGO ||============================== //
|
||||
|
||||
const Logo = () => {
|
||||
const customization = useSelector((state) => state.customization)
|
||||
|
||||
return (
|
||||
<div style={{ alignItems: 'center', display: 'flex', flexDirection: 'row' }}>
|
||||
<img
|
||||
style={{ objectFit: 'contain', height: 'auto', width: 150 }}
|
||||
src={customization.isDarkMode ? logoDark : logo}
|
||||
alt='Flowise'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Logo
|
||||
@@ -0,0 +1,107 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
// material-ui
|
||||
import { Collapse, Fade, Box, Grow, Slide, Zoom } from '@mui/material'
|
||||
|
||||
// ==============================|| TRANSITIONS ||============================== //
|
||||
|
||||
const Transitions = forwardRef(function Transitions({ children, position, type, direction, ...others }, ref) {
|
||||
let positionSX = {
|
||||
transformOrigin: '0 0 0'
|
||||
}
|
||||
|
||||
switch (position) {
|
||||
case 'top-right':
|
||||
positionSX = {
|
||||
transformOrigin: 'top right'
|
||||
}
|
||||
break
|
||||
case 'top':
|
||||
positionSX = {
|
||||
transformOrigin: 'top'
|
||||
}
|
||||
break
|
||||
case 'bottom-left':
|
||||
positionSX = {
|
||||
transformOrigin: 'bottom left'
|
||||
}
|
||||
break
|
||||
case 'bottom-right':
|
||||
positionSX = {
|
||||
transformOrigin: 'bottom right'
|
||||
}
|
||||
break
|
||||
case 'bottom':
|
||||
positionSX = {
|
||||
transformOrigin: 'bottom'
|
||||
}
|
||||
break
|
||||
case 'top-left':
|
||||
default:
|
||||
positionSX = {
|
||||
transformOrigin: '0 0 0'
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return (
|
||||
<Box ref={ref}>
|
||||
{type === 'grow' && (
|
||||
<Grow {...others}>
|
||||
<Box sx={positionSX}>{children}</Box>
|
||||
</Grow>
|
||||
)}
|
||||
{type === 'collapse' && (
|
||||
<Collapse {...others} sx={positionSX}>
|
||||
{children}
|
||||
</Collapse>
|
||||
)}
|
||||
{type === 'fade' && (
|
||||
<Fade
|
||||
{...others}
|
||||
timeout={{
|
||||
appear: 500,
|
||||
enter: 600,
|
||||
exit: 400
|
||||
}}
|
||||
>
|
||||
<Box sx={positionSX}>{children}</Box>
|
||||
</Fade>
|
||||
)}
|
||||
{type === 'slide' && (
|
||||
<Slide
|
||||
{...others}
|
||||
timeout={{
|
||||
appear: 0,
|
||||
enter: 400,
|
||||
exit: 200
|
||||
}}
|
||||
direction={direction}
|
||||
>
|
||||
<Box sx={positionSX}>{children}</Box>
|
||||
</Slide>
|
||||
)}
|
||||
{type === 'zoom' && (
|
||||
<Zoom {...others}>
|
||||
<Box sx={positionSX}>{children}</Box>
|
||||
</Zoom>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
|
||||
Transitions.propTypes = {
|
||||
children: PropTypes.node,
|
||||
type: PropTypes.oneOf(['grow', 'fade', 'collapse', 'slide', 'zoom']),
|
||||
position: PropTypes.oneOf(['top-left', 'top-right', 'top', 'bottom-left', 'bottom-right', 'bottom']),
|
||||
direction: PropTypes.oneOf(['up', 'down', 'left', 'right'])
|
||||
}
|
||||
|
||||
Transitions.defaultProps = {
|
||||
type: 'grow',
|
||||
position: 'top-left',
|
||||
direction: 'up'
|
||||
}
|
||||
|
||||
export default Transitions
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { FormControl, OutlinedInput } from '@mui/material'
|
||||
|
||||
export const Input = ({ inputParam, value, onChange }) => {
|
||||
const [myValue, setMyValue] = useState(value ?? '')
|
||||
return (
|
||||
<FormControl sx={{ mt: 1, width: '100%' }} size='small'>
|
||||
<OutlinedInput
|
||||
id={inputParam.name}
|
||||
size='small'
|
||||
type={inputParam.type === 'string' ? 'text' : inputParam.type}
|
||||
placeholder={inputParam.placeholder}
|
||||
multiline={!!inputParam.rows}
|
||||
maxRows={inputParam.rows || 0}
|
||||
minRows={inputParam.rows || 0}
|
||||
value={myValue}
|
||||
name={inputParam.name}
|
||||
onChange={(e) => {
|
||||
setMyValue(e.target.value)
|
||||
onChange(e.target.value)
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
)
|
||||
}
|
||||
|
||||
Input.propTypes = {
|
||||
inputParam: PropTypes.object,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Suspense } from 'react'
|
||||
|
||||
// project imports
|
||||
import Loader from './Loader'
|
||||
|
||||
// ==============================|| LOADABLE - LAZY LOADING ||============================== //
|
||||
|
||||
const Loadable = (Component) =>
|
||||
function WithLoader(props) {
|
||||
return (
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Component {...props} />
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
export default Loadable
|
||||
@@ -0,0 +1,21 @@
|
||||
// material-ui
|
||||
import LinearProgress from '@mui/material/LinearProgress'
|
||||
import { styled } from '@mui/material/styles'
|
||||
|
||||
// styles
|
||||
const LoaderWrapper = styled('div')({
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1301,
|
||||
width: '100%'
|
||||
})
|
||||
|
||||
// ==============================|| LOADER ||============================== //
|
||||
const Loader = () => (
|
||||
<LoaderWrapper>
|
||||
<LinearProgress color='primary' />
|
||||
</LoaderWrapper>
|
||||
)
|
||||
|
||||
export default Loader
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Info } from '@mui/icons-material'
|
||||
import { IconButton, Tooltip } from '@mui/material'
|
||||
import parser from 'html-react-parser'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
export const TooltipWithParser = ({ title }) => {
|
||||
const customization = useSelector((state) => state.customization)
|
||||
|
||||
return (
|
||||
<Tooltip title={parser(title)} placement='right'>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<IconButton sx={{ height: 25, width: 25 }}>
|
||||
<Info
|
||||
style={{ background: 'transparent', color: customization.isDarkMode ? 'white' : 'inherit', height: 18, width: 18 }}
|
||||
/>
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
TooltipWithParser.propTypes = {
|
||||
title: PropTypes.node
|
||||
}
|
||||
Reference in New Issue
Block a user