Skip to content

Instantly share code, notes, and snippets.

@mariusandra
Last active December 4, 2019 20:39
Show Gist options
  • Save mariusandra/0b3e63e70b68f86e5dc5ad714341bed9 to your computer and use it in GitHub Desktop.
Save mariusandra/0b3e63e70b68f86e5dc5ad714341bed9 to your computer and use it in GitHub Desktop.
Kea DevTools (ALPHA)
import React, { useState } from 'react'
import { getContext } from 'kea'
function Connections ({ logic }) {
if (Object.keys(logic.connections).length === 1) {
return null
}
return (
<div style={{ marginTop: 10 }}>
<strong>Connections ({Object.keys(logic.connections).length - 1})</strong>
{Object.keys(logic.connections)
.filter(key => key !== logic.pathString)
.map(key => (
<div key={key}>{key}</div>
))}
</div>
)
}
function Actions ({ logic }) {
if (Object.keys(logic.actions).length === 0) {
return null
}
return (
<div style={{ marginTop: 10 }}>
<strong>Actions ({Object.keys(logic.actions).length})</strong>
{Object.keys(logic.actions).map(key => (
<div key={key}>{key}</div>
))}
</div>
)
}
function Selector ({ logic, selectorKey, store }) {
let response
let error = false
try {
response = logic.selectors[selectorKey](store.getState())
} catch (e) {
error = true
}
return (
<div>
{selectorKey}: {error ? <div style={{ color: 'red' }}>ERROR</div> : <textarea value={JSON.stringify(response)} />}
</div>
)
}
function Selectors ({ logic }) {
if (Object.keys(logic.selectors).length === 0) {
return null
}
const { store } = getContext()
return (
<div style={{ marginTop: 10 }}>
<strong>Selectors ({Object.keys(logic.selectors).length})</strong>
{Object.keys(logic.selectors).map(key => (
<Selector key={key} selectorKey={key} logic={logic} store={store} />
))}
</div>
)
}
function Logic ({ logic }) {
const [isExpanded, setExpanded] = useState(false)
return (
<div
style={{
display: 'inline-block',
background: '#fff',
boxShadow: '0px 0px 2px rgba(0,0,0,0.2)',
margin: 10,
padding: 10,
verticalAlign: 'top'
}}
>
<div style={{ fontWeight: 'bold', marginBottom: 10, cursor: 'pointer' }} onClick={() => setExpanded(!isExpanded)}>
{logic.pathString.split('.').pop()}
</div>
<div>
{isExpanded ? (
<>
<Connections logic={logic} />
<Actions logic={logic} />
<Selectors logic={logic} />
</>
) : (
<span>
{[
Object.keys(logic.connections).length > 1 ? `${Object.keys(logic.connections).length - 1} C` : '',
Object.keys(logic.actions).length > 0 ? `${Object.keys(logic.actions).length} A` : '',
Object.keys(logic.selectors).length > 0 ? `${Object.keys(logic.selectors).length} S` : ''
]
.filter(a => a)
.join(', ')}
</span>
)}
</div>
</div>
)
}
function NestedPaths ({ pathStart, keys, mounted }) {
let keyStarts = {}
let fullKeys = []
keys.forEach(key => {
const keyParts = key.substring(pathStart.length).split('.')
if (keyParts.length > 1) {
keyStarts[keyParts[0]] = true
} else {
fullKeys.push(keyParts[0])
}
})
return (
<div
style={{
background: '#fff',
padding: 10,
margin: 10,
boxShadow: '0px 0px 2px rgba(0,0,0,0.2)',
display: 'inline-block'
}}
>
{pathStart.length > 0 ? <div>{pathStart}</div> : null}
{fullKeys.map(key => (
<Logic key={pathStart + key} logic={mounted[pathStart + key]} />
))}
{Object.keys(keyStarts).map(key => {
const keyStart = pathStart.length === 0 ? `${key}.` : `${pathStart}${key}.`
const innerKeys = keys.filter(k => k.indexOf(keyStart) === 0)
return (
<div key={key}>
<NestedPaths pathStart={keyStart} keys={innerKeys} mounted={mounted} />
</div>
)
})}
</div>
)
}
export default function KeaDevTool () {
const {
mount: { mounted }
} = getContext()
const keys = Object.keys(mounted).sort((a, b) => a.localeCompare(b))
return (
<div style={{ textAlign: 'left' }}>
<NestedPaths pathStart='' mounted={mounted} keys={keys} />
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment