1+ import React from 'react' ;
2+ import PropTypes from 'prop-types' ;
3+ import { List , fromJS } from 'immutable' ;
4+
5+ import Vfield from '../../Vfield' ;
6+
7+ import VpropertyAdd from '../VpropertyAdd' ;
8+
9+ import styleSpec from '../../../vendor/style-spec/style-spec' ;
10+
11+ export default class VpropertyMetadata extends React . Component {
12+
13+ static propTypes = {
14+ property : PropTypes . shape ( {
15+ type : PropTypes . string . isRequired ,
16+ name : PropTypes . string . isRequired , // string of position . separated
17+ value : PropTypes . object ,
18+ placeholder : PropTypes . string ,
19+ error : PropTypes . oneOfType ( [
20+ PropTypes . string ,
21+ PropTypes . object
22+ ] ) ,
23+ specType : PropTypes . string
24+ } ) ,
25+ focus : PropTypes . string ,
26+ handle : PropTypes . object
27+ }
28+
29+ constructor ( props ) {
30+ super ( props ) ;
31+ const { handle, property} = this . props ;
32+
33+ //console.log('handle:',handle);
34+
35+ // convert value into array of arrays [[k,v],[k,v]]
36+ let valAry = [ ] ;
37+ property . value . keySeq ( ) . toArray ( ) . forEach ( ( key ) => {
38+ let val = property . value . get ( key ) ;
39+ if ( val === true ) val = 'true' ;
40+ else if ( val === false ) val = 'false' ;
41+ valAry . push ( [ key , val ] ) ;
42+ } ) ;
43+
44+ this . state = {
45+ valAry :fromJS ( valAry )
46+ } ;
47+
48+ this . handle = {
49+ add :( ) => {
50+ this . setState ( { valAry :this . state . valAry . push ( List ( [ ] ) ) } ) ;
51+ }
52+ } ;
53+
54+ for ( let i in this . handle ) {
55+ this . handle [ i ] = this . handle [ i ] . bind ( this ) ;
56+ }
57+
58+ this . fieldHandle = {
59+ ...handle ,
60+ backout :( f ) => {
61+ let setIn = f . name . split ( '.' ) . map ( ( v ) => {
62+ return Number ( v ) ;
63+ } ) ;
64+ if ( setIn [ 1 ] === 1 ) { // value backed out of
65+ const keyName = [ setIn [ 0 ] , 0 ] . join ( '.' ) ;
66+ handle . focus ( keyName ) ;
67+ return ;
68+ }
69+ if ( setIn [ 1 ] === 0 ) { // key backed out of
70+ const newValAry = this . state . valAry . remove ( setIn [ 0 ] ) ;
71+ this . setState ( { valAry :newValAry } ) ;
72+
73+ this . fieldHandle . commit ( newValAry ) ;
74+
75+ if ( setIn [ 0 ] > 0 ) {
76+ const prevName = [ setIn [ 0 ] - 1 , 1 ] . join ( '.' ) ;
77+ handle . focus ( prevName ) ;
78+ }
79+ }
80+ } ,
81+ change :( f ) => {
82+ // split name
83+ let setIn = f . name . split ( '.' ) . map ( ( v ) => {
84+ return Number ( v ) ;
85+ } ) ;
86+ const newValAry = this . state . valAry . setIn ( setIn , f . value ) ;
87+
88+ this . setState ( { valAry :newValAry } ) ;
89+
90+ this . fieldHandle . commit ( newValAry ) ;
91+ } ,
92+ commit :( newValAry ) => {
93+ let value = { } ;
94+
95+ newValAry . keySeq ( ) . toArray ( ) . forEach ( ( key ) => {
96+ let val = newValAry . getIn ( [ key , 1 ] ) ;
97+ if ( val === undefined ) val = '' ;
98+ else if ( val === 'true' ) val = true ;
99+ else if ( val === 'false' ) val = false ;
100+ else if ( val . match && val . match ( / ^ [ 0 - 9 ] + $ / ) ) val = Number ( val ) ;
101+ value [ newValAry . getIn ( [ key , 0 ] ) ] = val ;
102+ } ) ;
103+
104+ handle . change ( {
105+ name :property . name ,
106+ value :fromJS ( value )
107+ } ) ;
108+ }
109+ } ;
110+
111+ for ( let i in this . fieldHandle ) {
112+ this . fieldHandle [ i ] = this . fieldHandle [ i ] . bind ( this ) ;
113+ }
114+
115+ }
116+
117+ render ( ) {
118+ const { property, focus} = this . props ;
119+
120+ let rows = [ ] , ind = 0 ;
121+ this . state . valAry . keySeq ( ) . toArray ( ) . forEach ( ( key ) => {
122+
123+ const keyName = key + '.0' ;
124+ const valueName = key + '.1' ;
125+
126+ const error = ( property . error && property . error . get ) ? property . error . get ( key ) : null ;
127+ //console.log('function error:',error);
128+
129+ const keyFocus = ( keyName === focus ) ? true : false ;
130+ const valueFocus = ( valueName === focus ) ? true : false ;
131+
132+ let value = this . state . valAry . getIn ( [ key , 1 ] ) ;
133+ if ( value === true ) value = 'true' ;
134+ else if ( value === false ) value = 'false' ;
135+
136+ rows . push (
137+ < div key = { key } className = "row" >
138+ < div className = "col-sm-6 pr-1" >
139+ < Vfield key = { keyName } field = { {
140+ type :'string' ,
141+ name :keyName ,
142+ value :this . state . valAry . getIn ( [ key , 0 ] ) ,
143+ controlled :false ,
144+ autoFocus :keyFocus
145+ } } handle = { this . fieldHandle } />
146+ </ div >
147+ < div className = "col-sm-6 pl-0" >
148+ < Vfield key = { valueName } field = { {
149+ type :'string' ,
150+ name :valueName ,
151+ value :value ,
152+ controlled :false ,
153+ autoFocus :valueFocus
154+ } } handle = { this . fieldHandle } />
155+ </ div >
156+ </ div >
157+ ) ;
158+
159+ ind ++ ;
160+ } ) ;
161+
162+ return < div className = "form-group mb-0" >
163+ < div className = "mt-2 p-2 func-border position-relative" >
164+ { rows }
165+
166+ < div className = "mt-2" >
167+ < div onClick = { this . handle . add } className = "btn btn-xs btn-light" >
168+ < i className = "material-icons md-14" > add</ i >
169+ </ div >
170+ </ div >
171+ </ div >
172+ </ div >
173+ }
174+ } ;
0 commit comments