Add CodeDiffViewer and DiffLabel components for enhanced code comparison
- Introduced CodeDiffViewer component utilizing @codemirror/merge for visual code diffs. - Added DiffLabel component to display code change statistics and trigger the CodeDiffViewer modal. - Updated PropertyChanges component to integrate DiffLabel for code property changes. - Enhanced styling for code diff display with new CSS classes. - Updated package.json and lock files to include @codemirror/merge dependency.
This commit is contained in:
parent
d8c13426d1
commit
ee038d08c3
@ -1291,3 +1291,20 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-diff-viewer {
|
||||||
|
height: 70vh;
|
||||||
|
border: 1px solid #85858541;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-diff-viewer .cm-mergeView {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-label-square {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
background-color: #85858541;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|||||||
3
bun.lock
3
bun.lock
@ -23,6 +23,7 @@
|
|||||||
"@codemirror/lang-xml": "^6.1.0",
|
"@codemirror/lang-xml": "^6.1.0",
|
||||||
"@codemirror/lang-yaml": "^6.1.2",
|
"@codemirror/lang-yaml": "^6.1.2",
|
||||||
"@codemirror/language": "6.12.1",
|
"@codemirror/language": "6.12.1",
|
||||||
|
"@codemirror/merge": "^6.12.2",
|
||||||
"@codemirror/state": "6.7.1",
|
"@codemirror/state": "6.7.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "6.39.12",
|
"@codemirror/view": "6.39.12",
|
||||||
@ -238,6 +239,8 @@
|
|||||||
|
|
||||||
"@codemirror/lint": ["@codemirror/lint@6.9.3", "", { "dependencies": { "@codemirror/state": "6.7.1", "@codemirror/view": "6.39.12", "crelt": "1.0.6" } }, "sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw=="],
|
"@codemirror/lint": ["@codemirror/lint@6.9.3", "", { "dependencies": { "@codemirror/state": "6.7.1", "@codemirror/view": "6.39.12", "crelt": "1.0.6" } }, "sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw=="],
|
||||||
|
|
||||||
|
"@codemirror/merge": ["@codemirror/merge@6.12.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/highlight": "^1.0.0", "style-mod": "^4.1.0" } }, "sha512-V8JvyAPjHbPupqP7BeMcsdsYCbyPij74jxIbaIJDORI+VZzW44zFmon8bF+oxGWvOKhcRmkiUMXd8MxHr3YA2w=="],
|
||||||
|
|
||||||
"@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "6.7.1", "@codemirror/view": "6.39.12", "crelt": "1.0.7" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="],
|
"@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "6.7.1", "@codemirror/view": "6.39.12", "crelt": "1.0.7" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="],
|
||||||
|
|
||||||
"@codemirror/state": ["@codemirror/state@6.7.1", "", { "dependencies": { "@marijn/find-cluster-break": "1.0.3" } }, "sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A=="],
|
"@codemirror/state": ["@codemirror/state@6.7.1", "", { "dependencies": { "@marijn/find-cluster-break": "1.0.3" } }, "sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A=="],
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"@codemirror/lang-xml": "^6.1.0",
|
"@codemirror/lang-xml": "^6.1.0",
|
||||||
"@codemirror/lang-yaml": "^6.1.2",
|
"@codemirror/lang-yaml": "^6.1.2",
|
||||||
"@codemirror/language": "6.12.1",
|
"@codemirror/language": "6.12.1",
|
||||||
|
"@codemirror/merge": "^6.12.2",
|
||||||
"@codemirror/state": "6.7.1",
|
"@codemirror/state": "6.7.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "6.39.12",
|
"@codemirror/view": "6.39.12",
|
||||||
|
|||||||
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
@ -70,6 +70,9 @@ importers:
|
|||||||
'@codemirror/language':
|
'@codemirror/language':
|
||||||
specifier: 6.12.1
|
specifier: 6.12.1
|
||||||
version: 6.12.1
|
version: 6.12.1
|
||||||
|
'@codemirror/merge':
|
||||||
|
specifier: ^6.12.2
|
||||||
|
version: 6.12.2
|
||||||
'@codemirror/state':
|
'@codemirror/state':
|
||||||
specifier: 6.7.1
|
specifier: 6.7.1
|
||||||
version: 6.7.1
|
version: 6.7.1
|
||||||
@ -611,6 +614,9 @@ packages:
|
|||||||
'@codemirror/lint@6.9.3':
|
'@codemirror/lint@6.9.3':
|
||||||
resolution: {integrity: sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw==}
|
resolution: {integrity: sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw==}
|
||||||
|
|
||||||
|
'@codemirror/merge@6.12.2':
|
||||||
|
resolution: {integrity: sha512-V8JvyAPjHbPupqP7BeMcsdsYCbyPij74jxIbaIJDORI+VZzW44zFmon8bF+oxGWvOKhcRmkiUMXd8MxHr3YA2w==}
|
||||||
|
|
||||||
'@codemirror/search@6.6.0':
|
'@codemirror/search@6.6.0':
|
||||||
resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
|
resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
|
||||||
|
|
||||||
@ -7047,6 +7053,14 @@ snapshots:
|
|||||||
'@codemirror/view': 6.39.12
|
'@codemirror/view': 6.39.12
|
||||||
crelt: 1.0.6
|
crelt: 1.0.6
|
||||||
|
|
||||||
|
'@codemirror/merge@6.12.2':
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.12.1
|
||||||
|
'@codemirror/state': 6.7.1
|
||||||
|
'@codemirror/view': 6.39.12
|
||||||
|
'@lezer/highlight': 1.2.3
|
||||||
|
style-mod: 4.1.3
|
||||||
|
|
||||||
'@codemirror/search@6.6.0':
|
'@codemirror/search@6.6.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/state': 6.7.1
|
'@codemirror/state': 6.7.1
|
||||||
|
|||||||
@ -22,6 +22,64 @@ import { Button, Modal, Typography } from 'antd'
|
|||||||
|
|
||||||
const { Link } = Typography
|
const { Link } = Typography
|
||||||
|
|
||||||
|
export function toEditorCode(code, language = 'javascript') {
|
||||||
|
if (code == null) return ''
|
||||||
|
if (typeof code === 'object' && language === 'json') {
|
||||||
|
return JSON.stringify(code, null, 2)
|
||||||
|
}
|
||||||
|
return String(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeLanguageExtension(
|
||||||
|
language = 'javascript',
|
||||||
|
autoCompleteObject = null
|
||||||
|
) {
|
||||||
|
const lang = Array.isArray(language) ? language[0] : language
|
||||||
|
|
||||||
|
switch (String(lang || 'javascript').toLowerCase()) {
|
||||||
|
case 'javascript':
|
||||||
|
case 'js':
|
||||||
|
return javascript()
|
||||||
|
case 'python':
|
||||||
|
case 'py':
|
||||||
|
return python()
|
||||||
|
case 'json':
|
||||||
|
return json()
|
||||||
|
case 'xml':
|
||||||
|
return xml()
|
||||||
|
case 'fctemplatelang':
|
||||||
|
case 'ejs':
|
||||||
|
return fcTemplateLang({ autoCompleteObject })
|
||||||
|
case 'html':
|
||||||
|
return html()
|
||||||
|
case 'css':
|
||||||
|
return css()
|
||||||
|
case 'markdown':
|
||||||
|
case 'md':
|
||||||
|
return markdown()
|
||||||
|
case 'sql':
|
||||||
|
return sql()
|
||||||
|
case 'java':
|
||||||
|
return java()
|
||||||
|
case 'cpp':
|
||||||
|
case 'c++':
|
||||||
|
case 'c':
|
||||||
|
return cpp()
|
||||||
|
case 'rust':
|
||||||
|
case 'rs':
|
||||||
|
return rust()
|
||||||
|
case 'go':
|
||||||
|
return go()
|
||||||
|
case 'php':
|
||||||
|
return php()
|
||||||
|
case 'yaml':
|
||||||
|
case 'yml':
|
||||||
|
return yaml()
|
||||||
|
default:
|
||||||
|
return javascript()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function CodeBlockEditor({
|
export default function CodeBlockEditor({
|
||||||
code = '',
|
code = '',
|
||||||
language = 'javascript',
|
language = 'javascript',
|
||||||
@ -37,57 +95,12 @@ export default function CodeBlockEditor({
|
|||||||
}) {
|
}) {
|
||||||
const { isDarkMode } = useThemeContext()
|
const { isDarkMode } = useThemeContext()
|
||||||
const [codeMirrorOpen, setCodeMirrorOpen] = useState(false)
|
const [codeMirrorOpen, setCodeMirrorOpen] = useState(false)
|
||||||
var editorCode = code
|
const editorCode = toEditorCode(code, language)
|
||||||
|
|
||||||
if (typeof code == 'object' && language == 'json') {
|
const languageExtension = useMemo(
|
||||||
editorCode = JSON.stringify(code, null, 2)
|
() => getCodeLanguageExtension(language, autoCompleteObject),
|
||||||
}
|
[language, autoCompleteObject]
|
||||||
|
)
|
||||||
// Map language to CodeMirror extension
|
|
||||||
const languageExtension = useMemo(() => {
|
|
||||||
switch (language.toLowerCase()) {
|
|
||||||
case 'javascript':
|
|
||||||
case 'js':
|
|
||||||
return javascript()
|
|
||||||
case 'python':
|
|
||||||
case 'py':
|
|
||||||
return python()
|
|
||||||
case 'json':
|
|
||||||
return json()
|
|
||||||
case 'xml':
|
|
||||||
return xml()
|
|
||||||
case 'fctemplatelang':
|
|
||||||
case 'ejs':
|
|
||||||
return fcTemplateLang({ autoCompleteObject })
|
|
||||||
case 'html':
|
|
||||||
return html()
|
|
||||||
case 'css':
|
|
||||||
return css()
|
|
||||||
case 'markdown':
|
|
||||||
case 'md':
|
|
||||||
return markdown()
|
|
||||||
case 'sql':
|
|
||||||
return sql()
|
|
||||||
case 'java':
|
|
||||||
return java()
|
|
||||||
case 'cpp':
|
|
||||||
case 'c++':
|
|
||||||
case 'c':
|
|
||||||
return cpp()
|
|
||||||
case 'rust':
|
|
||||||
case 'rs':
|
|
||||||
return rust()
|
|
||||||
case 'go':
|
|
||||||
return go()
|
|
||||||
case 'php':
|
|
||||||
return php()
|
|
||||||
case 'yaml':
|
|
||||||
case 'yml':
|
|
||||||
return yaml()
|
|
||||||
default:
|
|
||||||
return javascript() // Default fallback
|
|
||||||
}
|
|
||||||
}, [language, autoCompleteObject])
|
|
||||||
|
|
||||||
const handleOnChange = (value) => {
|
const handleOnChange = (value) => {
|
||||||
if (typeof code == 'object' && language == 'json') {
|
if (typeof code == 'object' && language == 'json') {
|
||||||
|
|||||||
85
src/components/Dashboard/common/CodeDiffViewer.jsx
Normal file
85
src/components/Dashboard/common/CodeDiffViewer.jsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { useLayoutEffect, useMemo, useRef } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { MergeView } from '@codemirror/merge'
|
||||||
|
import { EditorState } from '@codemirror/state'
|
||||||
|
import { EditorView } from '@codemirror/view'
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
import { basicSetup } from 'codemirror'
|
||||||
|
import { useThemeContext } from '../context/ThemeContext'
|
||||||
|
import {
|
||||||
|
getCodeLanguageExtension,
|
||||||
|
toEditorCode
|
||||||
|
} from './CodeBlockEditor'
|
||||||
|
|
||||||
|
export default function CodeDiffViewer({
|
||||||
|
oldCode = '',
|
||||||
|
newCode = '',
|
||||||
|
language = 'javascript'
|
||||||
|
}) {
|
||||||
|
const { isDarkMode } = useThemeContext()
|
||||||
|
const parentRef = useRef(null)
|
||||||
|
const oldDoc = toEditorCode(oldCode, language)
|
||||||
|
const newDoc = toEditorCode(newCode, language)
|
||||||
|
|
||||||
|
const languageExtension = useMemo(
|
||||||
|
() => getCodeLanguageExtension(language),
|
||||||
|
[language]
|
||||||
|
)
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!parentRef.current) return
|
||||||
|
|
||||||
|
const editorTheme = EditorView.theme({
|
||||||
|
'&': {
|
||||||
|
fontSize: '14px',
|
||||||
|
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const sharedExtensions = [
|
||||||
|
basicSetup,
|
||||||
|
languageExtension,
|
||||||
|
editorTheme,
|
||||||
|
EditorView.editable.of(false),
|
||||||
|
EditorState.readOnly.of(true),
|
||||||
|
...(isDarkMode ? [oneDark] : [])
|
||||||
|
]
|
||||||
|
|
||||||
|
const view = new MergeView({
|
||||||
|
a: {
|
||||||
|
doc: oldDoc,
|
||||||
|
extensions: sharedExtensions
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
doc: newDoc,
|
||||||
|
extensions: sharedExtensions
|
||||||
|
},
|
||||||
|
parent: parentRef.current,
|
||||||
|
highlightChanges: true,
|
||||||
|
gutter: true,
|
||||||
|
collapseUnchanged: { margin: 3, minSize: 6 }
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
view.destroy()
|
||||||
|
}
|
||||||
|
}, [oldDoc, newDoc, languageExtension, isDarkMode])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={parentRef}
|
||||||
|
className={
|
||||||
|
isDarkMode ? 'code-diff-viewer is-dark' : 'code-diff-viewer'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeDiffViewer.propTypes = {
|
||||||
|
oldCode: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
|
newCode: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
|
language: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.arrayOf(PropTypes.string)
|
||||||
|
])
|
||||||
|
}
|
||||||
116
src/components/Dashboard/common/DiffLabel.jsx
Normal file
116
src/components/Dashboard/common/DiffLabel.jsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { useMemo, useState } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { Button, Modal, Typography, theme, Flex } from 'antd'
|
||||||
|
import { presentableDiff } from '@codemirror/merge'
|
||||||
|
import CodeDiffViewer from './CodeDiffViewer'
|
||||||
|
import { toEditorCode } from './CodeBlockEditor'
|
||||||
|
|
||||||
|
const { Link, Text } = Typography
|
||||||
|
|
||||||
|
const SQUARE_COUNT = 10
|
||||||
|
|
||||||
|
const countLines = (str) => {
|
||||||
|
if (!str) return 0
|
||||||
|
const parts = str.split('\n')
|
||||||
|
if (parts[parts.length - 1] === '') parts.pop()
|
||||||
|
return Math.max(parts.length, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeDiffStats(oldCode, newCode, language = 'javascript') {
|
||||||
|
const oldText = toEditorCode(oldCode, language)
|
||||||
|
const newText = toEditorCode(newCode, language)
|
||||||
|
const changes = presentableDiff(oldText, newText)
|
||||||
|
let additions = 0
|
||||||
|
let deletions = 0
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
const deleted = oldText.slice(change.fromA, change.toA)
|
||||||
|
const added = newText.slice(change.fromB, change.toB)
|
||||||
|
if (deleted) deletions += countLines(deleted)
|
||||||
|
if (added) additions += countLines(added)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { additions, deletions }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DiffLabel({
|
||||||
|
oldCode = '',
|
||||||
|
newCode = '',
|
||||||
|
language = 'javascript'
|
||||||
|
}) {
|
||||||
|
const { token } = theme.useToken()
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const [viewerReady, setViewerReady] = useState(false)
|
||||||
|
const { additions, deletions } = useMemo(
|
||||||
|
() => getCodeDiffStats(oldCode, newCode, language),
|
||||||
|
[oldCode, newCode, language]
|
||||||
|
)
|
||||||
|
|
||||||
|
const greenCount = Math.round(
|
||||||
|
(additions / (additions + deletions)) * SQUARE_COUNT
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Link
|
||||||
|
className='diff-label'
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex gap='small' align='center' style={{ marginTop: 0.5 }}>
|
||||||
|
<Text style={{ color: token.colorSuccess }}>+{additions}</Text>
|
||||||
|
<Flex gap='4px' align='center' style={{ marginBottom: 2 }}>
|
||||||
|
{Array.from({ length: SQUARE_COUNT }).map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className='diff-label-square'
|
||||||
|
style={{
|
||||||
|
backgroundColor:
|
||||||
|
i < greenCount ? token.colorSuccess : token.colorError
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
<Text style={{ color: token.colorError }}>-{deletions}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Link>
|
||||||
|
<Modal
|
||||||
|
closeIcon={false}
|
||||||
|
open={open}
|
||||||
|
width='90%'
|
||||||
|
destroyOnClose
|
||||||
|
afterOpenChange={setViewerReady}
|
||||||
|
onCancel={() => {
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
footer={
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{viewerReady ? (
|
||||||
|
<CodeDiffViewer
|
||||||
|
oldCode={oldCode}
|
||||||
|
newCode={newCode}
|
||||||
|
language={language}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DiffLabel.propTypes = {
|
||||||
|
oldCode: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
|
newCode: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
|
language: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.arrayOf(PropTypes.string)
|
||||||
|
])
|
||||||
|
}
|
||||||
@ -1,7 +1,11 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Descriptions, Typography, Flex } from 'antd'
|
import { Descriptions, Typography, Flex } from 'antd'
|
||||||
import { getModelProperty } from '../../../database/ObjectModels'
|
import {
|
||||||
|
getModelProperty,
|
||||||
|
getPropertyValue
|
||||||
|
} from '../../../database/ObjectModels'
|
||||||
import ObjectProperty from './ObjectProperty'
|
import ObjectProperty from './ObjectProperty'
|
||||||
|
import DiffLabel from './DiffLabel'
|
||||||
import ArrowRightIcon from '../../Icons/ArrowRightIcon'
|
import ArrowRightIcon from '../../Icons/ArrowRightIcon'
|
||||||
|
|
||||||
const { Text } = Typography
|
const { Text } = Typography
|
||||||
@ -51,6 +55,17 @@ const PropertyChanges = ({ type, value }) => {
|
|||||||
if (!changeProperty) {
|
if (!changeProperty) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldValue = getPropertyValue(value?.old, key)
|
||||||
|
const newValue = getPropertyValue(value?.new, key)
|
||||||
|
const isCodeKey = key === 'code' || changeProperty.type === 'codeBlock'
|
||||||
|
const isCodeEdit =
|
||||||
|
isCodeKey &&
|
||||||
|
oldValue != null &&
|
||||||
|
oldValue !== '' &&
|
||||||
|
newValue != null &&
|
||||||
|
newValue !== ''
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Descriptions.Item key={key} label={changeProperty.label}>
|
<Descriptions.Item key={key} label={changeProperty.label}>
|
||||||
<Flex
|
<Flex
|
||||||
@ -58,31 +73,41 @@ const PropertyChanges = ({ type, value }) => {
|
|||||||
style={{ minWidth: 0, width: '100%' }}
|
style={{ minWidth: 0, width: '100%' }}
|
||||||
className='property-changes'
|
className='property-changes'
|
||||||
>
|
>
|
||||||
{value?.old ? (
|
{isCodeEdit ? (
|
||||||
<ObjectProperty
|
<DiffLabel
|
||||||
{...changeProperty}
|
oldCode={oldValue}
|
||||||
longId={false}
|
newCode={newValue}
|
||||||
minimal={true}
|
language={changeProperty.language}
|
||||||
showPreview={false}
|
|
||||||
objectData={value?.old}
|
|
||||||
maxWidth='200px'
|
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : (
|
||||||
{value?.old && value?.new ? (
|
<>
|
||||||
<Text type='secondary'>
|
{value?.old ? (
|
||||||
<ArrowRightIcon />
|
<ObjectProperty
|
||||||
</Text>
|
{...changeProperty}
|
||||||
) : null}
|
longId={false}
|
||||||
{value?.new ? (
|
minimal={true}
|
||||||
<ObjectProperty
|
showPreview={false}
|
||||||
{...changeProperty}
|
objectData={value?.old}
|
||||||
longId={false}
|
maxWidth='200px'
|
||||||
minimal={true}
|
/>
|
||||||
showPreview={false}
|
) : null}
|
||||||
objectData={value?.new}
|
{value?.old && value?.new ? (
|
||||||
maxWidth='200px'
|
<Text type='secondary'>
|
||||||
/>
|
<ArrowRightIcon />
|
||||||
) : null}
|
</Text>
|
||||||
|
) : null}
|
||||||
|
{value?.new ? (
|
||||||
|
<ObjectProperty
|
||||||
|
{...changeProperty}
|
||||||
|
longId={false}
|
||||||
|
minimal={true}
|
||||||
|
showPreview={false}
|
||||||
|
objectData={value?.new}
|
||||||
|
maxWidth='200px'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user