mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution] - remove styled-components and cleanup for timeline header actions (#206694)
## Summary Similar to [this previous PR](https://github.com/elastic/kibana/pull/206523), this PR originally aimed at replacing the usages styled-components with @emotion/react in the security_solution/public/common/components/header_actions folder. I quickly realized that a lot of props and event components were actually not used at all, so a cleanup was welcome. Absolutely no UI or behavior logic changes should be introduced by this PR. This PR will impact the tables in timeline, and the markdown use in osquery. The biggest code cleanup are: - removing a couple of components related to the header actions used in timeline - removing random unused translations, constants or helper functions #### Timeline query, correlation and pinned tabs    ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
ca77772d2a
commit
d9b9425372
23 changed files with 60 additions and 900 deletions
|
@ -203,7 +203,6 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]filters_global[\/\\]filters_global.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]guided_onboarding_tour[\/\\]tour_step.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_actions[\/\\]actions.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_actions[\/\\]header_actions.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_page[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_page[\/\\]title.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_section[\/\\]index.tsx/,
|
||||
|
@ -216,8 +215,6 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]link_icon[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]links[\/\\]helpers.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]loader[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]markdown_editor[\/\\]eui_form.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]markdown_editor[\/\\]plugins[\/\\]osquery[\/\\]renderer.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]matrix_histogram[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]matrix_histogram[\/\\]matrix_loader.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml[\/\\]score[\/\\]anomaly_score.tsx/,
|
||||
|
@ -508,8 +505,6 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]open_timeline[\/\\]timelines_table[\/\\]index.test.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]row_renderers_browser[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]row_renderers_browser[\/\\]row_renderers_browser.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]body[\/\\]column_headers[\/\\]events_select[\/\\]helpers.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]body[\/\\]column_headers[\/\\]events_select[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]body[\/\\]renderers[\/\\]alert_renderer[\/\\]helpers[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]body[\/\\]renderers[\/\\]cti[\/\\]helpers.ts/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]body[\/\\]renderers[\/\\]cti[\/\\]threat_match_rows.tsx/,
|
||||
|
@ -547,7 +542,6 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]tabs[\/\\]esql[\/\\]styles.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]tabs[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]tabs[\/\\]session[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]tabs[\/\\]session[\/\\]use_session_view.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]tabs[\/\\]shared[\/\\]layout.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]unified_components[\/\\]data_table[\/\\]custom_timeline_data_grid_body.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]timelines[\/\\]components[\/\\]timeline[\/\\]unified_components[\/\\]index.tsx/,
|
||||
|
|
|
@ -40160,7 +40160,6 @@
|
|||
"xpack.securitySolution.timeline.callOut.immutable.message.description": "Ce modèle de chronologie prédéfinie ne peut pas être modifié. Pour effectuer des modifications, veuillez dupliquer ce modèle et effectuer les modifications dans le double du modèle.",
|
||||
"xpack.securitySolution.timeline.callOut.unauthorized.message.description": "Vous pouvez utiliser Timeline pour étudier les événements, mais vous ne disposez pas des autorisations requises pour enregistrer les chronologies pour une utilisation ultérieure. Si vous avez besoin d'enregistrer les chronologies, contactez votre administrateur Kibana.",
|
||||
"xpack.securitySolution.timeline.cancelDeleteNoteLabel": "Conserver la note",
|
||||
"xpack.securitySolution.timeline.categoryTooltip": "Catégorie",
|
||||
"xpack.securitySolution.timeline.dataTable.dropZoneTableLabel": "Abandonner la zone pour ajouter un champ en tant que colonne dans la table",
|
||||
"xpack.securitySolution.timeline.dataTable.exitFullScreenButton": "Quitter le mode plein écran (échap)",
|
||||
"xpack.securitySolution.timeline.dataTable.footer.autoRefreshActiveDescription": "Actualisation automatique active",
|
||||
|
@ -40172,35 +40171,24 @@
|
|||
"xpack.securitySolution.timeline.defaultTimelineTitle": "Aucun",
|
||||
"xpack.securitySolution.timeline.deleteNoteError": "Une erreur est survenue lors de la suppression de la note {error}",
|
||||
"xpack.securitySolution.timeline.deleteNoteLabel": "Supprimer la note",
|
||||
"xpack.securitySolution.timeline.descriptionTooltip": "Description",
|
||||
"xpack.securitySolution.timeline.destination": "Destination",
|
||||
"xpack.securitySolution.timeline.EqlQueryBarLabel": "Requête EQL",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.title": "Outils de rendu d'événement",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.warning": "L'activation des outils de rendu d'événement peut avoir un impact sur les performances de la table.",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.pinSelected": "Épingler la sélection",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectAll": "Tous",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectNone": "Aucune",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectPinned": "Épinglé",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectUnpinned": "Désépinglé",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.unpinSelected": "Désépingler la sélection",
|
||||
"xpack.securitySolution.timeline.eventsTableAriaLabel": "événements ; page {activePage} sur {totalPages}",
|
||||
"xpack.securitySolution.timeline.failDescription": "Une erreur s'est produite",
|
||||
"xpack.securitySolution.timeline.failSearchDescription": "Impossible de lancer la recherche",
|
||||
"xpack.securitySolution.timeline.fieldChooser.availableFieldsTooltip": "Champs disponibles pour l'affichage dans le tableau.",
|
||||
"xpack.securitySolution.timeline.fieldChooser.timelineField.removeFieldTooltip": "Supprimer le champ du tableau",
|
||||
"xpack.securitySolution.timeline.fieldTooltip": "Champ",
|
||||
"xpack.securitySolution.timeline.file.fromOriginalPathDescription": "depuis son chemin d'origine",
|
||||
"xpack.securitySolution.timeline.flyout.header.closeTimelineButtonLabel": "Fermer {isTimeline, select, true {la chronologie} other {le modèle}}",
|
||||
"xpack.securitySolution.timeline.flyout.pane.removeColumnButtonLabel": "Supprimer la colonne",
|
||||
"xpack.securitySolution.timeline.flyoutTimelineTemplateLabel": "Modèle de chronologie",
|
||||
"xpack.securitySolution.timeline.footer.events": "Événements",
|
||||
"xpack.securitySolution.timeline.footer.loadingLabel": "Chargement",
|
||||
"xpack.securitySolution.timeline.footer.of": "de",
|
||||
"xpack.securitySolution.timeline.footer.rows": "lignes",
|
||||
"xpack.securitySolution.timeline.fullScreenButton": "Plein écran",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeAnalyzerButton": "Fermer l'analyseur",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeSessionButton": "Fermer le visualiseur de session",
|
||||
"xpack.securitySolution.timeline.hideColumnLabel": "Masquer la colonne",
|
||||
"xpack.securitySolution.timeline.kpiFailDescription": "Une erreur s'est produite",
|
||||
"xpack.securitySolution.timeline.kpiFailSearchDescription": "Échec de chargement des KPI",
|
||||
"xpack.securitySolution.timeline.kpis.destinationKpiTitle": "IP de destination",
|
||||
|
@ -40262,9 +40250,6 @@
|
|||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlSelectedText": "Rechercher",
|
||||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlTooltip": "Les événements des fournisseurs de données ci-dessus sont combinés avec les résultats de ce KQL",
|
||||
"xpack.securitySolution.timeline.sidePanel.maxAnomalyScoreByJobTitle": "Score maximal d'anomalie par tâche",
|
||||
"xpack.securitySolution.timeline.sortAZLabel": "Trier A-Z",
|
||||
"xpack.securitySolution.timeline.sortFieldsButton": "Trier les champs",
|
||||
"xpack.securitySolution.timeline.sortZALabel": "Trier Z-A",
|
||||
"xpack.securitySolution.timeline.source": "Source",
|
||||
"xpack.securitySolution.timeline.tabs.analyserTabTimelineTitle": "Analyseur",
|
||||
"xpack.securitySolution.timeline.tabs.discoverEsqlInTimeline": "ES|QL",
|
||||
|
@ -40276,7 +40261,6 @@
|
|||
"xpack.securitySolution.timeline.tabs.sessionTabTimelineTitle": "Vue de session",
|
||||
"xpack.securitySolution.timeline.tcp": "TCP",
|
||||
"xpack.securitySolution.timeline.toggleEventDetailsTitle": "Développer les détails de l'événement",
|
||||
"xpack.securitySolution.timeline.typeTooltip": "Type",
|
||||
"xpack.securitySolution.timeline.unsavedWorkMessage": "Quitter Timeline avec un travail non enregistré ?",
|
||||
"xpack.securitySolution.timeline.unsavedWorkTitle": "Modifications non enregistrées",
|
||||
"xpack.securitySolution.timeline.userDetails.managed.description": "Les métadonnées de toutes les intégrations de référentiel de ressource sont autorisées dans votre environnement.",
|
||||
|
|
|
@ -40020,7 +40020,6 @@
|
|||
"xpack.securitySolution.timeline.callOut.immutable.message.description": "この事前構築済みタイムラインテンプレートを修正することはできません。変更するには、このテンプレートを複製し、複製したテンプレートを修正します。",
|
||||
"xpack.securitySolution.timeline.callOut.unauthorized.message.description": "タイムラインを使用すると、イベントを調査することができますが、今後使用する目的でタイムラインを保存するために必要な権限がありません。タイムラインを保存する必要がある場合は、Kibana管理者に連絡してください。",
|
||||
"xpack.securitySolution.timeline.cancelDeleteNoteLabel": "メモを保持",
|
||||
"xpack.securitySolution.timeline.categoryTooltip": "カテゴリー",
|
||||
"xpack.securitySolution.timeline.dataTable.dropZoneTableLabel": "フィールドを列として表に追加するには、ゾーンをドロップします",
|
||||
"xpack.securitySolution.timeline.dataTable.exitFullScreenButton": "全画面モードを終了(Esc)",
|
||||
"xpack.securitySolution.timeline.dataTable.footer.autoRefreshActiveDescription": "自動更新アクション",
|
||||
|
@ -40032,35 +40031,24 @@
|
|||
"xpack.securitySolution.timeline.defaultTimelineTitle": "なし",
|
||||
"xpack.securitySolution.timeline.deleteNoteError": "メモの削除中にエラーが発生しました。{error}",
|
||||
"xpack.securitySolution.timeline.deleteNoteLabel": "メモを削除",
|
||||
"xpack.securitySolution.timeline.descriptionTooltip": "説明",
|
||||
"xpack.securitySolution.timeline.destination": "送信先",
|
||||
"xpack.securitySolution.timeline.EqlQueryBarLabel": "EQL クエリ",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.title": "イベントレンダラー",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.warning": "イベントレンダリングを有効化すると、テーブルパフォーマンスに影響する可能性があります。",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.pinSelected": "選択項目にピン付け",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectAll": "すべて",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectNone": "なし",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectPinned": "ピン付け済み",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectUnpinned": "ピンが外されました",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.unpinSelected": "選択項目のピンを外す",
|
||||
"xpack.securitySolution.timeline.eventsTableAriaLabel": "イベント; {activePage}/{totalPages} ページ",
|
||||
"xpack.securitySolution.timeline.failDescription": "エラーが発生しました",
|
||||
"xpack.securitySolution.timeline.failSearchDescription": "検索を実行できませんでした",
|
||||
"xpack.securitySolution.timeline.fieldChooser.availableFieldsTooltip": "フィールドをテーブルに表示できます。",
|
||||
"xpack.securitySolution.timeline.fieldChooser.timelineField.removeFieldTooltip": "フィールドを表から削除",
|
||||
"xpack.securitySolution.timeline.fieldTooltip": "フィールド",
|
||||
"xpack.securitySolution.timeline.file.fromOriginalPathDescription": "元のパスから",
|
||||
"xpack.securitySolution.timeline.flyout.header.closeTimelineButtonLabel": "{isTimeline, select, true {タイムライン} other {テンプレート}}を閉じる",
|
||||
"xpack.securitySolution.timeline.flyout.pane.removeColumnButtonLabel": "列を削除",
|
||||
"xpack.securitySolution.timeline.flyoutTimelineTemplateLabel": "タイムラインテンプレート",
|
||||
"xpack.securitySolution.timeline.footer.events": "イベント",
|
||||
"xpack.securitySolution.timeline.footer.loadingLabel": "読み込み中",
|
||||
"xpack.securitySolution.timeline.footer.of": "/",
|
||||
"xpack.securitySolution.timeline.footer.rows": "行",
|
||||
"xpack.securitySolution.timeline.fullScreenButton": "全画面",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeAnalyzerButton": "アナライザーを閉じる",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeSessionButton": "セッションビューアーの終了",
|
||||
"xpack.securitySolution.timeline.hideColumnLabel": "列を非表示",
|
||||
"xpack.securitySolution.timeline.kpiFailDescription": "エラーが発生しました",
|
||||
"xpack.securitySolution.timeline.kpiFailSearchDescription": "KPIの読み込みに失敗",
|
||||
"xpack.securitySolution.timeline.kpis.destinationKpiTitle": "デスティネーション IP",
|
||||
|
@ -40122,9 +40110,6 @@
|
|||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlSelectedText": "検索",
|
||||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlTooltip": "上のデータプロバイダーからのイベントは、この KQL からの結果と組み合わされます。",
|
||||
"xpack.securitySolution.timeline.sidePanel.maxAnomalyScoreByJobTitle": "ジョブ別の最高異常スコア",
|
||||
"xpack.securitySolution.timeline.sortAZLabel": "A-Zの昇順で並べ替え",
|
||||
"xpack.securitySolution.timeline.sortFieldsButton": "フィールドの並べ替え",
|
||||
"xpack.securitySolution.timeline.sortZALabel": "ZーAの降順で並べ替え",
|
||||
"xpack.securitySolution.timeline.source": "送信元",
|
||||
"xpack.securitySolution.timeline.tabs.analyserTabTimelineTitle": "アナライザー",
|
||||
"xpack.securitySolution.timeline.tabs.discoverEsqlInTimeline": "ES|QL",
|
||||
|
@ -40136,7 +40121,6 @@
|
|||
"xpack.securitySolution.timeline.tabs.sessionTabTimelineTitle": "セッションビュー",
|
||||
"xpack.securitySolution.timeline.tcp": "TCP",
|
||||
"xpack.securitySolution.timeline.toggleEventDetailsTitle": "イベントの詳細を展開",
|
||||
"xpack.securitySolution.timeline.typeTooltip": "型",
|
||||
"xpack.securitySolution.timeline.unsavedWorkMessage": "作業を保存せずにタイムラインから移動しますか?",
|
||||
"xpack.securitySolution.timeline.unsavedWorkTitle": "保存されていない変更",
|
||||
"xpack.securitySolution.timeline.userDetails.managed.description": "環境で有効になっているアセットリポジトリ統合からのメタデータ。",
|
||||
|
|
|
@ -39437,7 +39437,6 @@
|
|||
"xpack.securitySolution.timeline.callOut.immutable.message.description": "此预置时间线模板无法修改。要执行更改,请复制此模板,然后修改复制的模板。",
|
||||
"xpack.securitySolution.timeline.callOut.unauthorized.message.description": "可以使用'时间线'调查事件,但您没有所需的权限来保存时间线以供将来使用。如果需要保存时间线,请联系您的 Kibana 管理员。",
|
||||
"xpack.securitySolution.timeline.cancelDeleteNoteLabel": "保留备注",
|
||||
"xpack.securitySolution.timeline.categoryTooltip": "类别",
|
||||
"xpack.securitySolution.timeline.dataTable.dropZoneTableLabel": "放置区域以将字段作为列添加到表中",
|
||||
"xpack.securitySolution.timeline.dataTable.exitFullScreenButton": "退出全屏 (esc)",
|
||||
"xpack.securitySolution.timeline.dataTable.footer.autoRefreshActiveDescription": "自动刷新已启用",
|
||||
|
@ -39449,35 +39448,24 @@
|
|||
"xpack.securitySolution.timeline.defaultTimelineTitle": "无",
|
||||
"xpack.securitySolution.timeline.deleteNoteError": "删除备注时出错 {error}",
|
||||
"xpack.securitySolution.timeline.deleteNoteLabel": "删除备注",
|
||||
"xpack.securitySolution.timeline.descriptionTooltip": "描述",
|
||||
"xpack.securitySolution.timeline.destination": "目标",
|
||||
"xpack.securitySolution.timeline.EqlQueryBarLabel": "EQL 查询",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.title": "事件呈现器",
|
||||
"xpack.securitySolution.timeline.eventRenderersSwitch.warning": "启用事件呈现器可能会影响表性能。",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.pinSelected": "固定所选",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectAll": "全部",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectNone": "无",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectPinned": "已固定",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.selectUnpinned": "已取消固定",
|
||||
"xpack.securitySolution.timeline.eventsSelect.actions.unpinSelected": "取消固定所选",
|
||||
"xpack.securitySolution.timeline.eventsTableAriaLabel": "事件;第 {activePage} 页,共 {totalPages} 页",
|
||||
"xpack.securitySolution.timeline.failDescription": "发生错误",
|
||||
"xpack.securitySolution.timeline.failSearchDescription": "无法运行搜索",
|
||||
"xpack.securitySolution.timeline.fieldChooser.availableFieldsTooltip": "适用于在表中显示的字段。",
|
||||
"xpack.securitySolution.timeline.fieldChooser.timelineField.removeFieldTooltip": "从表中移除字段",
|
||||
"xpack.securitySolution.timeline.fieldTooltip": "字段",
|
||||
"xpack.securitySolution.timeline.file.fromOriginalPathDescription": "从其原始路径",
|
||||
"xpack.securitySolution.timeline.flyout.header.closeTimelineButtonLabel": "关闭{isTimeline, select, true {时间线} other {模板}}",
|
||||
"xpack.securitySolution.timeline.flyout.pane.removeColumnButtonLabel": "移除列",
|
||||
"xpack.securitySolution.timeline.flyoutTimelineTemplateLabel": "时间线模板",
|
||||
"xpack.securitySolution.timeline.footer.events": "事件",
|
||||
"xpack.securitySolution.timeline.footer.loadingLabel": "正在加载",
|
||||
"xpack.securitySolution.timeline.footer.of": "/",
|
||||
"xpack.securitySolution.timeline.footer.rows": "行",
|
||||
"xpack.securitySolution.timeline.fullScreenButton": "全屏",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeAnalyzerButton": "关闭分析器",
|
||||
"xpack.securitySolution.timeline.graphOverlay.closeSessionButton": "关闭会话查看器",
|
||||
"xpack.securitySolution.timeline.hideColumnLabel": "隐藏列",
|
||||
"xpack.securitySolution.timeline.kpiFailDescription": "发生错误",
|
||||
"xpack.securitySolution.timeline.kpiFailSearchDescription": "无法加载 KPI",
|
||||
"xpack.securitySolution.timeline.kpis.destinationKpiTitle": "目标 IP",
|
||||
|
@ -39539,9 +39527,6 @@
|
|||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlSelectedText": "搜索",
|
||||
"xpack.securitySolution.timeline.searchOrFilter.searchKqlTooltip": "来自上述数据提供程序的事件与此 KQL 的结果进行组合",
|
||||
"xpack.securitySolution.timeline.sidePanel.maxAnomalyScoreByJobTitle": "最大异常分数(按作业)",
|
||||
"xpack.securitySolution.timeline.sortAZLabel": "A-Z 排序",
|
||||
"xpack.securitySolution.timeline.sortFieldsButton": "排序字段",
|
||||
"xpack.securitySolution.timeline.sortZALabel": "Z-A 排序",
|
||||
"xpack.securitySolution.timeline.source": "源",
|
||||
"xpack.securitySolution.timeline.tabs.analyserTabTimelineTitle": "分析器",
|
||||
"xpack.securitySolution.timeline.tabs.discoverEsqlInTimeline": "ES|QL",
|
||||
|
@ -39553,7 +39538,6 @@
|
|||
"xpack.securitySolution.timeline.tabs.sessionTabTimelineTitle": "会话视图",
|
||||
"xpack.securitySolution.timeline.tcp": "TCP",
|
||||
"xpack.securitySolution.timeline.toggleEventDetailsTitle": "展开事件详情",
|
||||
"xpack.securitySolution.timeline.typeTooltip": "类型",
|
||||
"xpack.securitySolution.timeline.unsavedWorkMessage": "离开有未保存工作的时间线?",
|
||||
"xpack.securitySolution.timeline.unsavedWorkTitle": "未保存的更改",
|
||||
"xpack.securitySolution.timeline.userDetails.managed.description": "在您的环境中启用的任何资产存储库集成中的元数据。",
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { mockTimelineModel, TestProviders } from '../../mock';
|
||||
import { mockTriggersActionsUi } from '../../mock/mock_triggers_actions_ui_plugin';
|
||||
import type { ColumnHeaderOptions, HeaderActionProps } from '../../../../common/types';
|
||||
import { TimelineTabs } from '../../../../common/types';
|
||||
import { HeaderActions } from './header_actions';
|
||||
import { timelineActions } from '../../../timelines/store';
|
||||
import { getColumnHeader } from '../../../timelines/components/timeline/body/column_headers/helpers';
|
||||
|
||||
jest.mock('../../hooks/use_experimental_features', () => ({
|
||||
useIsExperimentalFeatureEnabled: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../timelines/components/row_renderers_browser', () => ({
|
||||
StatefulRowRenderersBrowser: () => <div data-test-subj="show-row-renderers-gear" />,
|
||||
}));
|
||||
|
||||
const mockDispatch = jest.fn();
|
||||
jest.mock('react-redux', () => ({
|
||||
...jest.requireActual('react-redux'),
|
||||
useDispatch: () => mockDispatch,
|
||||
}));
|
||||
|
||||
jest.mock('../../hooks/use_selector', () => ({
|
||||
useDeepEqualSelector: () => mockTimelineModel,
|
||||
useShallowEqualSelector: jest.fn(),
|
||||
}));
|
||||
|
||||
const columnId = 'test-field';
|
||||
const timelineId = 'test-timeline';
|
||||
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
mockTriggersActionsUi.getFieldBrowser.mockImplementation(
|
||||
({
|
||||
onToggleColumn,
|
||||
onResetColumns,
|
||||
}: {
|
||||
onToggleColumn: (columnId: string) => void;
|
||||
onResetColumns: () => void;
|
||||
}) => (
|
||||
<div data-test-subj="mock-field-browser">
|
||||
<div data-test-subj="mock-toggle-button" onClick={() => onToggleColumn(columnId)} />
|
||||
<div data-test-subj="mock-reset-button" onClick={onResetColumns} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
jest.mock('../../lib/kibana', () => ({
|
||||
useKibana: () => ({
|
||||
services: {
|
||||
triggersActionsUi: { ...mockTriggersActionsUi },
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const defaultProps: HeaderActionProps = {
|
||||
browserFields: {},
|
||||
columnHeaders: [],
|
||||
isSelectAllChecked: false,
|
||||
onSelectAll: jest.fn(),
|
||||
showEventsSelect: false,
|
||||
showSelectAllCheckbox: false,
|
||||
sort: [],
|
||||
tabType: TimelineTabs.query,
|
||||
timelineId,
|
||||
width: 10,
|
||||
fieldBrowserOptions: {},
|
||||
};
|
||||
|
||||
describe('HeaderActions', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('FieldBrowser', () => {
|
||||
it('should render the field browser', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(result.getByTestId('mock-field-browser')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should dispatch upsertColumn when non existing column is toggled', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
result.getByTestId('mock-toggle-button').click();
|
||||
|
||||
expect(mockDispatch).toHaveBeenCalledWith(
|
||||
timelineActions.upsertColumn({
|
||||
column: getColumnHeader(columnId, []),
|
||||
id: timelineId,
|
||||
index: 1,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should dispatch removeColumn when existing column is toggled', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions
|
||||
{...defaultProps}
|
||||
columnHeaders={[{ id: columnId } as unknown as ColumnHeaderOptions]}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
result.getByTestId('mock-toggle-button').click();
|
||||
|
||||
expect(mockDispatch).toHaveBeenCalledWith(
|
||||
timelineActions.removeColumn({
|
||||
columnId,
|
||||
id: timelineId,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should dispatch updateColumns when columns are reset', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
result.getByTestId('mock-reset-button').click();
|
||||
|
||||
expect(mockDispatch).toHaveBeenCalledWith(
|
||||
timelineActions.updateColumns({ id: timelineId, columns: mockTimelineModel.defaultColumns })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Controls', () => {
|
||||
it('should not show the event renderer settings', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(result.queryByTestId('show-row-renderers-gear')).toBeNull();
|
||||
});
|
||||
|
||||
it('should not show the sorting settings', () => {
|
||||
const result = render(
|
||||
<TestProviders>
|
||||
<HeaderActions {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(result.queryByTestId('timeline-sorting-fields')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,199 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useMemo, useCallback, memo } from 'react';
|
||||
import { EuiButtonIcon, EuiToolTip, EuiCheckbox } from '@elastic/eui';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { isFullScreen } from '../../../timelines/components/timeline/helpers';
|
||||
import type { HeaderActionProps } from '../../../../common/types';
|
||||
import { TimelineId } from '../../../../common/types';
|
||||
import { isActiveTimeline } from '../../../helpers';
|
||||
import { getColumnHeader } from '../../../timelines/components/timeline/body/column_headers/helpers';
|
||||
import { timelineActions } from '../../../timelines/store';
|
||||
import { useGlobalFullScreen, useTimelineFullScreen } from '../../containers/use_full_screen';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { DEFAULT_ACTION_BUTTON_WIDTH } from '.';
|
||||
import { EventsTh, EventsThContent } from '../../../timelines/components/timeline/styles';
|
||||
import { EXIT_FULL_SCREEN } from '../exit_full_screen/translations';
|
||||
import { EventsSelect } from '../../../timelines/components/timeline/body/column_headers/events_select';
|
||||
import * as i18n from './translations';
|
||||
import { useDeepEqualSelector } from '../../hooks/use_selector';
|
||||
import { selectTimelineById } from '../../../timelines/store/selectors';
|
||||
|
||||
const FieldBrowserContainer = styled.div`
|
||||
.euiToolTipAnchor {
|
||||
.euiButtonContent {
|
||||
padding: ${({ theme }) => `0 ${theme.eui.euiSizeXS}`};
|
||||
}
|
||||
button {
|
||||
color: ${({ theme }) => theme.eui.euiColorPrimary};
|
||||
}
|
||||
.euiButtonContent__icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.euiButtonEmpty__text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ActionsContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
const HeaderActionsComponent: React.FC<HeaderActionProps> = memo(
|
||||
({
|
||||
browserFields,
|
||||
columnHeaders,
|
||||
isSelectAllChecked,
|
||||
onSelectAll,
|
||||
showEventsSelect,
|
||||
showSelectAllCheckbox,
|
||||
showFullScreenToggle = true,
|
||||
timelineId,
|
||||
fieldBrowserOptions,
|
||||
}) => {
|
||||
const { triggersActionsUi } = useKibana().services;
|
||||
const { globalFullScreen, setGlobalFullScreen } = useGlobalFullScreen();
|
||||
const { timelineFullScreen, setTimelineFullScreen } = useTimelineFullScreen();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { defaultColumns } = useDeepEqualSelector((state) =>
|
||||
selectTimelineById(state, timelineId)
|
||||
);
|
||||
|
||||
const toggleFullScreen = useCallback(() => {
|
||||
if (timelineId === TimelineId.active) {
|
||||
setTimelineFullScreen(!timelineFullScreen);
|
||||
} else {
|
||||
setGlobalFullScreen(!globalFullScreen);
|
||||
}
|
||||
}, [
|
||||
timelineId,
|
||||
setTimelineFullScreen,
|
||||
timelineFullScreen,
|
||||
setGlobalFullScreen,
|
||||
globalFullScreen,
|
||||
]);
|
||||
|
||||
const fullScreen = useMemo(
|
||||
() =>
|
||||
isFullScreen({
|
||||
globalFullScreen,
|
||||
isActiveTimelines: isActiveTimeline(timelineId),
|
||||
timelineFullScreen,
|
||||
}),
|
||||
[globalFullScreen, timelineFullScreen, timelineId]
|
||||
);
|
||||
const handleSelectAllChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onSelectAll({ isSelected: event.currentTarget.checked });
|
||||
},
|
||||
[onSelectAll]
|
||||
);
|
||||
|
||||
const onResetColumns = useCallback(() => {
|
||||
dispatch(timelineActions.updateColumns({ id: timelineId, columns: defaultColumns }));
|
||||
}, [defaultColumns, dispatch, timelineId]);
|
||||
|
||||
const onToggleColumn = useCallback(
|
||||
(columnId: string) => {
|
||||
if (columnHeaders.some(({ id }) => id === columnId)) {
|
||||
dispatch(
|
||||
timelineActions.removeColumn({
|
||||
columnId,
|
||||
id: timelineId,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
timelineActions.upsertColumn({
|
||||
column: getColumnHeader(columnId, defaultColumns),
|
||||
id: timelineId,
|
||||
index: 1,
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
[columnHeaders, dispatch, timelineId, defaultColumns]
|
||||
);
|
||||
|
||||
return (
|
||||
<ActionsContainer data-test-subj="header-actions-container">
|
||||
{showSelectAllCheckbox && (
|
||||
<EventsTh role="checkbox">
|
||||
<EventsThContent textAlign="center" width={DEFAULT_ACTION_BUTTON_WIDTH}>
|
||||
<EuiCheckbox
|
||||
data-test-subj="select-all-events"
|
||||
id={'select-all-events'}
|
||||
checked={isSelectAllChecked}
|
||||
onChange={handleSelectAllChange}
|
||||
/>
|
||||
</EventsThContent>
|
||||
</EventsTh>
|
||||
)}
|
||||
{fieldBrowserOptions && (
|
||||
<EventsTh role="button">
|
||||
<FieldBrowserContainer>
|
||||
{triggersActionsUi.getFieldBrowser({
|
||||
browserFields,
|
||||
columnIds: columnHeaders.map(({ id }) => id),
|
||||
onResetColumns,
|
||||
onToggleColumn,
|
||||
options: fieldBrowserOptions,
|
||||
})}
|
||||
</FieldBrowserContainer>
|
||||
</EventsTh>
|
||||
)}
|
||||
|
||||
{showFullScreenToggle && (
|
||||
<EventsTh role="button">
|
||||
<EventsThContent textAlign="center" width={DEFAULT_ACTION_BUTTON_WIDTH}>
|
||||
<EuiToolTip content={fullScreen ? EXIT_FULL_SCREEN : i18n.FULL_SCREEN}>
|
||||
<EuiButtonIcon
|
||||
aria-label={
|
||||
isFullScreen({
|
||||
globalFullScreen,
|
||||
isActiveTimelines: isActiveTimeline(timelineId),
|
||||
timelineFullScreen,
|
||||
})
|
||||
? EXIT_FULL_SCREEN
|
||||
: i18n.FULL_SCREEN
|
||||
}
|
||||
display={fullScreen ? 'fill' : 'empty'}
|
||||
color="primary"
|
||||
data-test-subj={
|
||||
// a full screen button gets created for timeline and for the host page
|
||||
// this sets the data-test-subj for each case so that tests can differentiate between them
|
||||
isActiveTimeline(timelineId) ? 'full-screen-active' : 'full-screen'
|
||||
}
|
||||
iconType="fullScreen"
|
||||
onClick={toggleFullScreen}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EventsThContent>
|
||||
</EventsTh>
|
||||
)}
|
||||
|
||||
{showEventsSelect && (
|
||||
<EventsTh role="button">
|
||||
<EventsThContent textAlign="center" width={DEFAULT_ACTION_BUTTON_WIDTH}>
|
||||
<EventsSelect checkState="unchecked" timelineId={timelineId} />
|
||||
</EventsThContent>
|
||||
</EventsTh>
|
||||
)}
|
||||
</ActionsContainer>
|
||||
);
|
||||
}
|
||||
);
|
||||
HeaderActionsComponent.displayName = 'HeaderActionsComponent';
|
||||
|
||||
export const HeaderActions = React.memo(HeaderActionsComponent);
|
|
@ -7,4 +7,3 @@
|
|||
|
||||
export * from './helpers';
|
||||
export * from './actions';
|
||||
export * from './header_actions';
|
||||
|
|
|
@ -14,14 +14,6 @@ export const OPEN_SESSION_VIEW = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const SORT_FIELDS = i18n.translate('xpack.securitySolution.timeline.sortFieldsButton', {
|
||||
defaultMessage: 'Sort fields',
|
||||
});
|
||||
|
||||
export const FULL_SCREEN = i18n.translate('xpack.securitySolution.timeline.fullScreenButton', {
|
||||
defaultMessage: 'Full screen',
|
||||
});
|
||||
|
||||
export const VIEW_DETAILS = i18n.translate(
|
||||
'xpack.securitySolution.hoverActions.viewDetailsAriaLabel',
|
||||
{
|
||||
|
|
|
@ -6,36 +6,26 @@
|
|||
*/
|
||||
|
||||
import React, { forwardRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import type { EuiMarkdownEditorProps } from '@elastic/eui';
|
||||
import { EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||
import { EuiFormRow } from '@elastic/eui';
|
||||
import type { FieldHook } from '../../../shared_imports';
|
||||
import { getFieldValidityAndErrorMessage } from '../../../shared_imports';
|
||||
|
||||
import type { MarkdownEditorRef } from './editor';
|
||||
import { MarkdownEditor } from './editor';
|
||||
|
||||
/* eslint-disable react/no-unused-prop-types */
|
||||
type MarkdownEditorFormProps = EuiMarkdownEditorProps & {
|
||||
id: string;
|
||||
field: FieldHook;
|
||||
dataTestSubj: string;
|
||||
idAria: string;
|
||||
isDisabled?: boolean;
|
||||
bottomRightContent?: React.ReactNode;
|
||||
includePlugins?: boolean;
|
||||
};
|
||||
/* eslint-enable react/no-unused-prop-types */
|
||||
|
||||
const BottomContentWrapper = styled(EuiFlexGroup)`
|
||||
${({ theme }) => `
|
||||
padding: ${theme.eui.euiSizeM} 0;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const MarkdownEditorForm = React.memo(
|
||||
forwardRef<MarkdownEditorRef, MarkdownEditorFormProps>(
|
||||
({ id, field, dataTestSubj, idAria, bottomRightContent, includePlugins }, ref) => {
|
||||
({ field, dataTestSubj, idAria, includePlugins }, ref) => {
|
||||
const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field);
|
||||
const [isMarkdownInvalid, setIsMarkdownInvalid] = useState(false);
|
||||
|
||||
|
@ -50,23 +40,15 @@ export const MarkdownEditorForm = React.memo(
|
|||
label={field.label}
|
||||
labelAppend={field.labelAppend}
|
||||
>
|
||||
<>
|
||||
<MarkdownEditor
|
||||
ref={ref}
|
||||
ariaLabel={idAria}
|
||||
editorId={id}
|
||||
onChange={field.setValue}
|
||||
value={field.value as string}
|
||||
data-test-subj={`${dataTestSubj}-markdown-editor`}
|
||||
setIsMarkdownInvalid={setIsMarkdownInvalid}
|
||||
includePlugins={includePlugins}
|
||||
/>
|
||||
{bottomRightContent && (
|
||||
<BottomContentWrapper justifyContent={'flexEnd'}>
|
||||
<EuiFlexItem grow={false}>{bottomRightContent}</EuiFlexItem>
|
||||
</BottomContentWrapper>
|
||||
)}
|
||||
</>
|
||||
<MarkdownEditor
|
||||
ref={ref}
|
||||
ariaLabel={idAria}
|
||||
onChange={field.setValue}
|
||||
value={field.value as string}
|
||||
data-test-subj={`${dataTestSubj}-markdown-editor`}
|
||||
setIsMarkdownInvalid={setIsMarkdownInvalid}
|
||||
includePlugins={includePlugins}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
// receives the configuration from the parser and renders
|
||||
import React, { useCallback, useContext, useMemo, useState } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import { reduce } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import { EuiButton, EuiToolTip } from '@elastic/eui';
|
||||
import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
|
||||
import { useUpsellingMessage } from '../../../../hooks/use_upselling';
|
||||
|
@ -18,12 +18,6 @@ import { expandDottedObject } from '../../../../../../common/utils/expand_dotted
|
|||
import OsqueryLogo from './osquery_icon/osquery.svg';
|
||||
import { OsqueryFlyout } from '../../../../../detections/components/osquery/osquery_flyout';
|
||||
|
||||
const StyledEuiButton = styled(EuiButton)`
|
||||
> span > img {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const OsqueryRenderer = ({
|
||||
configuration,
|
||||
}: {
|
||||
|
@ -58,16 +52,21 @@ export const OsqueryRenderer = ({
|
|||
return (
|
||||
<>
|
||||
<EuiToolTip content={interactionsUpsellingMessage}>
|
||||
<StyledEuiButton
|
||||
<EuiButton
|
||||
iconType={OsqueryLogo}
|
||||
onClick={handleOpen}
|
||||
disabled={!!interactionsUpsellingMessage}
|
||||
css={css`
|
||||
> span > img {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
`}
|
||||
>
|
||||
{configuration.label ??
|
||||
i18n.translate('xpack.securitySolution.markdown.osquery.runOsqueryButtonLabel', {
|
||||
defaultMessage: 'Run Osquery',
|
||||
})}
|
||||
</StyledEuiButton>
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
{showFlyout && (
|
||||
<OsqueryFlyout
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiText } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Pin } from '../../../pin';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
const InputDisplay = styled.div`
|
||||
width: 5px;
|
||||
`;
|
||||
|
||||
InputDisplay.displayName = 'InputDisplay';
|
||||
|
||||
const PinIconContainer = styled.div`
|
||||
margin-right: 5px;
|
||||
`;
|
||||
|
||||
PinIconContainer.displayName = 'PinIconContainer';
|
||||
|
||||
const PinActionItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
PinActionItem.displayName = 'PinActionItem';
|
||||
|
||||
export type EventsSelectAction =
|
||||
| 'select-all'
|
||||
| 'select-none'
|
||||
| 'select-pinned'
|
||||
| 'select-unpinned'
|
||||
| 'pin-selected'
|
||||
| 'unpin-selected';
|
||||
|
||||
export interface EventsSelectOption {
|
||||
value: EventsSelectAction;
|
||||
inputDisplay: JSX.Element | string;
|
||||
disabled?: boolean;
|
||||
dropdownDisplay: JSX.Element | string;
|
||||
}
|
||||
|
||||
export const DropdownDisplay = React.memo<{ text: string }>(({ text }) => (
|
||||
<EuiText size="s" color="subdued">
|
||||
{text}
|
||||
</EuiText>
|
||||
));
|
||||
|
||||
DropdownDisplay.displayName = 'DropdownDisplay';
|
||||
|
||||
export const getEventsSelectOptions = (): EventsSelectOption[] => [
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: <DropdownDisplay text={i18n.SELECT_ALL} />,
|
||||
value: 'select-all',
|
||||
},
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: <DropdownDisplay text={i18n.SELECT_NONE} />,
|
||||
value: 'select-none',
|
||||
},
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: <DropdownDisplay text={i18n.SELECT_PINNED} />,
|
||||
value: 'select-pinned',
|
||||
},
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: <DropdownDisplay text={i18n.SELECT_UNPINNED} />,
|
||||
value: 'select-unpinned',
|
||||
},
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: (
|
||||
<PinActionItem>
|
||||
<PinIconContainer>
|
||||
<Pin allowUnpinning={true} isAlert={false} pinned={true} />
|
||||
</PinIconContainer>
|
||||
<DropdownDisplay text={i18n.PIN_SELECTED} />
|
||||
</PinActionItem>
|
||||
),
|
||||
value: 'pin-selected',
|
||||
},
|
||||
{
|
||||
inputDisplay: <InputDisplay />,
|
||||
disabled: true,
|
||||
dropdownDisplay: (
|
||||
<PinActionItem>
|
||||
<PinIconContainer>
|
||||
<Pin allowUnpinning={true} isAlert={false} pinned={false} />
|
||||
</PinIconContainer>
|
||||
<DropdownDisplay text={i18n.UNPIN_SELECTED} />
|
||||
</PinActionItem>
|
||||
),
|
||||
value: 'unpin-selected',
|
||||
},
|
||||
];
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiCheckbox, EuiSuperSelect } from '@elastic/eui';
|
||||
import { noop } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import styled, { createGlobalStyle } from 'styled-components';
|
||||
|
||||
import { getEventsSelectOptions } from './helpers';
|
||||
|
||||
export type CheckState = 'checked' | 'indeterminate' | 'unchecked';
|
||||
export const EVENTS_SELECT_WIDTH = 60; // px
|
||||
|
||||
// SIDE EFFECT: the following `createGlobalStyle` overrides
|
||||
// the style of the select items
|
||||
const EventsSelectGlobalStyle = createGlobalStyle`
|
||||
.eventsSelectItem {
|
||||
width: 100% !important;
|
||||
|
||||
.euiContextMenu__icon {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.eventsSelectDropdown {
|
||||
width: ${EVENTS_SELECT_WIDTH}px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CheckboxContainer = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
CheckboxContainer.displayName = 'CheckboxContainer';
|
||||
|
||||
const PositionedCheckbox = styled.div`
|
||||
left: 7px;
|
||||
position: absolute;
|
||||
top: -28px;
|
||||
`;
|
||||
|
||||
PositionedCheckbox.displayName = 'PositionedCheckbox';
|
||||
|
||||
interface Props {
|
||||
checkState: CheckState;
|
||||
timelineId: string;
|
||||
}
|
||||
|
||||
export const EventsSelect = React.memo<Props>(({ checkState, timelineId }) => {
|
||||
return (
|
||||
<div data-test-subj="events-select">
|
||||
<EuiSuperSelect
|
||||
className="eventsSelectDropdown"
|
||||
data-test-subj="events-select-dropdown"
|
||||
itemClassName="eventsSelectItem"
|
||||
onChange={noop}
|
||||
options={getEventsSelectOptions()}
|
||||
/>
|
||||
<CheckboxContainer data-test-subj="timeline-events-select-checkbox-container">
|
||||
<PositionedCheckbox data-test-subj="timeline-events-select-positioned-checkbox">
|
||||
<EuiCheckbox
|
||||
checked={checkState === 'checked'}
|
||||
data-test-subj="events-select-checkbox"
|
||||
disabled
|
||||
id={`timeline-${timelineId}-events-select`}
|
||||
indeterminate={checkState === 'indeterminate'}
|
||||
onChange={noop}
|
||||
/>
|
||||
</PositionedCheckbox>
|
||||
</CheckboxContainer>
|
||||
<EventsSelectGlobalStyle />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
EventsSelect.displayName = 'EventsSelect';
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const PIN_SELECTED = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.pinSelected',
|
||||
{
|
||||
defaultMessage: 'Pin selected',
|
||||
}
|
||||
);
|
||||
|
||||
export const SELECT_ALL = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.selectAll',
|
||||
{
|
||||
defaultMessage: 'All',
|
||||
}
|
||||
);
|
||||
|
||||
export const SELECT_NONE = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.selectNone',
|
||||
{
|
||||
defaultMessage: 'None',
|
||||
}
|
||||
);
|
||||
|
||||
export const SELECT_PINNED = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.selectPinned',
|
||||
{
|
||||
defaultMessage: 'Pinned',
|
||||
}
|
||||
);
|
||||
|
||||
export const SELECT_UNPINNED = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.selectUnpinned',
|
||||
{
|
||||
defaultMessage: 'Unpinned',
|
||||
}
|
||||
);
|
||||
|
||||
export const UNPIN_SELECTED = i18n.translate(
|
||||
'xpack.securitySolution.timeline.eventsSelect.actions.unpinSelected',
|
||||
{
|
||||
defaultMessage: 'Unpin selected',
|
||||
}
|
||||
);
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const CATEGORY = i18n.translate('xpack.securitySolution.timeline.categoryTooltip', {
|
||||
defaultMessage: 'Category',
|
||||
});
|
||||
|
||||
export const DESCRIPTION = i18n.translate('xpack.securitySolution.timeline.descriptionTooltip', {
|
||||
defaultMessage: 'Description',
|
||||
});
|
||||
|
||||
export const FIELD = i18n.translate('xpack.securitySolution.timeline.fieldTooltip', {
|
||||
defaultMessage: 'Field',
|
||||
});
|
||||
|
||||
export const FULL_SCREEN = i18n.translate('xpack.securitySolution.timeline.fullScreenButton', {
|
||||
defaultMessage: 'Full screen',
|
||||
});
|
||||
|
||||
export const HIDE_COLUMN = i18n.translate('xpack.securitySolution.timeline.hideColumnLabel', {
|
||||
defaultMessage: 'Hide column',
|
||||
});
|
||||
|
||||
export const SORT_AZ = i18n.translate('xpack.securitySolution.timeline.sortAZLabel', {
|
||||
defaultMessage: 'Sort A-Z',
|
||||
});
|
||||
|
||||
export const SORT_ZA = i18n.translate('xpack.securitySolution.timeline.sortZALabel', {
|
||||
defaultMessage: 'Sort Z-A',
|
||||
});
|
||||
|
||||
export const TYPE = i18n.translate('xpack.securitySolution.timeline.typeTooltip', {
|
||||
defaultMessage: 'Type',
|
||||
});
|
||||
|
||||
export const REMOVE_COLUMN = i18n.translate(
|
||||
'xpack.securitySolution.timeline.flyout.pane.removeColumnButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Remove column',
|
||||
}
|
||||
);
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { rgba } from 'polished';
|
||||
import styled, { createGlobalStyle } from 'styled-components';
|
||||
import { IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME } from '@kbn/securitysolution-t-grid';
|
||||
|
@ -94,44 +93,12 @@ export const EventsTh = styled.div.attrs<{ role: string }>(
|
|||
}
|
||||
|
||||
/* don't display Draggable placeholder */
|
||||
|
||||
[data-rbd-placeholder-context-id] {
|
||||
display: none !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export const EventsThContent = styled.div.attrs(({ className = '' }) => ({
|
||||
className: `siemEventsTable__thContent ${className}`,
|
||||
}))<{ textAlign?: string; width?: number }>`
|
||||
font-size: ${({ theme }) => theme.eui.euiFontSizeXS};
|
||||
font-weight: ${({ theme }) => theme.eui.euiFontWeightSemiBold};
|
||||
line-height: ${({ theme }) => theme.eui.euiLineHeight};
|
||||
min-width: 0;
|
||||
padding: ${({ theme }) => theme.eui.euiSizeXS};
|
||||
text-align: ${({ textAlign }) => textAlign};
|
||||
width: ${({ width }) =>
|
||||
width != null
|
||||
? `${width}px`
|
||||
: '100%'}; /* Using width: 100% instead of flex: 1 and max-width: 100% for IE11 */
|
||||
|
||||
> button.euiButtonIcon,
|
||||
> .euiToolTipAnchor > button.euiButtonIcon {
|
||||
margin-left: ${({ theme }) => `-${theme.eui.euiSizeXS}`};
|
||||
}
|
||||
`;
|
||||
|
||||
const TIMELINE_EVENT_DETAILS_OFFSET = 40;
|
||||
|
||||
interface WidthProp {
|
||||
width: number;
|
||||
}
|
||||
|
||||
export const EventsTrSupplementContainer = styled.div.attrs<WidthProp>(({ width }) => ({
|
||||
role: 'dialog',
|
||||
style: {
|
||||
width: `${width - TIMELINE_EVENT_DETAILS_OFFSET}px`,
|
||||
},
|
||||
}))<WidthProp>``;
|
||||
|
||||
export const EventsTrSupplement = styled.div.attrs(({ className = '' }) => ({
|
||||
className: `siemEventsTable__trSupplement ${className}` as string,
|
||||
}))<{ className: string; $display?: 'block' | 'inline-block' }>`
|
||||
|
@ -139,6 +106,7 @@ export const EventsTrSupplement = styled.div.attrs(({ className = '' }) => ({
|
|||
font-size: ${({ theme }) => theme.eui.euiFontSizeXS};
|
||||
line-height: ${({ theme }) => theme.eui.euiLineHeight};
|
||||
padding-left: ${({ theme }) => theme.eui.euiSizeM};
|
||||
|
||||
.euiAccordion + div {
|
||||
background-color: ${({ theme }) => theme.eui.euiColorEmptyShade};
|
||||
padding: 0 ${({ theme }) => theme.eui.euiSizeS};
|
||||
|
@ -164,14 +132,6 @@ export const EventsTdContent = styled.div.attrs(({ className }) => ({
|
|||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* EVENTS LOADING
|
||||
*/
|
||||
export const EventsLoading = styled(EuiLoadingSpinner)`
|
||||
margin: 0 2px;
|
||||
vertical-align: middle;
|
||||
`;
|
||||
|
||||
export const HideShowContainer = styled.div.attrs<{ $isVisible: boolean }>(
|
||||
({ $isVisible = false }) => ({
|
||||
style: {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { EuiDataGridControlColumn } from '@elastic/eui';
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
@ -12,8 +13,6 @@ import type { ConnectedProps } from 'react-redux';
|
|||
import { connect } from 'react-redux';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { InPortal } from 'react-reverse-portal';
|
||||
import type { EuiDataGridControlColumn } from '@elastic/eui';
|
||||
|
||||
import { DataLoadingState } from '@kbn/unified-data-table';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy';
|
||||
|
@ -47,7 +46,7 @@ import { useTimelineControlColumn } from '../shared/use_timeline_control_columns
|
|||
import { LeftPanelNotesTab } from '../../../../../flyout/document_details/left';
|
||||
import { useNotesInFlyout } from '../../properties/use_notes_in_flyout';
|
||||
import { NotesFlyout } from '../../properties/notes_flyout';
|
||||
import { NotesEventTypes, DocumentEventTypes } from '../../../../../common/lib/telemetry';
|
||||
import { DocumentEventTypes, NotesEventTypes } from '../../../../../common/lib/telemetry';
|
||||
import { TimelineRefetch } from '../../refetch_timeline';
|
||||
|
||||
export type Props = TimelineTabCommonProps & PropsFromRedux;
|
||||
|
@ -213,10 +212,7 @@ export const EqlTabContentComponent: React.FC<Props> = ({
|
|||
);
|
||||
|
||||
const leadingControlColumns = useTimelineControlColumn({
|
||||
columns,
|
||||
sort: TIMELINE_NO_SORTING,
|
||||
timelineId,
|
||||
activeTab: TimelineTabs.eql,
|
||||
refetch,
|
||||
events,
|
||||
pinnedEventIds,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useMemo, useCallback, memo, useState, useEffect } from 'react';
|
||||
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
@ -37,7 +37,7 @@ import { useTimelineControlColumn } from '../shared/use_timeline_control_columns
|
|||
import { LeftPanelNotesTab } from '../../../../../flyout/document_details/left';
|
||||
import { useNotesInFlyout } from '../../properties/use_notes_in_flyout';
|
||||
import { NotesFlyout } from '../../properties/notes_flyout';
|
||||
import { NotesEventTypes, DocumentEventTypes } from '../../../../../common/lib/telemetry';
|
||||
import { DocumentEventTypes, NotesEventTypes } from '../../../../../common/lib/telemetry';
|
||||
import { defaultUdtHeaders } from '../../body/column_headers/default_headers';
|
||||
|
||||
interface PinnedFilter {
|
||||
|
@ -246,10 +246,7 @@ export const PinnedTabContentComponent: React.FC<Props> = ({
|
|||
);
|
||||
|
||||
const leadingControlColumns = useTimelineControlColumn({
|
||||
columns,
|
||||
sort,
|
||||
timelineId,
|
||||
activeTab: TimelineTabs.pinned,
|
||||
refetch,
|
||||
events,
|
||||
pinnedEventIds,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useMemo, useEffect, useCallback, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import { connect, useDispatch } from 'react-redux';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
@ -41,7 +41,6 @@ import { SourcererScopeName } from '../../../../../sourcerer/store/model';
|
|||
import { timelineDefaults } from '../../../../store/defaults';
|
||||
import { useSourcererDataView } from '../../../../../sourcerer/containers';
|
||||
import { isActiveTimeline } from '../../../../../helpers';
|
||||
|
||||
import type { TimelineModel } from '../../../../store/model';
|
||||
import { UnifiedTimelineBody } from '../../body/unified_timeline_body';
|
||||
import { isTimerangeSame } from '../shared/utils';
|
||||
|
@ -281,10 +280,7 @@ export const QueryTabContentComponent: React.FC<Props> = ({
|
|||
);
|
||||
|
||||
const leadingControlColumns = useTimelineControlColumn({
|
||||
columns,
|
||||
sort,
|
||||
timelineId,
|
||||
activeTab: TimelineTabs.query,
|
||||
refetch,
|
||||
events,
|
||||
pinnedEventIds,
|
||||
|
|
|
@ -20,3 +20,10 @@ export const CLOSE_SESSION = i18n.translate(
|
|||
defaultMessage: 'Close session viewer',
|
||||
}
|
||||
);
|
||||
|
||||
export const FULL_SCREEN = i18n.translate(
|
||||
'xpack.securitySolution.timeline.graphOverlay.fullScreenButton',
|
||||
{
|
||||
defaultMessage: 'Full screen',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -5,9 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { EuiButtonEmpty, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiButtonIcon,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiToolTip,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { dataTableSelectors, tableDefaults } from '@kbn/securitysolution-data-table';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
|
@ -24,11 +31,10 @@ import * as i18n from './translations';
|
|||
import { TimelineTabs } from '../../../../../../common/types/timeline';
|
||||
import { SourcererScopeName } from '../../../../../sourcerer/store/model';
|
||||
import { SCROLLING_DISABLED_CLASS_NAME } from '../../../../../../common/constants';
|
||||
import { FULL_SCREEN } from '../../body/column_headers/translations';
|
||||
import { EXIT_FULL_SCREEN } from '../../../../../common/components/exit_full_screen/translations';
|
||||
import {
|
||||
useTimelineFullScreen,
|
||||
useGlobalFullScreen,
|
||||
useTimelineFullScreen,
|
||||
} from '../../../../../common/containers/use_full_screen';
|
||||
import { useUserPrivileges } from '../../../../../common/components/user_privileges';
|
||||
import { timelineActions, timelineSelectors } from '../../../../store';
|
||||
|
@ -37,10 +43,6 @@ import { useDeepEqualSelector } from '../../../../../common/hooks/use_selector';
|
|||
import { DocumentEventTypes } from '../../../../../common/lib/telemetry';
|
||||
import { isFullScreen } from '../../helpers';
|
||||
|
||||
const FullScreenButtonIcon = styled(EuiButtonIcon)`
|
||||
margin: 4px 0 4px 0;
|
||||
`;
|
||||
|
||||
interface NavigationProps {
|
||||
fullScreen: boolean;
|
||||
globalFullScreen: boolean;
|
||||
|
@ -62,6 +64,8 @@ const NavigationComponent: React.FC<NavigationProps> = ({
|
|||
graphEventId,
|
||||
activeTab,
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const title = () => {
|
||||
if (isActiveTimelines) {
|
||||
return activeTab === TimelineTabs.graph ? i18n.CLOSE_ANALYZER : i18n.CLOSE_SESSION;
|
||||
|
@ -81,10 +85,10 @@ const NavigationComponent: React.FC<NavigationProps> = ({
|
|||
{title()}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
{isActiveTimelines === false && (
|
||||
{!isActiveTimelines && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={fullScreen ? EXIT_FULL_SCREEN : FULL_SCREEN}>
|
||||
<FullScreenButtonIcon
|
||||
<EuiToolTip content={fullScreen ? EXIT_FULL_SCREEN : i18n.FULL_SCREEN}>
|
||||
<EuiButtonIcon
|
||||
aria-label={
|
||||
isFullScreen({
|
||||
globalFullScreen,
|
||||
|
@ -92,13 +96,16 @@ const NavigationComponent: React.FC<NavigationProps> = ({
|
|||
timelineFullScreen,
|
||||
})
|
||||
? EXIT_FULL_SCREEN
|
||||
: FULL_SCREEN
|
||||
: i18n.FULL_SCREEN
|
||||
}
|
||||
display={fullScreen ? 'fill' : 'empty'}
|
||||
color="primary"
|
||||
data-test-subj="full-screen"
|
||||
iconType="fullScreen"
|
||||
onClick={toggleFullScreen}
|
||||
css={css`
|
||||
margin: ${euiTheme.size.xs} 0;
|
||||
`}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { EuiDataGridControlColumn } from '@elastic/eui';
|
||||
import { TestProviders } from '../../../../../common/mock';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useLicense } from '../../../../../common/hooks/use_license';
|
||||
import { useTimelineControlColumn } from './use_timeline_control_columns';
|
||||
import type { ColumnHeaderOptions } from '../../../../../../common/types/timeline/columns';
|
||||
import { TimelineId } from '@kbn/timelines-plugin/public/store/timeline';
|
||||
import { TimelineTabs } from '../../../../../../common/types';
|
||||
|
||||
jest.mock('../../../../../common/hooks/use_license', () => ({
|
||||
useLicense: jest.fn().mockReturnValue({
|
||||
|
@ -22,19 +21,6 @@ jest.mock('../../../../../common/hooks/use_license', () => ({
|
|||
const useLicenseMock = useLicense as jest.Mock;
|
||||
|
||||
describe('useTimelineControlColumns', () => {
|
||||
const mockColumns: ColumnHeaderOptions[] = [
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: 'source.ip',
|
||||
initialWidth: 150,
|
||||
},
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: 'agent.type',
|
||||
initialWidth: 150,
|
||||
},
|
||||
];
|
||||
|
||||
const refetchMock = jest.fn();
|
||||
|
||||
describe('leadingControlColumns', () => {
|
||||
|
@ -42,10 +28,7 @@ describe('useTimelineControlColumns', () => {
|
|||
const { result } = renderHook(
|
||||
() =>
|
||||
useTimelineControlColumn({
|
||||
columns: mockColumns,
|
||||
sort: [],
|
||||
timelineId: TimelineId.test,
|
||||
activeTab: TimelineTabs.query,
|
||||
refetch: refetchMock,
|
||||
events: [],
|
||||
pinnedEventIds: {},
|
||||
|
@ -65,10 +48,7 @@ describe('useTimelineControlColumns', () => {
|
|||
const { result } = renderHook(
|
||||
() =>
|
||||
useTimelineControlColumn({
|
||||
columns: mockColumns,
|
||||
sort: [],
|
||||
timelineId: TimelineId.test,
|
||||
activeTab: TimelineTabs.query,
|
||||
refetch: refetchMock,
|
||||
events: [],
|
||||
pinnedEventIds: {},
|
||||
|
@ -89,10 +69,7 @@ describe('useTimelineControlColumns', () => {
|
|||
const { result } = renderHook(
|
||||
() =>
|
||||
useTimelineControlColumn({
|
||||
columns: mockColumns,
|
||||
sort: [],
|
||||
timelineId: TimelineId.test,
|
||||
activeTab: TimelineTabs.query,
|
||||
refetch: refetchMock,
|
||||
events: [],
|
||||
pinnedEventIds: {},
|
||||
|
|
|
@ -5,29 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useMemo, useEffect } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import type { EuiDataGridCellValueElementProps } from '@elastic/eui';
|
||||
import type { SortColumnTable } from '@kbn/securitysolution-data-table';
|
||||
import type { TimelineItem } from '@kbn/timelines-plugin/common';
|
||||
import { JEST_ENVIRONMENT } from '../../../../../../common/constants';
|
||||
import { useLicense } from '../../../../../common/hooks/use_license';
|
||||
import { SourcererScopeName } from '../../../../../sourcerer/store/model';
|
||||
import { useSourcererDataView } from '../../../../../sourcerer/containers';
|
||||
import { getDefaultControlColumn } from '../../body/control_columns';
|
||||
import type { UnifiedActionProps } from '../../unified_components/data_table/control_column_cell_render';
|
||||
import type { TimelineTabs } from '../../../../../../common/types/timeline';
|
||||
import { HeaderActions } from '../../../../../common/components/header_actions/header_actions';
|
||||
import { TimelineControlColumnCellRender } from '../../unified_components/data_table/control_column_cell_render';
|
||||
import type { ColumnHeaderOptions } from '../../../../../../common/types';
|
||||
import { useTimelineColumns } from './use_timeline_columns';
|
||||
import type { UnifiedTimelineDataGridCellContext } from '../../types';
|
||||
import { useTimelineUnifiedDataTableContext } from '../../unified_components/data_table/use_timeline_unified_data_table_context';
|
||||
|
||||
interface UseTimelineControlColumnArgs {
|
||||
columns: ColumnHeaderOptions[];
|
||||
sort: SortColumnTable[];
|
||||
timelineId: string;
|
||||
activeTab: TimelineTabs;
|
||||
refetch: () => void;
|
||||
events: TimelineItem[];
|
||||
pinnedEventIds: Record<string, boolean>;
|
||||
|
@ -38,23 +27,16 @@ interface UseTimelineControlColumnArgs {
|
|||
const EMPTY_STRING_ARRAY: string[] = [];
|
||||
|
||||
const noOp = () => {};
|
||||
const noSelectAll = ({ isSelected }: { isSelected: boolean }) => {};
|
||||
export const useTimelineControlColumn = ({
|
||||
columns,
|
||||
sort,
|
||||
timelineId,
|
||||
activeTab,
|
||||
refetch,
|
||||
events,
|
||||
pinnedEventIds,
|
||||
eventIdToNoteIds,
|
||||
onToggleShowNotes,
|
||||
}: UseTimelineControlColumnArgs) => {
|
||||
const { browserFields } = useSourcererDataView(SourcererScopeName.timeline);
|
||||
|
||||
const isEnterprisePlus = useLicense().isEnterprise();
|
||||
const ACTION_BUTTON_COUNT = useMemo(() => (isEnterprisePlus ? 6 : 5), [isEnterprisePlus]);
|
||||
const { localColumns } = useTimelineColumns(columns);
|
||||
const ACTION_BUTTON_COUNT = useMemo(() => (isEnterprisePlus ? 5 : 4), [isEnterprisePlus]);
|
||||
|
||||
const RowCellRender = useMemo(
|
||||
() =>
|
||||
|
@ -108,39 +90,10 @@ export const useTimelineControlColumn = ({
|
|||
[events, timelineId, refetch, pinnedEventIds, eventIdToNoteIds, onToggleShowNotes]
|
||||
);
|
||||
|
||||
// We need one less when the unified components are enabled because the document expand is provided by the unified data table
|
||||
const UNIFIED_COMPONENTS_ACTION_BUTTON_COUNT = ACTION_BUTTON_COUNT - 1;
|
||||
return useMemo(() => {
|
||||
return getDefaultControlColumn(UNIFIED_COMPONENTS_ACTION_BUTTON_COUNT).map((x) => ({
|
||||
return getDefaultControlColumn(ACTION_BUTTON_COUNT).map((x) => ({
|
||||
...x,
|
||||
headerCellRender: function HeaderCellRender(props: UnifiedActionProps) {
|
||||
return (
|
||||
<HeaderActions
|
||||
width={x.width}
|
||||
browserFields={browserFields}
|
||||
columnHeaders={localColumns}
|
||||
isEventViewer={false}
|
||||
isSelectAllChecked={false}
|
||||
onSelectAll={noSelectAll}
|
||||
showEventsSelect={false}
|
||||
showSelectAllCheckbox={false}
|
||||
showFullScreenToggle={false}
|
||||
sort={sort}
|
||||
tabType={activeTab}
|
||||
{...props}
|
||||
timelineId={timelineId}
|
||||
/>
|
||||
);
|
||||
},
|
||||
rowCellRender: JEST_ENVIRONMENT ? RowCellRender : React.memo(RowCellRender),
|
||||
}));
|
||||
}, [
|
||||
UNIFIED_COMPONENTS_ACTION_BUTTON_COUNT,
|
||||
browserFields,
|
||||
localColumns,
|
||||
sort,
|
||||
activeTab,
|
||||
timelineId,
|
||||
RowCellRender,
|
||||
]);
|
||||
}, [ACTION_BUTTON_COUNT, RowCellRender]);
|
||||
};
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { BrowserFields, ColumnHeaderOptions } from '@kbn/timelines-plugin/common';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import type { ControlColumnProps } from '../../../../../../common/types';
|
||||
import type { SortColumnTimeline as Sort } from '../../../../../../common/types/timeline';
|
||||
import type { TimelineItem } from '../../../../../../common/search_strategy';
|
||||
import type { inputsModel } from '../../../../../common/store';
|
||||
import { getColumnHeaders } from '../../body/column_headers/helpers';
|
||||
|
||||
interface TimerangeSimilarityProps {
|
||||
end: inputsModel.InputsRange['timerange']['to'];
|
||||
start: inputsModel.InputsRange['timerange']['from'];
|
||||
|
@ -25,12 +25,8 @@ export const isTimerangeSame = (
|
|||
prevProps.start === nextProps.start &&
|
||||
prevProps.timerangeKind === nextProps.timerangeKind;
|
||||
|
||||
export const TIMELINE_EMPTY_EVENTS: TimelineItem[] = [];
|
||||
|
||||
export const TIMELINE_NO_SORTING: Sort[] = [];
|
||||
|
||||
export const timelineEmptyTrailingControlColumns: ControlColumnProps[] = [];
|
||||
|
||||
export const memoizedGetTimelineColumnHeaders: (
|
||||
headers: ColumnHeaderOptions[],
|
||||
browserFields: BrowserFields,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue