@@ -15,23 +15,19 @@ import '../../css/fontawesome-style.css'
15
15
16
16
var cache = new Map ( ) ;
17
17
18
- function getPropertyFromString ( propertyPath , list ) {
19
- var isOptional = propertyPath . substr ( 0 , 1 ) === '?' ;
20
- var props = propertyPath . substr ( 1 ) . split ( '.' ) ;
21
- var currentNode = list ;
22
- for ( let prop in props ) {
23
- currentNode = currentNode [ props [ prop ] ] ;
24
-
25
- if ( undefined === currentNode ) {
26
- if ( isOptional ) {
27
- break ;
28
- }
18
+ function getPropertyFromString ( name , list ) {
19
+ var isOptional = name . substr ( 0 , 1 ) === '?' ;
20
+ var nameWithoutPrefix = ( isOptional ? name . substr ( 1 ) : name ) ;
29
21
30
- throw 'Attribute "' + props [ prop ] + '" does not exists' ;
22
+ if ( undefined === list [ nameWithoutPrefix ] ) {
23
+ if ( isOptional ) {
24
+ return undefined ;
31
25
}
26
+
27
+ throw 'Attribute "' + props [ prop ] + '" does not exists' ;
32
28
}
33
29
34
- return currentNode ;
30
+ return list [ nameWithoutPrefix ] ;
35
31
}
36
32
37
33
/**
@@ -60,6 +56,8 @@ export class FancytreeAdapter {
60
56
this . tree = null ;
61
57
// the tree element (jQuery)
62
58
this . $tree = null ;
59
+ // a map of path and related keys
60
+ this . pathKeyMap = { } ;
63
61
}
64
62
65
63
bindToElement ( $elem ) {
@@ -74,23 +72,31 @@ export class FancytreeAdapter {
74
72
this . $tree = $elem ;
75
73
var actions = this . actions ;
76
74
var requestNode = this . requestNode ;
77
- var requestNodeToFancytreeNode = function ( requestNode ) {
75
+ var requestNodeToFancytreeNode = ( requestNode ) => {
78
76
if ( requestNode . length === 0 ) {
79
77
return ;
80
78
}
81
79
80
+ if ( '//' == requestNode . path || '/' == requestNode . path ) {
81
+ return requestNodeToFancytreeNode ( requestNode . children [ Object . keys ( requestNode . children ) [ 0 ] ] ) ;
82
+ }
83
+
84
+ var key = "" + jQuery . ui . fancytree . _nextNodeKey ++ ;
82
85
var fancytreeNode = {
83
86
title : requestNode . label ,
84
- key : requestNode . node_name ,
87
+ key : key ,
85
88
children : [ ] ,
86
- actions : { }
89
+ actions : { } ,
90
+ refPath : requestNode . path . replace ( '\/' , '/' ) . replace ( '//' , '/' )
87
91
} ;
88
92
93
+ this . pathKeyMap [ fancytreeNode . refPath ] = key ;
94
+
89
95
for ( let actionName in actions ) {
90
96
var action = actions [ actionName ] ;
91
97
var url = action . url ;
92
98
if ( typeof action . url == 'object' && action . url . hasOwnProperty ( 'data' ) ) {
93
- url = getPropertyFromString ( action . url . data , requestNode ) ;
99
+ url = getPropertyFromString ( action . url . data , requestNode . descriptors ) ;
94
100
}
95
101
96
102
if ( url === undefined ) {
@@ -112,9 +118,13 @@ export class FancytreeAdapter {
112
118
childrenCount ++ ;
113
119
}
114
120
115
- if ( childrenCount ) {
121
+ if ( 0 != childrenCount ) {
116
122
fancytreeNode . folder = true ;
117
123
fancytreeNode . lazy = true ;
124
+
125
+ if ( 0 === fancytreeNode . children . length ) {
126
+ fancytreeNode . children = null ;
127
+ }
118
128
}
119
129
120
130
return fancytreeNode ;
@@ -128,7 +138,7 @@ export class FancytreeAdapter {
128
138
129
139
// lazy load the children when a node is collapsed
130
140
lazyLoad : function ( event , data ) {
131
- var path = data . node . getKeyPath ( ) ;
141
+ var path = data . node . data . refPath ;
132
142
if ( useCache && cache . has ( path ) ) {
133
143
data . result = cache . get ( path ) ;
134
144
} else {
@@ -146,27 +156,33 @@ export class FancytreeAdapter {
146
156
147
157
// transform the JSON response into a data structure that's supported by FancyTree
148
158
postProcess : function ( event , data ) {
149
- if ( null == data . error ) {
150
- var result = requestNodeToFancytreeNode ( data . response ) ;
151
- if ( "" === result . key ) {
152
- result = result . children ;
153
- } else {
154
- result = [ result ] ;
155
- }
156
-
157
- if ( result . length == 1 ) {
158
- result [ 0 ] . expanded = true ;
159
- }
160
-
161
- data . result = result ;
162
- if ( useCache ) {
163
- cache . set ( data . node . getKeyPath ( ) , result ) ;
164
- }
165
- } else {
159
+ if ( data . hasOwnProperty ( 'error' ) && null != data . error ) {
166
160
data . result = {
167
161
// todo: maybe use a more admin friendly error message in prod?
168
162
error : 'An error occured while retrieving the nodes: ' + data . error
169
163
} ;
164
+
165
+ return ;
166
+ }
167
+
168
+ let result = requestNodeToFancytreeNode ( data . response ) ;
169
+ let nodeIsDuplicate = function ( node , parentPath ) {
170
+ return parentPath == node . refPath ;
171
+ } ;
172
+
173
+ if ( nodeIsDuplicate ( result , data . node . data . refPath ) ) {
174
+ result = result . children ;
175
+ } else {
176
+ result = [ result ] ;
177
+ }
178
+
179
+ if ( result . length == 1 && undefined !== result [ 0 ] . folder ) {
180
+ result [ 0 ] . expanded = true ;
181
+ }
182
+
183
+ data . result = result ;
184
+ if ( useCache ) {
185
+ cache . set ( data . node . data . refPath , result ) ;
170
186
}
171
187
} ,
172
188
@@ -186,44 +202,56 @@ export class FancytreeAdapter {
186
202
}
187
203
188
204
this . tree = this . $tree . fancytree ( 'getTree' ) ;
205
+
206
+ this . tree . getNodeByRefPath = function ( refPath ) {
207
+ return this . findFirst ( ( node ) => {
208
+ return node . data . refPath == refPath ;
209
+ } ) ;
210
+ } ;
189
211
}
190
212
191
213
bindToInput ( $input ) {
192
- var root = this . rootNode ;
193
- if ( root . substr ( - 1 ) == '/' ) {
194
- var root = this . rootNode . substr ( 0 , - 1 ) ;
195
- }
196
- var rootParent = root . substr ( 0 , root . lastIndexOf ( '/' ) ) ;
197
-
198
214
// output active node to input field
199
215
this . $tree . fancytree ( 'option' , 'activate' , ( event , data ) => {
200
- $input . val ( rootParent + data . node . getKeyPath ( ) ) ;
216
+ $input . val ( data . node . data . refPath ) ;
201
217
} ) ;
202
218
203
- var showKey = ( key ) => {
204
- this . tree . loadKeyPath ( key , function ( node , status ) {
219
+ var showPath = ( path ) => {
220
+ if ( ! this . pathKeyMap . hasOwnProperty ( path ) ) {
221
+ return ;
222
+ }
223
+
224
+ this . tree . loadKeyPath ( generateKeyPath ( path ) , function ( node , status ) {
205
225
if ( 'ok' == status ) {
206
226
node . setExpanded ( ) ;
207
227
node . setActive ( ) ;
208
228
}
209
229
} ) ;
210
230
} ;
211
- var removeRoot = ( path ) => {
212
- if ( 0 === path . indexOf ( rootParent + '/' ) ) {
213
- return path . substr ( rootParent . length + 1 ) ;
214
- }
231
+ var generateKeyPath = ( path ) => {
232
+ var keyPath = '' ;
233
+ var refPath = '' ;
234
+ var subPaths = path . split ( '/' ) ;
235
+
236
+ subPaths . forEach ( ( subPath ) => {
237
+ if ( subPath == '' || ! this . pathKeyMap . hasOwnProperty ( refPath += '/' + subPath ) ) {
238
+ return ;
239
+ }
240
+
241
+ keyPath += '/' + this . pathKeyMap [ refPath ] ;
242
+ } ) ;
215
243
216
- return path ;
244
+ return keyPath ;
217
245
} ;
218
246
219
247
// use initial input value as active node
220
248
this . $tree . bind ( 'fancytreeinit' , function ( event , data ) {
221
- showKey ( removeRoot ( $input . val ( ) ) ) ;
249
+ showPath ( $input . val ( ) ) ;
222
250
} ) ;
223
251
224
252
// change active node when the value of the input field changed
225
253
$input . on ( 'change' , function ( e ) {
226
- showKey ( removeRoot ( $ ( this ) . val ( ) ) ) ;
254
+ showPath ( $ ( this ) . val ( ) ) ;
227
255
} ) ;
228
256
}
229
257
0 commit comments