Refactored and improved seeds (#8695)
- Added a new Seeder service to help with custom object seeds - Added RichTextFieldInput to edit a rich text field directly on the table, but deactivated it for now.
This commit is contained in:
@ -17,7 +17,6 @@ import { isFieldRelationToOneObject } from '@/object-record/record-field/types/g
|
||||
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
|
||||
|
||||
import { ArrayFieldInput } from '@/object-record/record-field/meta-types/input/components/ArrayFieldInput';
|
||||
import { RichTextFieldInput } from '@/object-record/record-field/meta-types/input/components/RichTextFieldInput';
|
||||
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
|
||||
import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray';
|
||||
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
|
||||
@ -31,7 +30,6 @@ import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/is
|
||||
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
||||
import { isFieldRating } from '@/object-record/record-field/types/guards/isFieldRating';
|
||||
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
|
||||
import { isFieldRichText } from '@/object-record/record-field/types/guards/isFieldRichText';
|
||||
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput';
|
||||
@ -167,8 +165,6 @@ export const FieldInput = ({
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldRichText(fieldDefinition) ? (
|
||||
<RichTextFieldInput />
|
||||
) : isFieldArray(fieldDefinition) ? (
|
||||
<ArrayFieldInput
|
||||
onCancel={onCancel}
|
||||
|
||||
@ -28,6 +28,8 @@ import { RecordForSelect } from '@/object-record/relation-picker/types/RecordFor
|
||||
|
||||
import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray';
|
||||
import { isFieldArrayValue } from '@/object-record/record-field/types/guards/isFieldArrayValue';
|
||||
import { isFieldRichText } from '@/object-record/record-field/types/guards/isFieldRichText';
|
||||
import { isFieldRichTextValue } from '@/object-record/record-field/types/guards/isFieldRichTextValue';
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
|
||||
@ -111,6 +113,10 @@ export const usePersistField = () => {
|
||||
isFieldRawJson(fieldDefinition) &&
|
||||
isFieldRawJsonValue(valueToPersist);
|
||||
|
||||
const fieldIsRichText =
|
||||
isFieldRichText(fieldDefinition) &&
|
||||
isFieldRichTextValue(valueToPersist);
|
||||
|
||||
const fieldIsArray =
|
||||
isFieldArray(fieldDefinition) && isFieldArrayValue(valueToPersist);
|
||||
|
||||
@ -131,7 +137,8 @@ export const usePersistField = () => {
|
||||
fieldIsMultiSelect ||
|
||||
fieldIsAddress ||
|
||||
fieldIsRawJson ||
|
||||
fieldIsArray;
|
||||
fieldIsArray ||
|
||||
fieldIsRichText;
|
||||
|
||||
if (isValuePersistable) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { useTextFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useTextFieldDisplay';
|
||||
import { useRichTextFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useRichTextFieldDisplay';
|
||||
import { getFirstNonEmptyLineOfRichText } from '@/ui/input/editor/utils/getFirstNonEmptyLineOfRichText';
|
||||
import { PartialBlock } from '@blocknote/core';
|
||||
|
||||
export const RichTextFieldDisplay = () => {
|
||||
const { fieldValue } = useTextFieldDisplay();
|
||||
const parsedField =
|
||||
fieldValue === '' ? null : (JSON.parse(fieldValue) as PartialBlock[]);
|
||||
const { fieldValue } = useRichTextFieldDisplay();
|
||||
|
||||
return <>{getFirstNonEmptyLineOfRichText(parsedField)}</>;
|
||||
return (
|
||||
<div>
|
||||
<span>{getFirstNonEmptyLineOfRichText(fieldValue)}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput';
|
||||
import { FieldRichTextValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { usePersistField } from '@/object-record/record-field/hooks/usePersistField';
|
||||
import { isFieldRichText } from '@/object-record/record-field/types/guards/isFieldRichText';
|
||||
import { isFieldRichTextValue } from '@/object-record/record-field/types/guards/isFieldRichTextValue';
|
||||
import { PartialBlock } from '@blocknote/core';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
|
||||
export const useRichTextField = () => {
|
||||
const { recordId, fieldDefinition, hotkeyScope, maxWidth } =
|
||||
useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata(
|
||||
FieldMetadataType.RichText,
|
||||
isFieldRichText,
|
||||
fieldDefinition,
|
||||
);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldRichTextValue>(
|
||||
recordStoreFamilySelector({
|
||||
recordId,
|
||||
fieldName: fieldName,
|
||||
}),
|
||||
);
|
||||
const fieldRichTextValue = isFieldRichTextValue(fieldValue) ? fieldValue : '';
|
||||
|
||||
const { setDraftValue, getDraftValueSelector } =
|
||||
useRecordFieldInput<FieldRichTextValue>(`${recordId}-${fieldName}`);
|
||||
|
||||
const draftValue = useRecoilValue(getDraftValueSelector());
|
||||
|
||||
const draftValueParsed: PartialBlock[] = isNonEmptyString(draftValue)
|
||||
? JSON.parse(draftValue)
|
||||
: draftValue;
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistRichTextField = (nextValue: PartialBlock[]) => {
|
||||
if (!nextValue) {
|
||||
persistField(null);
|
||||
} else {
|
||||
const parsedValueToPersist = JSON.stringify(nextValue);
|
||||
|
||||
persistField(parsedValueToPersist);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
draftValue: draftValueParsed,
|
||||
setDraftValue,
|
||||
maxWidth,
|
||||
fieldDefinition,
|
||||
fieldValue: fieldRichTextValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistRichTextField,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
|
||||
import { FieldRichTextValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { assertFieldMetadata } from '@/object-record/record-field/types/guards/assertFieldMetadata';
|
||||
import { isFieldRichText } from '@/object-record/record-field/types/guards/isFieldRichText';
|
||||
import { PartialBlock } from '@blocknote/core';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { parseJson } from '~/utils/parseJson';
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
|
||||
export const useRichTextFieldDisplay = () => {
|
||||
const { recordId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata(
|
||||
FieldMetadataType.RichText,
|
||||
isFieldRichText,
|
||||
fieldDefinition,
|
||||
);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const fieldValue = useRecordFieldValue<FieldRichTextValue | undefined>(
|
||||
recordId,
|
||||
fieldName,
|
||||
);
|
||||
|
||||
const fieldValueParsed = parseJson<PartialBlock[]>(fieldValue);
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
fieldValue: fieldValueParsed,
|
||||
hotkeyScope,
|
||||
};
|
||||
};
|
||||
@ -1,5 +1,59 @@
|
||||
import { RichTextFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RichTextFieldDisplay';
|
||||
import { BLOCK_SCHEMA } from '@/activities/blocks/constants/Schema';
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { useRichTextField } from '@/object-record/record-field/meta-types/hooks/useRichTextField';
|
||||
import { FieldInputClickOutsideEvent } from '@/object-record/record-field/meta-types/input/components/DateTimeFieldInput';
|
||||
import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents';
|
||||
import { BlockEditor } from '@/ui/input/editor/components/BlockEditor';
|
||||
import { BlockEditorComponentInstanceContext } from '@/ui/input/editor/contexts/BlockEditorCompoponeInstanceContext';
|
||||
import { PartialBlock } from '@blocknote/core';
|
||||
import { useCreateBlockNote } from '@blocknote/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const RichTextFieldInput = () => {
|
||||
return <RichTextFieldDisplay />;
|
||||
import { useContext, useRef } from 'react';
|
||||
|
||||
const StyledRichTextContainer = styled.div`
|
||||
height: 400px;
|
||||
width: 500px;
|
||||
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
export type RichTextFieldInputProps = {
|
||||
onClickOutside?: FieldInputClickOutsideEvent;
|
||||
};
|
||||
|
||||
export const RichTextFieldInput = ({
|
||||
onClickOutside,
|
||||
}: RichTextFieldInputProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { recordId } = useContext(FieldContext);
|
||||
const { draftValue, hotkeyScope, persistRichTextField, fieldDefinition } =
|
||||
useRichTextField();
|
||||
|
||||
const editor = useCreateBlockNote({
|
||||
initialContent: draftValue,
|
||||
domAttributes: { editor: { class: 'editor' } },
|
||||
schema: BLOCK_SCHEMA,
|
||||
});
|
||||
|
||||
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
|
||||
onClickOutside?.(() => persistRichTextField(editor.document), event);
|
||||
};
|
||||
|
||||
useRegisterInputEvents<PartialBlock[]>({
|
||||
inputRef: containerRef,
|
||||
inputValue: draftValue,
|
||||
onClickOutside: handleClickOutside,
|
||||
hotkeyScope,
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledRichTextContainer ref={containerRef}>
|
||||
<BlockEditorComponentInstanceContext.Provider
|
||||
value={{ instanceId: `${recordId}-${fieldDefinition.fieldMetadataId}` }}
|
||||
>
|
||||
<BlockEditor editor={editor} />
|
||||
</BlockEditorComponentInstanceContext.Provider>
|
||||
</StyledRichTextContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -46,6 +46,8 @@ export type FieldDateMetadata = {
|
||||
};
|
||||
};
|
||||
|
||||
export type FieldNumberVariant = 'number' | 'percentage';
|
||||
|
||||
export type FieldNumberMetadata = {
|
||||
objectMetadataNameSingular?: string;
|
||||
fieldName: string;
|
||||
@ -53,7 +55,7 @@ export type FieldNumberMetadata = {
|
||||
isPositive?: boolean;
|
||||
settings?: {
|
||||
decimals?: number;
|
||||
type?: 'percentage' | 'number';
|
||||
type?: FieldNumberVariant;
|
||||
};
|
||||
};
|
||||
|
||||
@ -209,6 +211,7 @@ export type FieldMetadata =
|
||||
| FieldActorMetadata
|
||||
| FieldArrayMetadata
|
||||
| FieldTsVectorMetadata;
|
||||
|
||||
export type FieldTextValue = string;
|
||||
export type FieldUUidValue = string; // TODO: can we replace with a template literal type, or maybe overkill ?
|
||||
export type FieldDateTimeValue = string | null;
|
||||
@ -255,7 +258,7 @@ export type FieldRelationValue<
|
||||
export type Json = ZodHelperLiteral | { [key: string]: Json } | Json[];
|
||||
export type FieldJsonValue = Record<string, Json> | Json[] | null;
|
||||
|
||||
export type FieldRichTextValue = Record<string, Json> | Json[] | null;
|
||||
export type FieldRichTextValue = null | string;
|
||||
|
||||
export type FieldActorValue = {
|
||||
source: string;
|
||||
|
||||
@ -22,6 +22,7 @@ import {
|
||||
FieldRatingMetadata,
|
||||
FieldRawJsonMetadata,
|
||||
FieldRelationMetadata,
|
||||
FieldRichTextMetadata,
|
||||
FieldSelectMetadata,
|
||||
FieldTextMetadata,
|
||||
FieldUuidMetadata,
|
||||
@ -68,7 +69,7 @@ type AssertFieldMetadataFunction = <
|
||||
: E extends 'RAW_JSON'
|
||||
? FieldRawJsonMetadata
|
||||
: E extends 'RICH_TEXT'
|
||||
? FieldTextMetadata
|
||||
? FieldRichTextMetadata
|
||||
: E extends 'ACTOR'
|
||||
? FieldActorMetadata
|
||||
: E extends 'ARRAY'
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
import { FieldRichTextValue } from '../FieldMetadata';
|
||||
|
||||
export const richTextSchema: z.ZodType<FieldRichTextValue> = z.union([
|
||||
z.null(), // Exclude literal values other than null
|
||||
z.string(),
|
||||
]);
|
||||
|
||||
export const isFieldRichTextValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldRichTextValue =>
|
||||
richTextSchema.safeParse(fieldValue).success;
|
||||
@ -5,6 +5,7 @@ import { RecordTableCellWrapper } from '@/object-record/record-table/record-tabl
|
||||
import { RecordTableTd } from '@/object-record/record-table/record-table-cell/components/RecordTableTd';
|
||||
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||
|
||||
export const RecordTableCellsVisible = () => {
|
||||
const { isSelected } = useRecordTableRowContextOrThrow();
|
||||
@ -15,6 +16,10 @@ export const RecordTableCellsVisible = () => {
|
||||
visibleTableColumnsComponentSelector,
|
||||
);
|
||||
|
||||
if (!isNonEmptyArray(visibleTableColumns)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tableColumnsAfterFirst = visibleTableColumns.slice(1);
|
||||
|
||||
return (
|
||||
|
||||
@ -25,7 +25,7 @@ export const SettingsOptionIconCustomizer = ({
|
||||
<StyledIconCustomizer zoom={zoom} rotate={rotate}>
|
||||
<Icon
|
||||
size={theme.icon.size.lg}
|
||||
color={theme.IllustrationIcon.color.grey}
|
||||
color={theme.IllustrationIcon.color.gray}
|
||||
stroke={theme.icon.stroke.md}
|
||||
/>
|
||||
</StyledIconCustomizer>
|
||||
|
||||
@ -125,7 +125,7 @@ export const SETTINGS_NON_COMPOSITE_FIELD_TYPE_CONFIGS: SettingsNonCompositeFiel
|
||||
[FieldMetadataType.RichText]: {
|
||||
label: 'Rich Text',
|
||||
Icon: IllustrationIconSetting,
|
||||
exampleValue: { key: 'value' },
|
||||
exampleValue: "{ key: 'value' }",
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldRichTextValue>,
|
||||
[FieldMetadataType.Array]: {
|
||||
|
||||
@ -19,14 +19,17 @@ interface BlockEditorProps {
|
||||
onBlur?: () => void;
|
||||
onPaste?: (event: ClipboardEvent) => void;
|
||||
onChange?: () => void;
|
||||
readonly?: boolean;
|
||||
}
|
||||
|
||||
const StyledEditor = styled.div`
|
||||
width: 100%;
|
||||
|
||||
& .editor {
|
||||
background: ${({ theme }) => theme.background.primary};
|
||||
font-size: 13px;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
min-height: 400px;
|
||||
}
|
||||
& .editor [class^='_inlineContent']:before {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
@ -124,6 +127,7 @@ export const BlockEditor = ({
|
||||
onBlur,
|
||||
onChange,
|
||||
onPaste,
|
||||
readonly,
|
||||
}: BlockEditorProps) => {
|
||||
const theme = useTheme();
|
||||
const blockNoteTheme = theme.name === 'light' ? 'light' : 'dark';
|
||||
@ -155,6 +159,7 @@ export const BlockEditor = ({
|
||||
theme={blockNoteTheme}
|
||||
slashMenu={false}
|
||||
sideMenu={false}
|
||||
editable={!readonly}
|
||||
>
|
||||
<CustomSideMenu editor={editor} />
|
||||
<SuggestionMenuController
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
import { BLOCK_SCHEMA } from '@/activities/blocks/constants/Schema';
|
||||
import { isSlashMenuOpenComponentState } from '@/ui/input/editor/states/isSlashMenuOpenComponentState';
|
||||
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
|
||||
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export type BlockEditorDropdownFocusEffectProps = {
|
||||
editor: typeof BLOCK_SCHEMA.BlockNoteEditor;
|
||||
};
|
||||
|
||||
export const BlockEditorDropdownFocusEffect = ({
|
||||
editor,
|
||||
}: BlockEditorDropdownFocusEffectProps) => {
|
||||
const isSlashMenuOpenState = useRecoilComponentCallbackStateV2(
|
||||
isSlashMenuOpenComponentState,
|
||||
);
|
||||
|
||||
const { setActiveDropdownFocusIdAndMemorizePrevious } =
|
||||
useSetActiveDropdownFocusIdAndMemorizePrevious();
|
||||
|
||||
const { goBackToPreviousDropdownFocusId } =
|
||||
useGoBackToPreviousDropdownFocusId();
|
||||
|
||||
const updateCallBack = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
(event: any) => {
|
||||
// TODO: This triggers before the onClick event of the slash menu item, so the click outside of the editor dropdown is triggered and everything closes.
|
||||
// This is due to useRecoilCallback being executed before the onClick event of the slash menu item.
|
||||
const eventWantsToOpen = event.show === true;
|
||||
|
||||
const isAlreadyOpen = snapshot
|
||||
.getLoadable(isSlashMenuOpenState)
|
||||
.getValue();
|
||||
|
||||
const shouldOpen = eventWantsToOpen && !isAlreadyOpen;
|
||||
|
||||
if (shouldOpen) {
|
||||
setActiveDropdownFocusIdAndMemorizePrevious('custom-slash-menu');
|
||||
set(isSlashMenuOpenState, true);
|
||||
return;
|
||||
}
|
||||
|
||||
const eventWantsToClose = event.show === false;
|
||||
|
||||
const isAlreadyClosed = !isAlreadyOpen;
|
||||
|
||||
const shouldClose = eventWantsToClose && !isAlreadyClosed;
|
||||
|
||||
if (shouldClose) {
|
||||
goBackToPreviousDropdownFocusId();
|
||||
set(isSlashMenuOpenState, false);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[
|
||||
isSlashMenuOpenState,
|
||||
setActiveDropdownFocusIdAndMemorizePrevious,
|
||||
goBackToPreviousDropdownFocusId,
|
||||
],
|
||||
);
|
||||
|
||||
editor.suggestionMenus.on('update /', updateCallBack);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,4 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const BlockEditorComponentInstanceContext =
|
||||
createComponentInstanceContext();
|
||||
@ -0,0 +1,8 @@
|
||||
import { BlockEditorComponentInstanceContext } from '@/ui/input/editor/contexts/BlockEditorCompoponeInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const isSlashMenuOpenComponentState = createComponentStateV2<boolean>({
|
||||
key: 'isSlashMenuOpenComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: BlockEditorComponentInstanceContext,
|
||||
});
|
||||
@ -11,6 +11,14 @@ export const useSetActiveDropdownFocusIdAndMemorizePrevious = () => {
|
||||
.getLoadable(activeDropdownFocusIdState)
|
||||
.getValue();
|
||||
|
||||
const activeDropdownFocusId = snapshot
|
||||
.getLoadable(activeDropdownFocusIdState)
|
||||
.getValue();
|
||||
|
||||
if (activeDropdownFocusId === dropdownId) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(previousDropdownFocusIdState, focusedDropdownId);
|
||||
set(activeDropdownFocusIdState, dropdownId);
|
||||
},
|
||||
|
||||
@ -50,7 +50,10 @@ export const mapViewFieldsToColumnDefinitions = ({
|
||||
isSortable: correspondingColumnDefinition.isSortable,
|
||||
isFilterable: correspondingColumnDefinition.isFilterable,
|
||||
defaultValue: correspondingColumnDefinition.defaultValue,
|
||||
settings: correspondingColumnDefinition.metadata.settings,
|
||||
settings:
|
||||
'settings' in correspondingColumnDefinition.metadata
|
||||
? correspondingColumnDefinition.metadata.settings
|
||||
: undefined,
|
||||
} as ColumnDefinition<FieldMetadata>;
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
Reference in New Issue
Block a user