import { message, Table, Typography } from 'antd'; import { Layout, useMemoize, usePlugin } from 'flipper-plugin'; import React from 'react'; import { plugin } from '../index'; import { isPropertyLinked } from '../utils/linkedObject'; import BooleanValue from '../components/BooleanValue'; import { CanonicalObjectSchemaPropertyRow, SortedObjectSchema, } from '../CommonTypes'; const { Text } = Typography; const { Link } = Typography; const createRows = (currentSchema: SortedObjectSchema) => { const { order, properties, primaryKey } = currentSchema; const newRows: CanonicalObjectSchemaPropertyRow[] = []; order.forEach((propName: string, index: number) => { const value = properties[propName]; newRows.push({ ...value, key: index, primaryKey: value.name === primaryKey, }); }); return newRows; }; const renderPropertyLinked = ( objectType: string, schemas: SortedObjectSchema[], onSchemaSelected: (selectedSchema: SortedObjectSchema) => void, ): string | JSX.Element => { const targetSchema = schemas.find((schema) => schema.name === objectType); if (!targetSchema) { return objectType; } return ( onSchemaSelected(targetSchema)}> {targetSchema.name} ); }; const renderFullType = ( property: Realm.CanonicalObjectSchemaProperty, schemas: SortedObjectSchema[], onSchemaSelected: (selectedSchema: SortedObjectSchema) => void, ): string | JSX.Element => { let title; switch (property.type) { case 'list': case 'set': case 'dictionary': case 'object': title = ( <> {renderPropertyLinked( property.objectType as string, schemas, onSchemaSelected, )} ); break; default: title = <>{property.type}; } if (property.optional) { title = <>{title}?; } switch (property.type) { case 'list': title = ( <> {title} {'[]'} ); break; case 'set': title = ( <> {title} {'<>'} ); break; case 'dictionary': title = ( <> {title} {'{}'} ); break; } return title; }; type InputType = { schemas: Array; currentSchema: SortedObjectSchema | null; }; const SchemaVisualizer = ({ schemas, currentSchema }: InputType) => { if (!currentSchema) { return
Please select a schema.
; } if (!schemas || !schemas.length) { return
No schemas found
; } const instance = usePlugin(plugin); const onSchemaSelected = (selectedSchema: SortedObjectSchema) => { if (currentSchema.name === selectedSchema.name) { message.info('You are already viewing this schema'); } instance.setSelectedSchema(selectedSchema); }; function createColumnConfig() { const simpleColumnGenerator = (columnName: string) => ({ key: columnName, title: columnName, dataIndex: columnName, // onFilter: (value: string, record: any) => record[col].startsWith(value), render: (cellContent: string, record: CanonicalObjectSchemaPropertyRow) => renderTableCells(cellContent, typeof cellContent, columnName, record), // filterSearch: true, }); const innerTypeColumns = ['type', 'optional'].map(simpleColumnGenerator); const typeColumnGroup = { title: 'type', children: [ { title: 'full type', dataIndex: 'string format', key: 'string format', render: ( cellContent: string, record: CanonicalObjectSchemaPropertyRow, ) => { return renderFullType(record, schemas, onSchemaSelected); }, }, ...innerTypeColumns, ], }; // TODO: Consider using more descriptive column names const simpleColumns = ['primaryKey', 'name', 'indexed'].map( simpleColumnGenerator, ); return [...simpleColumns, typeColumnGroup]; } const renderTableCells = ( value: unknown, type: string, column: string, record: Realm.CanonicalObjectSchemaProperty, ) => { if (column === 'objectType' && isPropertyLinked(record)) { return renderPropertyLinked( record.objectType as string, schemas, onSchemaSelected, ); } switch (type) { case 'boolean': return ( ); case 'string': return {value as string}; default: return ; } }; const columns = [ 'primaryKey', 'name', 'type', // 'mapTo', 'indexed', 'optional', 'objectType', ]; const columnObjs = useMemoize((_) => createColumnConfig(), [columns]); const rows = createRows(currentSchema); return ( ); }; export default React.memo(SchemaVisualizer);