@@ -15,6 +15,9 @@ import * as kGlobals from "./globals.js";
15
15
import * as network from "./network.js" ;
16
16
import * as HTX from "./hiv_tx_network.js" ;
17
17
import * as columnDefinitions from "./column_definitions.js" ;
18
+ import "jQuery-QueryBuilder" ;
19
+ import "jQuery-QueryBuilder/dist/css/query-builder.default.css" ;
20
+ import "bootstrap-datepicker" ;
18
21
19
22
var hivtrace_cluster_network_graph = function (
20
23
json ,
@@ -73,7 +76,19 @@ var hivtrace_cluster_network_graph = function (
73
76
/** SLKP 20190902: somehow some of our networks have malformed edges! This will remove them */
74
77
json . Edges = _ . filter ( json . Edges , ( e ) => "source" in e && "target" in e ) ;
75
78
76
- var self = new HTX . HIVTxNetwork ( json , button_bar_ui ) ;
79
+ /** Not primary networks are individual cluster/subcluster views.
80
+ They don't interfere with the primary network object, and UI elements
81
+
82
+ */
83
+
84
+ const izPrimaryGraph = network . check_network_option (
85
+ options ,
86
+ "secondary" ,
87
+ true ,
88
+ false
89
+ ) ;
90
+
91
+ var self = new HTX . HIVTxNetwork ( json , button_bar_ui , null , ! izPrimaryGraph ) ;
77
92
78
93
self . process_multiple_sequences ( ) ;
79
94
@@ -186,18 +201,6 @@ var hivtrace_cluster_network_graph = function (
186
201
null
187
202
) ;
188
203
189
- /** Not primary networks are individual cluster/subcluster views.
190
- They don't interfere with the primary network object, and UI elements
191
-
192
- */
193
-
194
- self . isPrimaryGraph = network . check_network_option (
195
- options ,
196
- "secondary" ,
197
- true ,
198
- false
199
- ) ;
200
-
201
204
self . parent_graph_object = network . check_network_option (
202
205
options ,
203
206
"parent_graph" ,
@@ -1894,7 +1897,6 @@ var hivtrace_cluster_network_graph = function (
1894
1897
} else {
1895
1898
cluster_nodes = self . _extract_nodes_by_id ( cluster_id ) ;
1896
1899
}
1897
-
1898
1900
d3 . select (
1899
1901
self . get_ui_element_selector_by_role ( "cluster_list_data_export" , true )
1900
1902
) . on ( "click" , ( d ) => {
@@ -3874,7 +3876,7 @@ var hivtrace_cluster_network_graph = function (
3874
3876
3875
3877
self . draw_node_table (
3876
3878
null ,
3877
- null ,
3879
+ node_list ,
3878
3880
[ table_headers ] ,
3879
3881
table_rows ,
3880
3882
container ,
@@ -4827,12 +4829,13 @@ var hivtrace_cluster_network_graph = function (
4827
4829
) {
4828
4830
self . legend_svg
4829
4831
. append ( "g" )
4830
- . classed ( "hiv-trace-legend multi_sequence " , true )
4832
+ . classed ( "hiv-trace-legend" , true )
4831
4833
. attr ( "transform" , "translate(0," + offset + ")" )
4832
4834
. append ( "circle" )
4833
4835
. attr ( "cx" , "8" )
4834
4836
. attr ( "cy" , "-4" )
4835
4837
. attr ( "r" , "8" )
4838
+ . classed ( "multi_sequence" , true )
4836
4839
. style ( "fill" , "none" ) ;
4837
4840
self . legend_svg
4838
4841
. append ( "g" )
@@ -6033,7 +6036,248 @@ var hivtrace_cluster_network_graph = function (
6033
6036
}
6034
6037
6035
6038
if ( self . _is_CDC_ ) {
6036
- self . draw_extended_node_table ( self . aggregate_indvidual_level_records ( ) ) ;
6039
+ self . node_search_div = self . get_ui_element_selector_by_role (
6040
+ "node_search_div" ,
6041
+ true
6042
+ ) ;
6043
+
6044
+ if ( self . node_search_div && self . isPrimaryGraph ) {
6045
+ const compute_type = ( t , d ) => {
6046
+ if ( t == "String" ) return "string" ;
6047
+ if ( t == "Number" ) return d . is_integer ? "integer" : "double" ;
6048
+ if ( t == "Date" ) return "date" ;
6049
+ return "string" ;
6050
+ } ;
6051
+
6052
+ self . node_search_attributes =
6053
+ self . _extract_exportable_attributes ( false ) ;
6054
+
6055
+ self . qb_filter_def = _ . sortBy (
6056
+ _ . map ( self . node_search_attributes , ( d ) => {
6057
+ let def = {
6058
+ id : d . raw_attribute_key ,
6059
+ label : d . label ,
6060
+ type : compute_type ( d . type , d ) ,
6061
+ } ;
6062
+
6063
+ if ( def . type == "date" ) {
6064
+ def . plugin = "datepicker" ;
6065
+ def . plugin_config = {
6066
+ format : "yyyy/mm/dd" ,
6067
+ todayBtn : "linked" ,
6068
+ todayHighlight : true ,
6069
+ autoclose : true ,
6070
+ } ;
6071
+ def . operators = [
6072
+ "equal" ,
6073
+ "not equal" ,
6074
+ "less" ,
6075
+ "less_or_equal" ,
6076
+ "greater" ,
6077
+ "greater_or_equal" ,
6078
+ ] ;
6079
+ } else {
6080
+ if ( def . type == "string" ) {
6081
+ def . operators = [
6082
+ "equal" ,
6083
+ "not equal" ,
6084
+ "contains" ,
6085
+ "begins_with" ,
6086
+ "ends_with" ,
6087
+ "is_empty" ,
6088
+ "is_not_empty" ,
6089
+ ] ;
6090
+ } else if ( def . type == "integer" || def . type == "double" ) {
6091
+ def . operators = [
6092
+ "equal" ,
6093
+ "not equal" ,
6094
+ "less" ,
6095
+ "less_or_equal" ,
6096
+ "greater" ,
6097
+ "greater_or_equal" ,
6098
+ "between" ,
6099
+ ] ;
6100
+ }
6101
+ }
6102
+
6103
+ return def ;
6104
+ } ) ,
6105
+ ( d ) => d . label
6106
+ ) ;
6107
+
6108
+ let query_buttons = d3
6109
+ . select ( self . node_search_div )
6110
+ . selectAll (
6111
+ '[data-hivtrace-ui-role="node-selector-search-buttonbar"]'
6112
+ ) ;
6113
+
6114
+ if ( query_buttons . empty ( ) ) {
6115
+ d3 . select ( self . node_search_div )
6116
+ . append ( "div" )
6117
+ . classed ( "alert alert-info alert-dismissible alert-small" , true )
6118
+ . text (
6119
+ "Please define some search criteria to find and display information on persons in the network. By default, no persons are displayed."
6120
+ )
6121
+ . append ( "button" )
6122
+ . classed ( "close" , true )
6123
+ . attr ( "data-dismiss" , "alert" )
6124
+ . append ( "span" )
6125
+ . html ( "×" ) ;
6126
+
6127
+ /*
6128
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
6129
+ <span aria-hidden="true">×</span>
6130
+ </button>
6131
+ */
6132
+
6133
+ query_buttons = d3
6134
+ . select ( self . node_search_div )
6135
+ . append ( "div" )
6136
+ . classed ( "btn-group btn-group-sm" , true )
6137
+ . attr ( "data-hivtrace-ui-role" , "node-selector-search-buttonbar" ) ;
6138
+ self . node_query_button_reset = query_buttons
6139
+ . append ( "button" )
6140
+ . text ( "Reset" )
6141
+ . classed ( "btn btn-warning" , true ) ;
6142
+ self . node_query_button_search = query_buttons
6143
+ . append ( "button" )
6144
+ . text ( "Search" )
6145
+ . classed ( "btn btn-primary" , true ) ;
6146
+ }
6147
+
6148
+ $ ( self . node_search_div ) . queryBuilder ( {
6149
+ plugins : [
6150
+ "filter-description" ,
6151
+ "unique-filter" ,
6152
+ "bt-tooltip-errors" ,
6153
+ "invert" ,
6154
+ "not-group" ,
6155
+ ] ,
6156
+ filters : self . qb_filter_def ,
6157
+ } ) ;
6158
+
6159
+ self . process_search_field = ( value , condition ) => {
6160
+ switch ( condition . type ) {
6161
+ case "string" : {
6162
+ if ( ! value ) value = "" ;
6163
+ value = value . toLowerCase ( ) ;
6164
+ switch ( condition . operator ) {
6165
+ case "equal" :
6166
+ return value == condition . value ;
6167
+ case "not equal" :
6168
+ return value != condition . value ;
6169
+ case "contains" :
6170
+ return value . indexOf ( condition . value ) >= 0 ;
6171
+ case "begins_with" :
6172
+ return value . indexOf ( condition . value ) == 0 ;
6173
+ case "ends_with" :
6174
+ return (
6175
+ value . indexOf ( condition . value ) ==
6176
+ Math . max ( 0 , value . length - condition . value . length )
6177
+ ) ;
6178
+ case "is_not_empty" :
6179
+ return value . length > 0 ;
6180
+ case "is_empty" :
6181
+ return value . length == 0 ;
6182
+ }
6183
+ break ;
6184
+ }
6185
+ case "date" :
6186
+ case "integer" :
6187
+ case "double" : {
6188
+ if ( ! value ) return false ;
6189
+ switch ( condition . operator ) {
6190
+ case "equal" :
6191
+ return value == condition . value ;
6192
+ case "not equal" :
6193
+ return value != condition . value ;
6194
+ case "less" :
6195
+ return value < condition . value ;
6196
+ case "less_or_equal" :
6197
+ return value <= condition . value ;
6198
+ case "greater" :
6199
+ return value > condition . value ;
6200
+ case "greater_or_equal" :
6201
+ return value >= condition . value ;
6202
+ case "between" :
6203
+ return (
6204
+ value >= condition . value [ 0 ] && value <= condition . value [ 1 ]
6205
+ ) ;
6206
+ }
6207
+ break ;
6208
+ }
6209
+ }
6210
+ return false ;
6211
+ } ;
6212
+
6213
+ self . process_search = ( data , rules ) => {
6214
+ let rule_results ;
6215
+ if ( rules . rules ) {
6216
+ rule_results = _ . map ( rules . rules , ( r ) => {
6217
+ return self . process_search ( data , r ) ;
6218
+ } ) ;
6219
+ } else {
6220
+ return self . process_search_field (
6221
+ self . attribute_node_value_by_id (
6222
+ data ,
6223
+ rules . id ,
6224
+ rules . type == "number"
6225
+ ) ,
6226
+ rules
6227
+ ) ;
6228
+ }
6229
+
6230
+ if ( rules . condition == "AND" ) {
6231
+ rule_results = _ . every ( rule_results , ( d ) => d ) ;
6232
+ } else if ( rules . condition == "OR" ) {
6233
+ rule_results = _ . some ( rule_results , ( d ) => d ) ;
6234
+ } else {
6235
+ rule_results = false ;
6236
+ }
6237
+
6238
+ return rules . not ? ! rule_results : rule_results ;
6239
+ } ;
6240
+
6241
+ self . rule_lc = ( rules ) => {
6242
+ if ( rules . rules ) {
6243
+ _ . each ( rules . rules , ( r ) => {
6244
+ self . rule_lc ( r ) ;
6245
+ } ) ;
6246
+ } else {
6247
+ if ( rules . value ) {
6248
+ if ( rules . type == "string" ) {
6249
+ rules . value = rules . value . toLowerCase ( ) ;
6250
+ } else if ( rules . type == "date" ) {
6251
+ rules . value = timeDateUtil . DateViewNodeSearch . parse (
6252
+ rules . value
6253
+ ) ;
6254
+ }
6255
+ }
6256
+ }
6257
+ } ;
6258
+
6259
+ if ( ! self . aggregate_entity_data ) {
6260
+ self . aggregate_entity_data =
6261
+ self . aggregate_indvidual_level_records ( ) ;
6262
+ }
6263
+
6264
+ self . node_query_button_reset . on ( "click" , ( d ) =>
6265
+ $ ( self . node_search_div ) . queryBuilder ( "reset" )
6266
+ ) ;
6267
+ self . node_query_button_search . on ( "click" , ( d ) => {
6268
+ var result = $ ( self . node_search_div ) . queryBuilder ( "getRules" ) ;
6269
+ if ( ! $ . isEmptyObject ( result ) ) {
6270
+ self . rule_lc ( result ) ;
6271
+ self . draw_extended_node_table (
6272
+ _ . filter ( self . aggregate_entity_data , ( d ) =>
6273
+ self . process_search ( d , result )
6274
+ )
6275
+ ) ;
6276
+ }
6277
+ } ) ;
6278
+ }
6279
+
6280
+ self . draw_extended_node_table ( [ ] ) ;
6037
6281
} else {
6038
6282
self . draw_node_table ( self . extra_node_table_columns ) ;
6039
6283
}
@@ -7906,7 +8150,7 @@ var hivtrace_cluster_network_graph = function (
7906
8150
var l_scale = 5000 , // link scale
7907
8151
graph_data = self . json , // the raw JSON network object
7908
8152
max_points_to_render = 1536 ,
7909
- max_nodes_to_show = 16384 ,
8153
+ max_nodes_to_show = 4096 ,
7910
8154
singletons = 0 ,
7911
8155
open_cluster_queue = [ ] ,
7912
8156
currently_displayed_objects ,
0 commit comments