| <!-- |
| Licensed to the Apache Software |
| Foundation (ASF) under one or more contributor license agreements. See the |
| NOTICE file distributed with this work for additional information regarding |
| copyright ownership. The ASF licenses this file to You under the Apache License, |
| Version 2.0 (the "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| http://www.apache.org/licenses/LICENSE-2.0 |
| Unless required by applicable law or agreed to in writing, software distributed |
| under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES |
| OR CONDITIONS OF ANY KIND, either express or implied. See the License for |
| the specific language governing permissions and limitations under the License. |
| --> |
| <div class="table-wrapper"> |
| <table attr.data-qe-id="{{'alerts-table'}}" class="table table-sm" metron-config-table [data]="alerts" [cellSelectable]="true" (onSort)="onSort($event)" style="white-space: nowrap;" (window:resize)="resize()" #table> |
| <thead> |
| <tr> |
| <th width="15" class="dropdown-cell"> </th> |
| <th width="55"> <metron-config-sorter [type]="'number'" [sortBy]="threatScoreFieldName()"> Score </metron-config-sorter> </th> |
| <th *ngFor="let column of alertsColumnsToDisplay" [id]="column.name"> <metron-config-sorter [type]="column.type" [sortBy]="column.name" title="{{column.name}}"> {{ column.name | columnNameTranslate | centerEllipses:15 }}</metron-config-sorter> </th> |
| <th width="20" class="icon-cell"></th> |
| <th width="20" class="icon-cell"></th> |
| <th width="25"><input id="select-deselect-all" class="fontawesome-checkbox" type="checkbox" (click)="selectAllRows($event)"><label for="select-deselect-all"></label></th> |
| </tr> |
| </thead> |
| <tbody> |
| <ng-container *ngFor="let alert of alerts; let alertIndex = index;"> |
| |
| <!-- standalone alerts (not wrapped by meta alert) --> |
| <ng-container *ngIf="!alert.source.metron_alert || alert.source.metron_alert.length === 0"> |
| <tr attr.data-qe-id="{{'row-' + alertIndex}}" |
| [ngClass]="{'selected' : selectedAlerts.indexOf(alert) != -1}" |
| ctxMenu ctxMenuId="alertEntry" ctxMenuTitle="Alert entry: {{ alert.id }}" |
| [ctxMenuData]="merge(alert.source, { id: alert.id })" |
| [ctxMenuItems]="[{ label: 'Show details', event: 'ctxMenuEventShowDetails'}]" |
| (ctxMenuEventShowDetails)="showDetails($event, alert)"> |
| <td width="15" class="icon-cell"></td> |
| <td> |
| <div appAlertSeverity [severity]="getScore(alert.source)"> |
| <a attr.data-qe-id="{{'score'}}" |
| ctxMenu ctxMenuId="score" |
| [ctxMenuData]="alert.source" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(threatScoreFieldName(), getScore(alert.source))"> |
| {{ hasScore(alert.source) ? getScore(alert.source) : '-' }} |
| </a> |
| </div> |
| </td> |
| <td *ngFor="let column of alertsColumnsToDisplay; let columnIndex = index;" #cell> |
| <a attr.data-qe-id="{{'cell-' + columnIndex}}" title="{{getValue(alert, column, true)}}" style="color:#689AA9" |
| ctxMenu [ctxMenuId]="column.name" |
| [ctxMenuData]="alert.source" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(column.name, getValue(alert, column, false))"> |
| {{ getValue(alert,column, true) | centerEllipses:20:cell }} |
| </a> |
| </td> |
| <td width="20" class="icon-cell"></td> |
| <td width="20" class="icon-cell"> |
| <i class="fa fa-comments-o" aria-hidden="true" *ngIf="alert.source.comments && alert.source.comments.length > 0"></i> |
| </td> |
| <td> |
| <input id="{{ alert.id }}" class="fontawesome-checkbox" type="checkbox" name="{{alert.id}}" (click)="selectRow($event, alert)" [checked]="selectedAlerts.indexOf(alert) != -1"> |
| <label attr.for="{{ alert.id }}"></label> |
| </td> |
| </tr> |
| </ng-container> |
| |
| <!-- alerts wrapped into a meta alert --> |
| <ng-container *ngIf="alert.source.metron_alert && alert.source.metron_alert.length > 0"> |
| <!-- meta alert entries --> |
| <tr [ngClass]="{'selected' : selectedAlerts.indexOf(alert) != -1}" |
| ctxMenu ctxMenuId="metaAlertEntry" ctxMenuTitle="Alert entry: {{ alert.id }}" |
| [ctxMenuData]="merge(alert.source, { id: alert.id })" |
| [ctxMenuItems]="[{ label: 'Show details', event: 'ctxMenuEventShowDetails'}]" |
| (ctxMenuEventShowDetails)="showDetails($event, alert)"> |
| <td width="15" class="icon-cell dropdown-cell" (click)="toggleExpandCollapse($event, alert)"> |
| <i class="fa" aria-hidden="true" |
| [ngClass]="{'fa-caret-right': metaAlertsDisplayState[alert.id] === metronAlertDisplayState.COLLAPSE, 'fa-caret-down': metaAlertsDisplayState[alert.id] === metronAlertDisplayState.EXPAND}"> |
| </i> |
| </td> |
| <td> |
| <div appAlertSeverity [severity]="getScore(alert.source)"> |
| <a ctxMenu ctxMenuId="metaAlert-{{ alert.id }}" |
| [ctxMenuData]="alert.source" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(threatScoreFieldName(), getScore(alert.source))"> |
| {{ hasScore(alert.source) ? getScore(alert.source) : '-' }} |
| </a> |
| </div> |
| </td> |
| <td [attr.colspan]="alertsColumnsToDisplay.length - 1"> |
| <a [attr.title]="alert.source['guid']" style="color:#689AA9" |
| ctxMenu ctxMenuId="metaAlert-{{ alert.id }}" |
| [ctxMenuData]="alert.source" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter('guid', alert.source['guid'])"> |
| {{ alert.source['name'] ? alert.source['name'] : alert.id | centerEllipses:20:cell }} |
| </a> |
| <span> ({{ alert.source.metron_alert.length }})</span> |
| </td> |
| <td> |
| <a *ngIf="isStatusFieldPresent" style="color:#689AA9" |
| ctxMenu ctxMenuId="metaAlert-{{ alert.id }}" |
| [ctxMenuData]="alert.source" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter('alert_status', alert.source['alert_status'])"> |
| {{ alert.source['alert_status'] ?alert.source['alert_status'] : 'New' | centerEllipses:20:cell }} |
| </a> |
| </td> |
| <td width="20" class="icon-cell" (click)="deleteMetaAlert($event, alert)"> |
| <i class="fa fa-chain-broken" aria-hidden="true"></i> |
| </td> |
| <td width="20" class="icon-cell"> |
| <i class="fa fa-comments-o" aria-hidden="true" *ngIf="alert.source.comments && alert.source.comments.length > 0"></i> |
| </td> |
| <td> |
| <input id="{{ alert.id }}" class="fontawesome-checkbox" type="checkbox" name="{{alert.id}}" (click)="selectRow($event, alert)" [checked]="selectedAlerts.indexOf(alert) != -1"> |
| <label attr.for="{{ alert.id }}"></label> |
| </td> |
| </tr> |
| <!-- nested alert entries --> |
| <tr *ngFor="let metaAlerts of alert.source.metron_alert; let metaAlertIndex = index;" |
| [ngClass]="{'selected' : selectedAlerts.indexOf(metaAlerts) != -1 , 'd-none': metaAlertsDisplayState[alert.id] === metronAlertDisplayState.COLLAPSE}" |
| ctxMenu ctxMenuId="metaAlertEntry" ctxMenuTitle="Alert entry: {{ alert.id }}" |
| [ctxMenuData]="merge(metaAlerts, { id: alert.id })" |
| [ctxMenuItems]="[{ label: 'Show details', event: 'ctxMenuEventShowDetails'}]" |
| (ctxMenuEventShowDetails)="showMetaAlertDetails($event, metaAlerts)"> |
| <td width="15" class="icon-cell" class="dropdown-cell"></td> |
| <td style="padding-left: 15px"> |
| <div appAlertSeverity [severity]="getScore(metaAlerts)"> |
| <a ctxMenu [ctxMenuId]="threatScoreFieldName()" |
| [ctxMenuData]="metaAlerts" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(threatScoreFieldName(), getScore(alert.source))"> |
| {{ hasScore(metaAlerts) ? getScore(metaAlerts) : '-' }} |
| </a> |
| </div> |
| </td> |
| <td *ngFor="let column of alertsColumnsToDisplay"> |
| <a *ngIf="column.name !== 'alert_status'" title="{{ getValueFromSource(metaAlerts, column, true) }}" style="color:#689AA9" |
| ctxMenu [ctxMenuId]="column.name" |
| [ctxMenuData]="metaAlerts" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(column.name, getValueFromSource(metaAlerts, column, false))"> |
| {{ getValueFromSource(metaAlerts, column, true) | centerEllipses:20:cell }} |
| </a> |
| <a *ngIf="column.name === 'alert_status'" title="{{getValue(alert, column, true)}}" style="color:#689AA9" |
| ctxMenu [ctxMenuId]="column.name" |
| [ctxMenuData]="metaAlerts" |
| [ctxMenuItems]="[{ label: 'Add to search bar', event: 'ctxMenuEventAddToFilters'}]" |
| (ctxMenuEventAddToFilters)="addFilter(column.name, getValue(alert, column, false))"> |
| {{ getValue(alert,column, true) | centerEllipses:20:cell }} |
| </a> |
| </td> |
| <td width="20" class="icon-cell" (click)="deleteOneAlertFromMetaAlert($event, alert, metaAlertIndex)"> |
| <i class="fa fa-chain-broken" aria-hidden="true"></i> |
| </td> |
| <td width="20" class="icon-cell"> |
| <i class="fa fa-comments-o" aria-hidden="true" *ngIf="metaAlerts.comments && metaAlerts.comments.length > 0"></i> |
| </td> |
| <td></td> |
| </tr> |
| </ng-container> |
| |
| </ng-container> |
| </tbody> |
| </table> |
| </div> |
| |
| <div class="col-md-3 offset-md-5"> |
| <metron-table-pagination [(pagination)]="pagination" (pageChange)="onPageChange()"> </metron-table-pagination> |
| </div> |
| |