adminjs
adminjs copied to clipboard
Support for arbitrary keys in JSON/JSONB
Describe the problem feature solves Support for JSON/JSONB in version 3.3 seems to only supports explicit columns. While this is useful in some situations, there are JSONBs that contain arbitrary keys and it would be useful to have this data available in admin bro.
Describe the solution you'd like All the JSONB keys and values are shown, nested as deep as the JSONB itself.
For the show
action, the data should be shown like an array, but nested.
The edit
action also seem possible, it could be similar to the array edit
.
Describe alternatives you've considered
I already have a custom component that can show
the JSONB nested, although I have not gotten a custom edit
component working:
Click for Custom JSONB component
import React, { ReactNode } from 'react'
import _ from 'lodash'
import { unflatten } from 'flat'
import { Badge, Section, FormGroup, Label } from '@admin-bro/design-system'
import mapBoolean from 'admin-bro/lib/frontend/components/property-type/boolean/map-value'
class JSONBEntry extends React.PureComponent {
render() {
const { paramObject } = this.props;
if(typeof paramObject === 'boolean'){
return (
<Badge outline size="sm">{mapBoolean(paramObject)}</Badge>
)
}
if(_.isNil(paramObject)){
return <Badge outline size="sm">null</Badge>
}
if(typeof paramObject !== 'object'){
return paramObject;
}
return (
<Section>
{Object.entries(paramObject).map(([key, value]) => (
<FormGroup>
<Label>{key}</Label>
<JSONBEntry paramObject={value}/>
</FormGroup>
))}
</Section>
);
}
}
export default class ShowJSONB extends React.PureComponent {
render() {
const { property, record } = this.props;
const matchingParams = _.chain(record.params)
.omitBy(_.isNil)
.pickBy((value, key) => key.startsWith(property.name))
.value();
const paramObject = unflatten(matchingParams)[property.name];
return (
<FormGroup>
<Label>{property.label}</Label>
<JSONBEntry paramObject={paramObject}/>
</FormGroup>
);
}
}
This implementation isn't super robust, it just does very simple checks on the data types. It is also affected by https://github.com/SoftwareBrothers/admin-bro/issues/525
It would be great if this could be integrated into adminbro itself. Is there a better way to do this? I am just getting familiar with all the changes in verision 3.3
Acceptance criteria All nested JSON/JSONB data is shown without explicitly listing where in the JSONB it is
Nested JSON/JSONB data could be editable as well, similar to arrays.
Are there any news on this feature?
+1
My edit
component based on @bakkerthehacker code:
import * as React from 'react';
import { Box, Label } from '@admin-bro/design-system';
import ReactJson from 'react-json-view';
import * as _ from 'lodash';
import { unflatten } from 'flat';
const EditJSONB = (props: any) => {
const { property, record, onChange } = props;
const matchingParams = _.chain(record.params)
.omitBy(_.isNil)
.pickBy((value, key) => key.startsWith(property.name))
.value();
const object: any = unflatten(matchingParams);
const paramObject = object?.[property.name];
const saveData = (data: any): void => {
onChange(property.name, data);
};
const onEdit = (event: any) => {
const updated_src = event?.updated_src;
saveData(updated_src);
};
const onAdd = (event: any) => {
const updated_src = event?.updated_src;
saveData(updated_src);
};
const onDelete = (event: any) => {
const updated_src = event?.updated_src;
saveData(updated_src);
};
return (
<Box mb="xl">
<Label>{property.label}</Label>
<ReactJson
name={property.name}
collapsed={false}
src={paramObject}
onEdit={onEdit}
onAdd={onAdd}
onDelete={onDelete}
/>
</Box>
);
};
export default EditJSONB;
Is there any plans to implement this? The component that was shared in the original issue is out of date
We don't yet started to work on this issue, however it is on our mind while planning work for the future
@dziraf Hi! Do you think it would be a great opportunity to add these components to https://github.com/SoftwareBrothers/adminjs-custom-components?
Currently we also have a key-value
property type which allows you to add new JSON keys and it's values dynamically. However, it's very simple as it doesn't support types (all values, including numeric, are saved as text), it doesn't allow you to add predefined fields and you cannot nest it's fields.
Potential improvements to which contributions are welcome:
- type conversion on save
- add support for predefined fields
- add support for nesting dynamic JSONs
- theoretically it can be merged with
mixed
type for more flexibility