@@ -76,17 +76,13 @@ export default class ConfigureFieldMapping extends Component<
76
76
if ( mappingsView . ok ) {
77
77
const existingMappings = { ...this . state . createdMappings } ;
78
78
Object . keys ( mappingsView . response . properties ) . forEach ( ( ruleFieldName ) => {
79
- existingMappings [ ruleFieldName ] = mappingsView . response . properties [ ruleFieldName ] . path ;
79
+ existingMappings [ ruleFieldName ] =
80
+ this . state . createdMappings [ ruleFieldName ] ||
81
+ mappingsView . response . properties [ ruleFieldName ] . path ;
80
82
} ) ;
81
83
this . setState ( {
82
84
createdMappings : existingMappings ,
83
- mappingsData : {
84
- ...mappingsView . response ,
85
- unmapped_field_aliases : [
86
- 'timestamp' ,
87
- ...( mappingsView . response . unmapped_field_aliases || [ ] ) ,
88
- ] ,
89
- } ,
85
+ mappingsData : mappingsView . response ,
90
86
} ) ;
91
87
this . updateMappingSharedState ( existingMappings ) ;
92
88
}
@@ -111,11 +107,16 @@ export default class ConfigureFieldMapping extends Component<
111
107
return invalidFields ;
112
108
}
113
109
114
- onMappingCreation = ( ruleFieldName : string , indxFieldName : string ) : void => {
110
+ onMappingCreation = ( ruleFieldName : string , indexFieldName : string ) : void => {
115
111
const newMappings : ruleFieldToIndexFieldMap = {
116
112
...this . state . createdMappings ,
117
- [ ruleFieldName ] : indxFieldName ,
113
+ [ ruleFieldName ] : indexFieldName ,
118
114
} ;
115
+
116
+ if ( ! indexFieldName ) {
117
+ delete newMappings [ ruleFieldName ] ;
118
+ }
119
+
119
120
const invalidMappingFieldNames = this . getInvalidMappingFieldNames ( newMappings ) ;
120
121
this . setState ( {
121
122
createdMappings : newMappings ,
@@ -142,17 +143,28 @@ export default class ConfigureFieldMapping extends Component<
142
143
...createdMappings ,
143
144
} ;
144
145
145
- // read only data
146
146
const mappedRuleFields : string [ ] = [ ] ;
147
- const mappedLogFields : string [ ] = [ ] ;
147
+ const logFields : Set < string > = new Set ( mappingsData . unmapped_index_fields || [ ] ) ;
148
+ let pendingCount = mappingsData . unmapped_field_aliases ?. length || 0 ;
149
+ const unmappedRuleFields = [ ...( mappingsData . unmapped_field_aliases || [ ] ) ] ;
150
+
148
151
Object . keys ( mappingsData . properties ) . forEach ( ( ruleFieldName ) => {
149
152
mappedRuleFields . unshift ( ruleFieldName ) ;
150
- mappedLogFields . unshift ( mappingsData . properties [ ruleFieldName ] . path ) ;
153
+
154
+ // Need this check to avoid adding undefined value
155
+ // When user removes existing mapping for default mapped values, the mapping will be undefined
156
+ if ( existingMappings [ ruleFieldName ] ) {
157
+ logFields . add ( existingMappings [ ruleFieldName ] ) ;
158
+ }
151
159
} ) ;
152
160
153
- // edit data
154
- const ruleFields = [ ...( mappingsData . unmapped_field_aliases || [ ] ) ] ;
155
- const indexFields = [ ...( mappingsData . unmapped_index_fields || [ ] ) ] ;
161
+ Object . keys ( existingMappings ) . forEach ( ( mappedRuleField ) => {
162
+ if ( unmappedRuleFields . includes ( mappedRuleField ) ) {
163
+ pendingCount -- ;
164
+ }
165
+ } ) ;
166
+
167
+ const indexFieldOptions = Array . from ( logFields ) ;
156
168
157
169
return (
158
170
< div >
@@ -168,24 +180,31 @@ export default class ConfigureFieldMapping extends Component<
168
180
169
181
< EuiSpacer size = { 'm' } />
170
182
171
- { ruleFields . length > 0 ? (
183
+ { unmappedRuleFields . length > 0 ? (
172
184
< >
173
- < EuiCallOut
174
- title = { `${ ruleFields . length } rule fields may need manual mapping` }
175
- color = { 'warning' }
176
- >
177
- < p >
178
- To generate accurate findings, we recommend mapping the following security rules
179
- fields with the log field from your data source.
180
- </ p >
181
- </ EuiCallOut >
185
+ { pendingCount > 0 ? (
186
+ < EuiCallOut
187
+ title = { `${ pendingCount } rule fields may need manual mapping` }
188
+ color = { 'warning' }
189
+ >
190
+ < p >
191
+ To generate accurate findings, we recommend mapping the following security rules
192
+ fields with the log fields in your data source.
193
+ </ p >
194
+ </ EuiCallOut >
195
+ ) : (
196
+ < EuiCallOut title = { `All rule fields have been mapped` } color = { 'success' } >
197
+ < p > Your data source have been mapped with all security rule fields.</ p >
198
+ </ EuiCallOut >
199
+ ) }
200
+
182
201
< EuiSpacer size = { 'm' } />
183
- < ContentPanel title = { `Manual field mappings ( ${ ruleFields . length } ) ` } titleSize = { 'm' } >
202
+ < ContentPanel title = { `Pending field mappings` } titleSize = { 'm' } >
184
203
< FieldMappingsTable < MappingViewType . Edit >
185
204
{ ...this . props }
186
205
loading = { loading }
187
- ruleFields = { ruleFields }
188
- indexFields = { indexFields }
206
+ ruleFields = { unmappedRuleFields }
207
+ indexFields = { indexFieldOptions }
189
208
mappingProps = { {
190
209
type : MappingViewType . Edit ,
191
210
existingMappings,
@@ -213,7 +232,7 @@ export default class ConfigureFieldMapping extends Component<
213
232
buttonContent = {
214
233
< div data-test-subj = "mapped-fields-btn" >
215
234
< EuiTitle >
216
- < h4 > { `View mapped fields (${ mappedRuleFields . length } )` } </ h4 >
235
+ < h4 > { `Default mapped fields (${ mappedRuleFields . length } )` } </ h4 >
217
236
</ EuiTitle >
218
237
</ div >
219
238
}
@@ -222,13 +241,16 @@ export default class ConfigureFieldMapping extends Component<
222
241
initialIsOpen = { false }
223
242
>
224
243
< EuiHorizontalRule margin = { 'xs' } />
225
- < FieldMappingsTable < MappingViewType . Readonly >
244
+ < FieldMappingsTable < MappingViewType . Edit >
226
245
{ ...this . props }
227
246
loading = { loading }
228
247
ruleFields = { mappedRuleFields }
229
- indexFields = { mappedLogFields }
248
+ indexFields = { indexFieldOptions }
230
249
mappingProps = { {
231
- type : MappingViewType . Readonly ,
250
+ type : MappingViewType . Edit ,
251
+ existingMappings,
252
+ invalidMappingFieldNames,
253
+ onMappingCreation : this . onMappingCreation ,
232
254
} }
233
255
/>
234
256
</ EuiAccordion >
0 commit comments