Newer
Older
import { faChevronDown, faHashtag, faUser } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { insertMarkTags } from '@helper/text'
import { useAppSelector } from '@hooks'
import { JsonViewer } from '@shared/components/json_viewer/view/json_viewer.view'
import DOMPurify from 'dompurify'
import { useCallback, useState } from 'react'
import { Collapse } from 'react-bootstrap'
interface DeviceListCollapsableProps {
search?: string
}
enum Collapsables {
Metadata = 1,
Config = 2,
}
export const DeviceListCollapsable = ({ search }: DeviceListCollapsableProps) => {
const { selected, pnds } = useAppSelector(state => state.device)
const [collapseable, setCollapsable] = useState<Collapsables | undefined>(undefined)
const user = pnds.find(pnd => pnd.id === selected?.device.pid)
const username = user?.name || ''
const deviceId = selected?.device.id || ''
const json = JSON.parse(selected?.mne?.model || '{}')
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const metadataKey = Object.keys(json).at(2) as keyof typeof json
const metadataObject = (json[metadataKey] as JSON) || {}
const configKey = Object.keys(json).at(0) as keyof typeof json
const configObject = (json[configKey] as JSON) || {}
const setCollapsed = useCallback((section: Collapsables) => {
setCollapsable(prev => (prev === section ? undefined : section))
}, [])
const renderDeviceInfo = useCallback(
() => (
<>
<div className="d-flex justify-content-between">
<div>
<FontAwesomeIcon className="me-2" icon={faHashtag} />
UUID:
</div>
<span
dangerouslySetInnerHTML={{
__html: search
? insertMarkTags(deviceId, search)
: DOMPurify.sanitize(deviceId),
}}
/>
</div>
<div className="d-flex justify-content-between">
<div>
<FontAwesomeIcon className="me-2" icon={faUser} />
User:
</div>
<span>{username}</span>
</div>
</>
),
[deviceId, search, username],
)
const renderCollapsableSection = useCallback(
(title: string, section: Collapsables, content: JSON) => (
<>
<div
className={`d-flex justify-content-between clickable ${
section === Collapsables.Config
? 'mt-3'
: 'border-top border-dark mt-3 pt-3'
}`}
aria-expanded={collapseable === section}
onClick={() => setCollapsed(section)}>
<div>
<FontAwesomeIcon
icon={faChevronDown}
rotation={collapseable === section ? undefined : 270}
/>
{title}
</div>
</div>
<Collapse in={collapseable === section}>
<div id={`collapse-${deviceId}-${section}`}>
{JsonViewer({
json: content,
options: {
editable: false,
searchEnabled: false,
},
})}
</div>
</Collapse>
</>
),
[collapseable, deviceId, setCollapsed],
)
return (
<div id={`collapse-${deviceId}`}>
<div className="pb-4 pt-1 d-flex flex-column gap-1">
{renderDeviceInfo()}
{renderCollapsableSection('Metadata', Collapsables.Metadata, metadataObject)}
{renderCollapsableSection('Config', Collapsables.Config, configObject)}
</div>
</div>
)
}