import React from 'react'; import BooleanValue from '../components/BooleanValue'; import { Button, message, Typography } from 'antd'; import fileDownload from 'js-file-download'; import { CanonicalObjectSchema } from 'realm'; import { DeserializedRealmData, DeserializedRealmDecimal128, DeserializedRealmObject, DownloadDataFunction } from '../CommonTypes'; import { ClickableText } from '../components/ClickableText'; type TypeDescription = { type: string; objectType?: string; }; export const renderValue = ( value: unknown, property: TypeDescription, schemas: CanonicalObjectSchema[], helpers: { downloadData: DownloadDataFunction; inspectValue?: (value: any) => void; }, inner?: boolean, /** Inspect longer length values */ ): JSX.Element | string | number => { const {downloadData, inspectValue} = helpers; if (value === null) { return inner ? 'null' : null; } if (value === undefined) { return inner ? ( 'undefined' ) : ( undefined ); } let schema; const withCutoff = (displayValue: string, cutoff: number) => { /** If the cell contains a string which is too long cut it off and render it as a clickable text. */ if (!inner && inspectValue && displayValue.length > cutoff) { return ( inspectValue(value)} ellipsis /> ); } return displayValue } switch (property.type) { case 'string': return withCutoff(value as string, 30); case 'double': case 'int': case 'float': return withCutoff(value.toString(), 20); case 'date': case 'objectId': case 'uuid': return value as string; case 'bool': return parseBoolean(value as boolean); case 'list': case 'set': return withCutoff(parseSetOrList(value as Realm.Set, property, schemas, downloadData), 30); case 'data': return parseData(value as DeserializedRealmData, downloadData); case 'dictionary': return withCutoff(parseDictionary(value as Record), 30); case 'decimal128': return withCutoff(parseDecimal128(value as DeserializedRealmDecimal128), 20); case 'object': // eslint-disable-next-line @typescript-eslint/no-shadow schema = schemas.find((schema) => schema.name === property.objectType); if(schema?.embedded) { return `[${schema.name}]` } return parseLinkedObject(schema as Realm.ObjectSchema, value as DeserializedRealmObject); case 'mixed': return withCutoff(parseMixed(value), 30); default: return Unsupported type } }; function parseSetOrList( input: Realm.Set | Realm.List, property: TypeDescription, schemas: Realm.CanonicalObjectSchema[], downloadData: DownloadDataFunction, ): string { const output = input.map((value: unknown) => { // check if the container holds objects if (schemas.some((schema) => schema.name === property.objectType)) { return renderValue( value, { type: 'object', objectType: property.objectType, }, schemas, {downloadData}, true, ); } return renderValue( value, { type: property.objectType as string, }, schemas, {downloadData}, true, ); }); return '[' + output + ']'; } function parseDictionary(input: Record): string { return JSON.stringify(input); } function parseData(input: DeserializedRealmData, downloadData: DownloadDataFunction, ) { if (input.info === undefined) { return data; } const handleDownload = () => { downloadData(input.info[0], input.info[1], input.info[2]).then( (res) => { fileDownload(new Uint8Array(res).buffer, 'data'); }, (reason) => { message.error('downloading failed', reason.message); }, ); }; return ; } function parseBoolean(input: boolean): JSX.Element { const inputAsString = input.toString(); return ; } function parseDecimal128(input: DeserializedRealmDecimal128): string { return input.$numberDecimal ?? input; } function parseLinkedObject( schema: Realm.ObjectSchema, linkedObj: DeserializedRealmObject, ): string { const childSchema: Realm.ObjectSchema | undefined = schema; if (linkedObj.realmObject && childSchema.primaryKey !== undefined && childSchema !== undefined) { return '[' + childSchema.name + ']' + '.' + childSchema.primaryKey + ': ' + linkedObj.realmObject[childSchema.primaryKey]; } else { return '[' + childSchema.name + ']._objectKey: ' + linkedObj.objectKey; } } function parseMixed(input: unknown): string { return JSON.stringify(input); }