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);
}