import React from 'react'
import Radio from '@material-ui/core/Radio'
import {
JobSpecFormats,
JobSpecFormat,
getJobSpecFormat,
isJson,
isToml,
getTaskList,
} from './utils'
import { ApiResponse } from 'utils/json-api-client'
import Button from 'components/Button'
import * as api from 'api'
import { useDispatch } from 'react-redux'
import {
OcrJobSpecRequest,
OcrJobSpec,
JobSpecRequest,
} from 'core/store/models'
import { JobSpec } from 'core/store/presenters'
import BaseLink from 'components/BaseLink'
import ErrorMessage from 'components/Notifications/DefaultError'
import { notifySuccess, notifyError } from 'actionCreators'
import * as storage from 'utils/local-storage'
import Content from 'components/Content'
import {
TextField,
Grid,
Card,
CardContent,
FormControlLabel,
FormControl,
FormLabel,
RadioGroup,
Divider,
CardHeader,
CircularProgress,
Typography,
} from '@material-ui/core'
import {
createStyles,
withStyles,
WithStyles,
Theme,
} from '@material-ui/core/styles'
import { useLocation, useHistory } from 'react-router-dom'
import { TaskSpec } from 'core/store/models'
import TaskListDag from './TaskListDag'
import TaskList from 'components/Jobs/TaskList'
import { Stratify } from './parseDot'
const jobSpecFormatList = [JobSpecFormats.JSON, JobSpecFormats.TOML]
export const SELECTED_FORMAT = 'persistSpec.format'
export const PERSIST_SPEC = 'persistSpec.'
const styles = (theme: Theme) =>
createStyles({
card: {
marginBottom: theme.spacing.unit * 3,
},
loader: {
position: 'absolute',
},
emptyTasks: {
padding: theme.spacing.unit * 3,
},
})
const SuccessNotification = ({ id }: { id: string }) => (
<>
Successfully created job{' '}
{id}
>
)
export function validate({
format,
value,
}: {
format: JobSpecFormats
value: string
}) {
if (value.trim() === '') {
return false
} else if (format === JobSpecFormats.JSON && isJson({ value })) {
return true
} else if (format === JobSpecFormats.TOML && isToml({ value })) {
return true
} else {
return false
}
}
function apiCall({
format,
value,
}: {
format: JobSpecFormats
value: string
}): Promise> {
if (format === JobSpecFormats.JSON) {
const definition: JobSpecRequest = JSON.parse(value)
return api.v2.specs.createJobSpec(definition)
}
if (format === JobSpecFormats.TOML) {
const definition: OcrJobSpecRequest = { toml: value }
return api.v2.ocrSpecs.createJobSpec(definition)
}
return Promise.reject('Invalid format')
}
function getInitialValues({
query,
}: {
query: string
}): { jobSpec: string; format: JobSpecFormats } {
const params = new URLSearchParams(query)
const queryJobSpec = params.get('definition') as string
const queryJobSpecFormat =
getJobSpecFormat({
value: queryJobSpec,
}) || JobSpecFormats.JSON
if (queryJobSpec) {
storage.set(`${PERSIST_SPEC}${queryJobSpecFormat}`, queryJobSpec)
return {
jobSpec: queryJobSpec,
format: queryJobSpecFormat,
}
}
const lastOpenedFormat =
JobSpecFormats[params.get('format')?.toUpperCase() as JobSpecFormat] ||
storage.get(SELECTED_FORMAT) ||
JobSpecFormats.JSON
const lastOpenedJobSpec =
storage.get(`${PERSIST_SPEC}${lastOpenedFormat}`) || ''
return {
jobSpec: lastOpenedJobSpec,
format: lastOpenedFormat,
}
}
export const New = ({
classes,
}: {
classes: WithStyles['classes']
}) => {
const location = useLocation()
const [initialValues] = React.useState(() =>
getInitialValues({
query: location.search,
}),
)
const [format, setFormat] = React.useState(
initialValues.format,
)
const [value, setValue] = React.useState(initialValues.jobSpec)
const [valid, setValid] = React.useState(true)
const [loading, setLoading] = React.useState(false)
const [tasks, setTasks] = React.useState(() =>
getTaskList({ value: initialValues.jobSpec }),
)
const dispatch = useDispatch()
const history = useHistory()
React.useEffect(() => {
const timeout = setTimeout(() => setTasks(getTaskList({ value })), 500)
return () => clearTimeout(timeout)
}, [value, setTasks])
function handleFormat(_event: React.ChangeEvent<{}>, format: string) {
setValue(storage.get(`${PERSIST_SPEC}${format}`) || '')
setFormat(format as JobSpecFormats)
storage.set(SELECTED_FORMAT, format)
setValid(true)
history.replace({
search: `?format=${format}`,
})
}
function handleValue(event: React.ChangeEvent) {
setValue(event.target.value)
storage.set(`${PERSIST_SPEC}${format}`, event.target.value)
setValid(true)
}
async function handleSubmit(event: React.FormEvent) {
event.preventDefault()
const isValid = validate({ format, value })
setValid(isValid)
if (isValid) {
setLoading(true)
apiCall({
format,
value,
})
.then(({ data }) => {
dispatch(notifySuccess(SuccessNotification, data))
})
.catch((error) => {
dispatch(notifyError(ErrorMessage, error))
setValid(false)
})
.finally(() => {
setLoading(false)
})
}
}
return (
{tasks.format === JobSpecFormats.JSON && tasks.list && (
)}
{tasks.format === JobSpecFormats.TOML && tasks.list && (
)}
{!tasks.list && (
Tasks not found
)}
)
}
export default withStyles(styles)(New)