@@ -3,6 +3,30 @@ import { Decorator } from '@storybook/react';
33
44import { DiagramProps , FieldId , NodeField , NodeProps } from '@/types' ;
55
6+ const fieldTypes = [
7+ 'double' ,
8+ 'string' ,
9+ 'object' ,
10+ 'array' ,
11+ 'binData' ,
12+ 'undefined' ,
13+ 'objectId' ,
14+ 'bool' ,
15+ 'date' ,
16+ 'null' ,
17+ 'regex' ,
18+ 'dbPointer' ,
19+ 'javascript' ,
20+ 'symbol' ,
21+ 'javascriptWithScope' ,
22+ 'int' ,
23+ 'timestamp' ,
24+ 'long' ,
25+ 'decimal' ,
26+ 'minKey' ,
27+ 'maxKey' ,
28+ ] ;
29+
630function stringArrayCompare ( a : string [ ] , b : string [ ] ) : boolean {
731 if ( a . length !== b . length ) return false ;
832 if ( a === b ) return true ;
@@ -20,6 +44,7 @@ const newField = (parentFieldPath?: string[]) => {
2044 name,
2145 type : 'string' ,
2246 selectable : true ,
47+ editable : true ,
2348 depth : parentFieldPath ? parentFieldPath . length : 0 ,
2449 id : parentFieldPath ? [ ...parentFieldPath , name ] : [ name ] ,
2550 } ;
@@ -57,6 +82,24 @@ function renameField(existingFields: NodeField[], fieldPath: string[], newName:
5782 return fields ;
5883}
5984
85+ function changeFieldType ( existingFields : NodeField [ ] , fieldPath : string [ ] , newType : string ) {
86+ let currentType ;
87+ const fields = existingFields . map ( field => {
88+ if ( JSON . stringify ( field . id ) !== JSON . stringify ( fieldPath ) ) return field ;
89+ currentType = field . type ;
90+ return { ...field , type : newType } ;
91+ } ) ;
92+ // If the currentType is 'object' or 'array', we should also remove all child fields.
93+ if ( currentType === 'object' || currentType === 'array' ) {
94+ return fields . filter ( field => {
95+ const type = typeof field . id === 'string' ? [ field . id ] : field . id || [ ] ;
96+ // Leading period helps ignore the current field (where type was changed).
97+ return ! type . join ( '.' ) . startsWith ( `${ fieldPath . join ( '.' ) } .` ) ;
98+ } ) ;
99+ }
100+ return fields ;
101+ }
102+
60103let idAccumulator : string [ ] ;
61104let lastDepth = 0 ;
62105// Used to build a string array id based on field depth.
@@ -192,6 +235,19 @@ export const useEditableNodes = (initialNodes: NodeProps[]) => {
192235 ) ;
193236 } , [ ] ) ;
194237
238+ const onFieldTypeChange = useCallback ( ( nodeId : string , fieldPath : string [ ] , newType : string ) => {
239+ setNodes ( nodes =>
240+ nodes . map ( node =>
241+ node . id === nodeId
242+ ? {
243+ ...node ,
244+ fields : changeFieldType ( node . fields , fieldPath , newType ) ,
245+ }
246+ : node ,
247+ ) ,
248+ ) ;
249+ } , [ ] ) ;
250+
195251 const onNodeExpandToggle = useCallback ( ( _evt : ReactMouseEvent , nodeId : string ) => {
196252 setExpanded ( state => {
197253 return {
@@ -222,6 +278,8 @@ export const useEditableNodes = (initialNodes: NodeProps[]) => {
222278 onNodeExpandToggle,
223279 onAddFieldToObjectFieldClick,
224280 onFieldNameChange,
281+ onFieldTypeChange,
282+ fieldTypes,
225283 } ;
226284} ;
227285
0 commit comments