Skip to content

Commit

Permalink
feat(yaml): raw json edit
Browse files Browse the repository at this point in the history
  • Loading branch information
soofstad committed May 22, 2024
1 parent 0d3e305 commit 70753eb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 20 deletions.
100 changes: 84 additions & 16 deletions packages/dm-core-plugins/src/yaml/YamlPlugin.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
import {
ErrorGroup,
IUIPlugin,
Loading,
TGenericObject,
useDocument,
} from '@development-framework/dm-core'
import { Button, Input, Label } from '@equinor/eds-core-react'
import { Button, Input, Label, Switch } from '@equinor/eds-core-react'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js'
import { ChangeEvent, Dispatch, SetStateAction, useState } from 'react'
import { ChangeEvent, Dispatch, SetStateAction, useRef, useState } from 'react'
import { toast } from 'react-toastify'
import styled from 'styled-components'
import YAML from 'yaml'

const StyledPre = styled.pre`
white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
white-space: -pre-wrap; /* Opera */
white-space: -o-pre-wrap; /* Opera */
white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
word-wrap: break-word; /* IE 5.5+ */
background-color: #e0e3e5;
margin: 0;
padding: 1rem;
border-radius: 0.2rem;
border-style: ridge;
border-width: 0.2rem;
border-color: #193549;
width: 100%;
overflow-y: auto;
`

const CodeContainer = styled.pre`
background-color: #193549;
margin: 0;
Expand All @@ -37,13 +55,20 @@ const CodeContainer = styled.pre`

const YamlView = (props: {
document: TGenericObject
updateDocument: (
document: TGenericObject,
notify: boolean,
partialUpdate?: boolean | undefined
) => Promise<void>
depth?: number
_setDepth?: Dispatch<SetStateAction<number>>
}) => {
const { document, depth, _setDepth } = props
const { document, depth, _setDepth, updateDocument } = props
const asYAML: string = YAML.stringify(document)
const asJSON: string = JSON.stringify(document)
const highlighted = hljs.highlight(asYAML, { language: 'yaml' })
const [isEditMode, setIsEditMode] = useState(false)
const textInput = useRef<HTMLInputElement>(null)

const onClick = (text: string) => {
navigator.clipboard.writeText(text)
Expand All @@ -57,6 +82,16 @@ const YamlView = (props: {
}
}

const saveChanges = () => {
try {
const parsed = JSON.parse(textInput.current?.innerText || '{}')
updateDocument(parsed, true)
} catch (e) {
console.log(e)
toast.error(`Invalid JSON - ${e.message}`, { autoClose: false })
}
}

return (
<div className='dm-plugin-padding flex flex-col w-full'>
<div className='flex justify-end items-center my-2 gap-1 w-fit'>
Expand All @@ -76,30 +111,63 @@ const YamlView = (props: {
label='Depth'
/>
</div>
</div>
<CodeContainer>
<code
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(highlighted.value),
}}
<Switch
label='Edit'
checked={isEditMode}
onChange={() => setIsEditMode(!isEditMode)}
/>
</CodeContainer>
</div>
{isEditMode ? (
<>
<div className='flex justify-end p-1'>
<Button onClick={saveChanges}>Save</Button>
</div>
<StyledPre
ref={textInput}
contentEditable={isEditMode}
suppressContentEditableWarning={true}
>
{JSON.stringify(document, null, 2)}
</StyledPre>
<div className='flex justify-end p-1'>
<Button onClick={saveChanges}>Save</Button>
</div>
</>
) : (
<CodeContainer>
<code
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(highlighted.value),
}}
/>
</CodeContainer>
)}
</div>
)
}

export const YamlPlugin = (props: IUIPlugin) => {
const { idReference } = props
const [depth, setDepth] = useState(0)
const { document, isLoading, error } = useDocument<TGenericObject>(
idReference,
depth
)
const { document, isLoading, error, updateDocument } =
useDocument<TGenericObject>(idReference, depth)
if (isLoading) return <Loading />

if (error) throw new Error(JSON.stringify(error, null, 2))
if (error && !error.message) throw new Error(JSON.stringify(error, null, 2))

return (
<YamlView document={document || {}} _setDepth={setDepth} depth={depth} />
<>
{error && (
<div className='p-1'>
<ErrorGroup>{error.message}</ErrorGroup>
</div>
)}
<YamlView
document={document || {}}
_setDepth={setDepth}
depth={depth}
updateDocument={updateDocument}
/>
</>
)
}
5 changes: 1 addition & 4 deletions packages/dm-core/src/hooks/useDocument.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,7 @@ export function useDocument<T>(
})
.catch((error: AxiosError<ErrorResponse>) => {
console.error(error)
if (notify)
toast.error(
'Unable to update document, with message: ' + error.message
)
if (notify) toast.error(error.response?.data.message ?? error.message)
setError(error.response?.data || { message: error.name, data: error })
})
.finally(() => setLoading(false))
Expand Down

0 comments on commit 70753eb

Please sign in to comment.