[7.x] [Embeddable] Export CSV action for Lens embeddables in dashboard (#83654) (#84885)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Marco Liberati 2020-12-03 16:45:18 +01:00 committed by GitHub
parent a2b98af354
commit 896187eab8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 495 additions and 26 deletions

View file

@ -11,5 +11,5 @@
<b>Signature:</b>
```typescript
readonly addTriggerAction: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">) => void;
readonly addTriggerAction: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">) => void;
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
readonly getAction: <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">;
readonly getAction: <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
readonly getTriggerActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[];
readonly getTriggerActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[];
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
readonly getTriggerCompatibleActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[]>;
readonly getTriggerCompatibleActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[]>;
```

View file

@ -21,19 +21,19 @@ export declare class UiActionsService
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | <code>ActionRegistry</code> | |
| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, action: ActionDefinition&lt;TriggerContextMapping[T]&gt; &#124; Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot;&gt;) =&gt; void</code> | <code>addTriggerAction</code> is similar to <code>attachAction</code> as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.<code>addTriggerAction</code> also infers better typing of the <code>action</code> argument. |
| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, action: ActionDefinition&lt;TriggerContextMapping[T]&gt; &#124; Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot; &#124; &quot;ACTION_EXPORT_CSV&quot;&gt;) =&gt; void</code> | <code>addTriggerAction</code> is similar to <code>attachAction</code> as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.<code>addTriggerAction</code> also infers better typing of the <code>action</code> argument. |
| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, actionId: string) =&gt; void</code> | |
| [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | <code>() =&gt; void</code> | Removes all registered triggers and actions. |
| [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | <code>(triggerId: TriggerId, actionId: string) =&gt; void</code> | |
| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, context: TriggerContext&lt;T&gt;) =&gt; Promise&lt;void&gt;</code> | |
| [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) | | <code>UiActionsExecutionService</code> | |
| [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) | | <code>() =&gt; UiActionsService</code> | "Fork" a separate instance of <code>UiActionsService</code> that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of <code>UiActionsService</code> are only available within this instance. |
| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <code>&lt;T extends ActionDefinition&lt;{}&gt;&gt;(id: string) =&gt; Action&lt;ActionContext&lt;T&gt;, &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot;&gt;</code> | |
| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <code>&lt;T extends ActionDefinition&lt;{}&gt;&gt;(id: string) =&gt; Action&lt;ActionContext&lt;T&gt;, &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot; &#124; &quot;ACTION_EXPORT_CSV&quot;&gt;</code> | |
| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T) =&gt; TriggerContract&lt;T&gt;</code> | |
| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T) =&gt; Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot;&gt;[]</code> | |
| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, context: TriggerContextMapping[T]) =&gt; Promise&lt;Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot;&gt;[]&gt;</code> | |
| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T) =&gt; Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot; &#124; &quot;ACTION_EXPORT_CSV&quot;&gt;[]</code> | |
| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <code>&lt;T extends &quot;&quot; &#124; &quot;SELECT_RANGE_TRIGGER&quot; &#124; &quot;VALUE_CLICK_TRIGGER&quot; &#124; &quot;FILTER_TRIGGER&quot; &#124; &quot;VISUALIZE_FIELD_TRIGGER&quot; &#124; &quot;VISUALIZE_GEO_FIELD_TRIGGER&quot; &#124; &quot;CONTEXT_MENU_TRIGGER&quot; &#124; &quot;PANEL_BADGE_TRIGGER&quot; &#124; &quot;PANEL_NOTIFICATION_TRIGGER&quot;&gt;(triggerId: T, context: TriggerContextMapping[T]) =&gt; Promise&lt;Action&lt;TriggerContextMapping[T], &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot; &#124; &quot;ACTION_EXPORT_CSV&quot;&gt;[]&gt;</code> | |
| [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) | | <code>(actionId: string) =&gt; boolean</code> | |
| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <code>&lt;A extends ActionDefinition&lt;{}&gt;&gt;(definition: A) =&gt; Action&lt;ActionContext&lt;A&gt;, &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot;&gt;</code> | |
| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <code>&lt;A extends ActionDefinition&lt;{}&gt;&gt;(definition: A) =&gt; Action&lt;ActionContext&lt;A&gt;, &quot;&quot; &#124; &quot;ACTION_VISUALIZE_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_GEO_FIELD&quot; &#124; &quot;ACTION_VISUALIZE_LENS_FIELD&quot; &#124; &quot;ACTION_GLOBAL_APPLY_FILTER&quot; &#124; &quot;ACTION_SELECT_RANGE&quot; &#124; &quot;ACTION_VALUE_CLICK&quot; &#124; &quot;ACTION_CUSTOMIZE_PANEL&quot; &#124; &quot;ACTION_ADD_PANEL&quot; &#124; &quot;openInspector&quot; &#124; &quot;deletePanel&quot; &#124; &quot;editPanel&quot; &#124; &quot;togglePanel&quot; &#124; &quot;replacePanel&quot; &#124; &quot;clonePanel&quot; &#124; &quot;addToFromLibrary&quot; &#124; &quot;unlinkFromLibrary&quot; &#124; &quot;ACTION_LIBRARY_NOTIFICATION&quot; &#124; &quot;ACTION_EXPORT_CSV&quot;&gt;</code> | |
| [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) | | <code>(trigger: Trigger) =&gt; void</code> | |
| [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) | | <code>TriggerRegistry</code> | |
| [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) | | <code>TriggerToActionsRegistry</code> | |

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
readonly registerAction: <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">;
readonly registerAction: <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
```

View file

@ -0,0 +1,15 @@
[float]
[role="xpack"]
[[download_csv]]
=== Download CSV
To download the underlying data of the Lens panels on your dashboard, you can use the *Download as CSV* option.
TIP: The *Download as CSV* option supports multiple CSV file downloads from the same Lens visualization out of the box, if configured: for instance with multiple layers on a bar chart.
To use the *Download as CSV* option:
* Click the from the panel menu, then click *Download as CSV*.
+
[role="screenshot"]
image::images/download_csv_context_menu.png[Download as CSV from panel context menu]

View file

@ -16,3 +16,4 @@ The data that displays depends on the element that you inspect.
image:images/Dashboard_inspect.png[Inspect in dashboard]
include::explore-underlying-data.asciidoc[]
include::download-underlying-data.asciidoc[]

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View file

@ -9,9 +9,10 @@
"urlForwarding",
"navigation",
"uiActions",
"savedObjects"
"savedObjects",
"share"
],
"optionalPlugins": ["home", "share", "usageCollection", "savedObjectsTaggingOss"],
"optionalPlugins": ["home", "usageCollection", "savedObjectsTaggingOss"],
"server": true,
"ui": true,
"requiredBundles": ["kibanaUtils", "kibanaReact", "home"]

View file

@ -0,0 +1,134 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/
import { CoreStart } from 'kibana/public';
import { isErrorEmbeddable, IContainer, ErrorEmbeddable } from '../../embeddable_plugin';
import { DashboardContainer } from '../../application/embeddable';
import { getSampleDashboardInput, getSampleDashboardPanel } from '../../application/test_helpers';
import {
ContactCardEmbeddable,
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
ContactCardExportableEmbeddableFactory,
CONTACT_CARD_EXPORTABLE_EMBEDDABLE,
} from '../../embeddable_plugin_test_samples';
import { coreMock } from '../../../../../core/public/mocks';
import { ExportCSVAction } from './export_csv_action';
import { embeddablePluginMock } from '../../../../embeddable/public/mocks';
import { DataPublicPluginStart } from '../../../../data/public/types';
import { dataPluginMock } from '../../../../data/public/mocks';
import { LINE_FEED_CHARACTER } from 'src/plugins/data/common/exports/export_csv';
describe('Export CSV action', () => {
const { setup, doStart } = embeddablePluginMock.createInstance();
setup.registerEmbeddableFactory(
CONTACT_CARD_EXPORTABLE_EMBEDDABLE,
new ContactCardExportableEmbeddableFactory((() => null) as any, {} as any)
);
const start = doStart();
let container: DashboardContainer;
let embeddable: ContactCardEmbeddable;
let coreStart: CoreStart;
let dataMock: jest.Mocked<DataPublicPluginStart>;
beforeEach(async () => {
coreStart = coreMock.createStart();
coreStart.savedObjects.client = {
...coreStart.savedObjects.client,
get: jest.fn().mockImplementation(() => ({ attributes: { title: 'Holy moly' } })),
find: jest.fn().mockImplementation(() => ({ total: 15 })),
create: jest.fn().mockImplementation(() => ({ id: 'brandNewSavedObject' })),
};
const options = {
ExitFullScreenButton: () => null,
SavedObjectFinder: () => null,
application: {} as any,
embeddable: start,
inspector: {} as any,
notifications: {} as any,
overlays: coreStart.overlays,
savedObjectMetaData: {} as any,
uiActions: {} as any,
};
const input = getSampleDashboardInput({
panels: {
'123': getSampleDashboardPanel<ContactCardEmbeddableInput>({
explicitInput: { firstName: 'Kibanana', id: '123' },
type: CONTACT_CARD_EXPORTABLE_EMBEDDABLE,
}),
},
});
container = new DashboardContainer(input, options);
dataMock = dataPluginMock.createStartContract();
const contactCardEmbeddable = await container.addNewEmbeddable<
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
ContactCardEmbeddable
>(CONTACT_CARD_EXPORTABLE_EMBEDDABLE, {
firstName: 'Kibana',
});
if (isErrorEmbeddable(contactCardEmbeddable)) {
throw new Error('Failed to create embeddable');
} else {
embeddable = contactCardEmbeddable;
}
});
test('Download is incompatible with embeddables without getInspectorAdapters implementation', async () => {
const action = new ExportCSVAction({ core: coreStart, data: dataMock });
const errorEmbeddable = new ErrorEmbeddable(
'Wow what an awful error',
{ id: ' 404' },
embeddable.getRoot() as IContainer
);
expect(await action.isCompatible({ embeddable: errorEmbeddable })).toBe(false);
});
test('Should download a compatible Embeddable', async () => {
const action = new ExportCSVAction({ core: coreStart, data: dataMock });
const result = ((await action.execute({ embeddable, asString: true })) as unknown) as
| undefined
| Record<string, { content: string; type: string }>;
expect(result).toEqual({
'Hello Kibana.csv': {
content: `First Name,Last Name${LINE_FEED_CHARACTER}Kibana,undefined${LINE_FEED_CHARACTER}`,
type: 'text/plain;charset=utf-8',
},
});
});
test('Should not download incompatible Embeddable', async () => {
const action = new ExportCSVAction({ core: coreStart, data: dataMock });
const errorEmbeddable = new ErrorEmbeddable(
'Wow what an awful error',
{ id: ' 404' },
embeddable.getRoot() as IContainer
);
const result = ((await action.execute({
embeddable: errorEmbeddable,
asString: true,
})) as unknown) as undefined | Record<string, string>;
expect(result).toBeUndefined();
});
});

View file

@ -0,0 +1,138 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/
import { i18n } from '@kbn/i18n';
import { Datatable } from 'src/plugins/expressions/public';
import { FormatFactory } from '../../../../data/common/field_formats/utils';
import { DataPublicPluginStart, exporters } from '../../../../data/public';
import { downloadMultipleAs } from '../../../../share/public';
import { Adapters, IEmbeddable } from '../../../../embeddable/public';
import { ActionByType } from '../../../../ui_actions/public';
import { CoreStart } from '../../../../../core/public';
export const ACTION_EXPORT_CSV = 'ACTION_EXPORT_CSV';
export interface Params {
core: CoreStart;
data: DataPublicPluginStart;
}
export interface ExportContext {
embeddable?: IEmbeddable;
// used for testing
asString?: boolean;
}
/**
* This is "Export CSV" action which appears in the context
* menu of a dashboard panel.
*/
export class ExportCSVAction implements ActionByType<typeof ACTION_EXPORT_CSV> {
public readonly id = ACTION_EXPORT_CSV;
public readonly type = ACTION_EXPORT_CSV;
public readonly order = 5;
constructor(protected readonly params: Params) {}
public getIconType() {
return 'exportAction';
}
public readonly getDisplayName = (context: ExportContext): string =>
i18n.translate('dashboard.actions.DownloadCreateDrilldownAction.displayName', {
defaultMessage: 'Download as CSV',
});
public async isCompatible(context: ExportContext): Promise<boolean> {
return !!this.hasDatatableContent(context.embeddable?.getInspectorAdapters?.());
}
private hasDatatableContent = (adapters: Adapters | undefined) => {
return Object.keys(adapters?.tables || {}).length > 0;
};
private getFormatter = (): FormatFactory | undefined => {
if (this.params.data) {
return this.params.data.fieldFormats.deserialize;
}
};
private getDataTableContent = (adapters: Adapters | undefined) => {
if (this.hasDatatableContent(adapters)) {
return adapters?.tables;
}
return;
};
private exportCSV = async (context: ExportContext) => {
const formatFactory = this.getFormatter();
// early exit if not formatter is available
if (!formatFactory) {
return;
}
const tableAdapters = this.getDataTableContent(
context?.embeddable?.getInspectorAdapters()
) as Record<string, Datatable>;
if (tableAdapters) {
const datatables = Object.values(tableAdapters);
const content = datatables.reduce<Record<string, { content: string; type: string }>>(
(memo, datatable, i) => {
// skip empty datatables
if (datatable) {
const postFix = datatables.length > 1 ? `-${i + 1}` : '';
const untitledFilename = i18n.translate(
'dashboard.actions.downloadOptionsUnsavedFilename',
{
defaultMessage: 'unsaved',
}
);
memo[`${context!.embeddable!.getTitle() || untitledFilename}${postFix}.csv`] = {
content: exporters.datatableToCSV(datatable, {
csvSeparator: this.params.core.uiSettings.get('csv:separator', ','),
quoteValues: this.params.core.uiSettings.get('csv:quoteValues', true),
formatFactory,
}),
type: exporters.CSV_MIME_TYPE,
};
}
return memo;
},
{}
);
// useful for testing
if (context.asString) {
return (content as unknown) as Promise<void>;
}
if (content) {
return downloadMultipleAs(content);
}
}
};
public async execute(context: ExportContext): Promise<void> {
// make it testable: type here will be forced
return await this.exportCSV(context);
}
}

View file

@ -47,3 +47,4 @@ export {
LibraryNotificationAction,
ACTION_LIBRARY_NOTIFICATION,
} from './library_notification_action';
export { ExportContext, ExportCSVAction, ACTION_EXPORT_CSV } from './export_csv_action';

View file

@ -101,6 +101,11 @@ import { DashboardConstants } from './dashboard_constants';
import { addEmbeddableToDashboardUrl } from './url_utils/url_helper';
import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder';
import { UrlGeneratorState } from '../../share/public';
import {
ACTION_EXPORT_CSV,
ExportContext,
ExportCSVAction,
} from './application/actions/export_csv_action';
declare module '../../share/public' {
export interface UrlGeneratorStateMapping {
@ -160,6 +165,7 @@ declare module '../../../plugins/ui_actions/public' {
[ACTION_ADD_TO_LIBRARY]: AddToLibraryActionContext;
[ACTION_UNLINK_FROM_LIBRARY]: UnlinkFromLibraryActionContext;
[ACTION_LIBRARY_NOTIFICATION]: LibraryNotificationActionContext;
[ACTION_EXPORT_CSV]: ExportContext;
}
}
@ -414,7 +420,7 @@ export class DashboardPlugin
public start(core: CoreStart, plugins: StartDependencies): DashboardStart {
const { notifications } = core;
const { uiActions } = plugins;
const { uiActions, data, share } = plugins;
const SavedObjectFinder = getSavedObjectFinder(core.savedObjects, core.uiSettings);
@ -431,6 +437,11 @@ export class DashboardPlugin
uiActions.registerAction(clonePanelAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, clonePanelAction.id);
if (share) {
const ExportCSVPlugin = new ExportCSVAction({ core, data });
uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, ExportCSVPlugin);
}
if (this.dashboardFeatureFlagConfig?.allowByValueEmbeddables) {
const addToLibraryAction = new AddToLibraryAction({ toasts: notifications.toasts });
uiActions.registerAction(addToLibraryAction);

View file

@ -22,7 +22,7 @@
import { FormatFactory } from 'src/plugins/data/common/field_formats/utils';
import { Datatable } from 'src/plugins/expressions';
const LINE_FEED_CHARACTER = '\r\n';
export const LINE_FEED_CHARACTER = '\r\n';
const nonAlphaNumRE = /[^a-zA-Z0-9]/;
const allDoubleQuoteRE = /"/g;
export const CSV_MIME_TYPE = 'text/plain;charset=utf-8';

View file

@ -0,0 +1,44 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/
import { ContactCardEmbeddable } from './contact_card_embeddable';
export class ContactCardExportableEmbeddable extends ContactCardEmbeddable {
public getInspectorAdapters = () => {
return {
tables: {
layer1: {
type: 'datatable',
columns: [
{ id: 'firstName', name: 'First Name' },
{ id: 'originalLastName', name: 'Last Name' },
],
rows: [
{
firstName: this.getInput().firstName,
orignialLastName: this.getInput().lastName,
},
],
},
},
};
};
}
export const CONTACT_EXPORTABLE_USER_TRIGGER = 'CONTACT_EXPORTABLE_USER_TRIGGER';

View file

@ -0,0 +1,85 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
import { UiActionsStart } from 'src/plugins/ui_actions/public';
import { CoreStart } from 'src/core/public';
import { toMountPoint } from '../../../../../../kibana_react/public';
import { EmbeddableFactoryDefinition } from '../../../embeddables';
import { Container } from '../../../containers';
import { ContactCardEmbeddableInput } from './contact_card_embeddable';
import { ContactCardExportableEmbeddable } from './contact_card_exportable_embeddable';
import { ContactCardInitializer } from './contact_card_initializer';
export const CONTACT_CARD_EXPORTABLE_EMBEDDABLE = 'CONTACT_CARD_EXPORTABLE_EMBEDDABLE';
export class ContactCardExportableEmbeddableFactory
implements EmbeddableFactoryDefinition<ContactCardEmbeddableInput> {
public readonly type = CONTACT_CARD_EXPORTABLE_EMBEDDABLE;
constructor(
private readonly execTrigger: UiActionsStart['executeTriggerActions'],
private readonly overlays: CoreStart['overlays']
) {}
public async isEditable() {
return true;
}
public getDisplayName() {
return i18n.translate('embeddableApi.samples.contactCard.displayName', {
defaultMessage: 'contact card',
});
}
public getExplicitInput = (): Promise<Partial<ContactCardEmbeddableInput>> => {
return new Promise((resolve) => {
const modalSession = this.overlays.openModal(
toMountPoint(
<ContactCardInitializer
onCancel={() => {
modalSession.close();
// @ts-expect-error
resolve(undefined);
}}
onCreate={(input: { firstName: string; lastName?: string }) => {
modalSession.close();
resolve(input);
}}
/>
),
{
'data-test-subj': 'createContactCardEmbeddable',
}
);
});
};
public create = async (initialInput: ContactCardEmbeddableInput, parent?: Container) => {
return new ContactCardExportableEmbeddable(
initialInput,
{
execAction: this.execTrigger,
},
parent
);
};
}

View file

@ -20,5 +20,7 @@
export * from './contact_card';
export * from './contact_card_embeddable';
export * from './contact_card_embeddable_factory';
export * from './contact_card_exportable_embeddable';
export * from './contact_card_exportable_embeddable_factory';
export * from './contact_card_initializer';
export * from './slow_contact_card_embeddable_factory';

View file

@ -234,7 +234,7 @@ export class UiActionsService {
//
// (undocumented)
protected readonly actions: ActionRegistry;
readonly addTriggerAction: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: UiActionsActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">) => void;
readonly addTriggerAction: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: UiActionsActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">) => void;
// (undocumented)
readonly attachAction: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, actionId: string) => void;
readonly clear: () => void;
@ -248,21 +248,21 @@ export class UiActionsService {
readonly executionService: UiActionsExecutionService;
readonly fork: () => UiActionsService;
// (undocumented)
readonly getAction: <T extends UiActionsActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">;
readonly getAction: <T extends UiActionsActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
// Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts
//
// (undocumented)
readonly getTrigger: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => TriggerContract<T>;
// (undocumented)
readonly getTriggerActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[];
readonly getTriggerActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[];
// (undocumented)
readonly getTriggerCompatibleActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[]>;
readonly getTriggerCompatibleActions: <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[]>;
// (undocumented)
readonly hasAction: (actionId: string) => boolean;
// Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts
//
// (undocumented)
readonly registerAction: <A extends UiActionsActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">;
readonly registerAction: <A extends UiActionsActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
// (undocumented)
readonly registerTrigger: (trigger: Trigger) => void;
// Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts

View file

@ -44,6 +44,7 @@ import { IndexPatternsContract } from '../../../../../../src/plugins/data/public
import { getEditPath, DOC_TYPE } from '../../../common';
import { IBasePath } from '../../../../../../src/core/public';
import { LensAttributeService } from '../../lens_attribute_service';
import { LensInspectorAdapters } from '../types';
export type LensSavedObjectAttributes = Omit<Document, 'savedObjectId' | 'type'>;
@ -84,6 +85,7 @@ export class Embeddable
private subscription: Subscription;
private autoRefreshFetchSubscription: Subscription;
private isInitialized = false;
private activeData: LensInspectorAdapters | undefined;
private externalSearchContext: {
timeRange?: TimeRange;
@ -131,6 +133,10 @@ export class Embeddable
}
}
public getInspectorAdapters() {
return this.activeData;
}
async initializeSavedVis(input: LensEmbeddableInput) {
const attributes:
| LensSavedObjectAttributes
@ -175,6 +181,13 @@ export class Embeddable
}
}
private updateActiveData = (
data: unknown,
inspectorAdapters?: LensInspectorAdapters | undefined
) => {
this.activeData = inspectorAdapters;
};
/**
*
* @param {HTMLElement} domNode
@ -194,6 +207,7 @@ export class Embeddable
variables={input.palette ? { theme: { palette: input.palette } } : {}}
searchSessionId={this.input.searchSessionId}
handleEvent={this.handleEvent}
onData$={this.updateActiveData}
renderMode={input.renderMode}
/>,
domNode

View file

@ -15,6 +15,7 @@ import {
import { ExecutionContextSearch } from 'src/plugins/data/public';
import { RenderMode } from 'src/plugins/expressions';
import { getOriginalRequestErrorMessage } from '../error_helper';
import { LensInspectorAdapters } from '../types';
export interface ExpressionWrapperProps {
ExpressionRenderer: ReactExpressionRendererType;
@ -23,6 +24,7 @@ export interface ExpressionWrapperProps {
searchContext: ExecutionContextSearch;
searchSessionId?: string;
handleEvent: (event: ExpressionRendererEvent) => void;
onData$: (data: unknown, inspectorAdapters?: LensInspectorAdapters | undefined) => void;
renderMode?: RenderMode;
}
@ -33,6 +35,7 @@ export function ExpressionWrapper({
variables,
handleEvent,
searchSessionId,
onData$,
renderMode,
}: ExpressionWrapperProps) {
return (
@ -60,6 +63,7 @@ export function ExpressionWrapper({
expression={expression}
searchContext={searchContext}
searchSessionId={searchSessionId}
onData$={onData$}
renderMode={renderMode}
renderError={(errorMessage, error) => (
<div data-test-subj="expression-renderer-error">

View file

@ -5,13 +5,16 @@
*/
import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public';
import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public';
import { DashboardStart } from 'src/plugins/dashboard/public';
import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public';
import { VisualizationsSetup, VisualizationsStart } from 'src/plugins/visualizations/public';
import { NavigationPublicPluginStart } from 'src/plugins/navigation/public';
import { UrlForwardingSetup } from 'src/plugins/url_forwarding/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public';
import { EmbeddableSetup, EmbeddableStart } from '../../../../src/plugins/embeddable/public';
import { DashboardStart } from '../../../../src/plugins/dashboard/public';
import { ExpressionsSetup, ExpressionsStart } from '../../../../src/plugins/expressions/public';
import {
VisualizationsSetup,
VisualizationsStart,
} from '../../../../src/plugins/visualizations/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';
import { UrlForwardingSetup } from '../../../../src/plugins/url_forwarding/public';
import { GlobalSearchPluginSetup } from '../../global_search/public';
import { ChartsPluginSetup, ChartsPluginStart } from '../../../../src/plugins/charts/public';
import { EditorFrameService } from './editor_frame_service';
@ -64,6 +67,7 @@ export interface LensPluginStartDependencies {
charts: ChartsPluginStart;
savedObjectsTagging?: SavedObjectTaggingPluginStart;
}
export class LensPlugin {
private datatableVisualization: DatatableVisualization;
private editorFrameService: EditorFrameService;

View file

@ -140,5 +140,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const hasGeoSrcFilter = await filterBar.hasFilter('geo.src', 'US', true, true);
expect(hasGeoSrcFilter).to.be(true);
});
it('CSV export action exists in panel context menu', async () => {
const ACTION_ID = 'ACTION_EXPORT_CSV';
const ACTION_TEST_SUBJ = `embeddablePanelAction-${ACTION_ID}`;
await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.clickNewDashboard();
await dashboardAddPanel.clickOpenAddPanel();
await dashboardAddPanel.filterEmbeddableNames('lnsPieVis');
await find.clickByButtonText('lnsPieVis');
await dashboardAddPanel.closeAddPanel();
await panelActions.openContextMenu();
await panelActions.clickContextMenuMoreItem();
await testSubjects.existOrFail(ACTION_TEST_SUBJ);
});
});
}