diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx index 8d031690e996c..f1f055160a3ca 100644 --- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx @@ -524,7 +524,6 @@ export class QueryStringInputUI extends Component {
- - +
@@ -11,10 +10,7 @@ i18n-default-message="Inspect" >
-
+
http://host:port/{{ selectedIndex.name }}/_graph/explore
-
- -
+
-
- +
+
+
+ +
diff --git a/x-pack/legacy/plugins/graph/public/components/_app.scss b/x-pack/legacy/plugins/graph/public/components/_app.scss index 8df55e5995034..cd29dc3a782c8 100644 --- a/x-pack/legacy/plugins/graph/public/components/_app.scss +++ b/x-pack/legacy/plugins/graph/public/components/_app.scss @@ -1,129 +1,91 @@ -.gphGraph__bar { - margin: 0px $euiSizeS $euiSizeS $euiSizeS; -} - -.gphAddData { - position: absolute; - right: 0; - bottom: 0; - height: calc(100% - 116px); - background-color: $euiPageBackgroundColor; - width: $euiSizeXXL * 10; - border-top: 1px solid $euiBorderColor; - z-index: $euiZNavigation; +@import "@elastic/eui/src/components/header/variables"; - &__body { - padding: $euiSize; +// variables +$sidebarWidth: $euiSizeXXL * 10; - .euiPanel { - margin-bottom: $euiSize; - } - .euiText { - margin-bottom: $euiSizeXS; - } - } +.gphGraph__workspace, +.gphGraph__workspace__inner { + position: relative; + flex-grow: 1; + display: flex; + flex-direction: column; +} - &__editNodeName + &__editNodeName { - margin-top: $euiSizeS; - } +.gphGraph__visContainer { + position: absolute; + top: 80px; + left: 0; + width: calc(100% - #{$sidebarWidth}); + height: 100%; - &__prependIcon { - display: flex; - width: $euiSize * 2; - align-items: center; - justify-content: center; - background: $euiColorLightShade; - border-right: 1px solid $euiBorderColor; + .gphVisualization { + height: 100%; } +} - &__circleIcon { - display: flex; - width: $euiSizeL; - height: $euiSizeL; - align-items: center; - justify-content: center; - border-radius: 50%; - - .gphLegacyIcon { - margin-right: 0; - text-align: center; - display: inline-flex; - width: auto; - font-size: 12px; - } - } +.gphGraph__bar { + padding: 0px $euiSizeS $euiSizeS $euiSizeS; + border-bottom: 1px solid $euiBorderColor; } -.gphAddData__header { +.gphGraph__mainWrapper { + flex-grow: 1; display: flex; - border-bottom: 1px solid $euiBorderColor; - padding: $euiSize 0; - - &__title { - flex: 1; - padding: 0 $euiSize; - } - - &__title, - &__toggleIcon { - padding: 0 $euiSize; - } + flex-direction: column; } +.gphGraph__openSidebar { + @include euiBottomShadowSmall; + position: absolute; + top: $euiSizeS; + right: $euiSizeXS; + background: $euiColorEmptyShade; + padding: $euiSizeXS; +} -.gphAddData__nodesArea { +.gphGraph__graphWrapper { + background-color: $euiColorEmptyShade; position: relative; - padding: $euiSize $euiSizeS; - border: $euiBorderThin; - border-radius: $euiBorderRadius; - margin-top: $euiSizeS; - margin-bottom: $euiSize; +} - > span { - margin-right: $euiSizeXS; +.gphGraphSidebar { + background-color: $euiPageBackgroundColor; + width: $sidebarWidth; + border-left: 1px solid $euiBorderColor; + overflow: hidden; - &:last-of-type { - margin-right: 0 - } + > * { + width: $sidebarWidth; } - span + span { - margin-top: $euiSizeXS; + &__header { + display: flex; + border-bottom: 1px solid $euiBorderColor; + padding: $euiSize 0; + } + &__title { + flex: 1; + padding: 0 $euiSize; } - &:hover, - &:focus { - .gphAddData__nodesArea__delete { - visibility: visible; - opacity: 1; - } + &__title, + &__toggleIcon { + padding: 0 $euiSize; } - &__delete { - @include euiBottomShadowSmall; - position: absolute; - top: 50%; - right: 0; - margin-right: -$euiSizeS; - margin-top: -$euiSizeM; - background: $euiColorEmptyShade; - padding: $euiSizeXS; - visibility: hidden; - opacity: 0; + &__body { + @include euiScrollBar; + padding-bottom: 0; /* 1 */ + flex-grow: 1; + flex-basis: 1px; /* Fixes scrolling for Firefox */ + overflow-y: auto; } -} -.gphAddData__nodesAddList { - box-sizing: border-box; + &__bodyOverflow { + padding: $euiSize; - .gphAddData__circleIcon { - margin-right: $euiSizeS; + > *:last-child { + margin-bottom: $euiSize; /* 1 */ + } } } - -.gphGraph__openSidebar { - @include euiBottomShadowSmall; - background: $euiColorEmptyShade; - padding: $euiSizeXS; -} - diff --git a/x-pack/legacy/plugins/graph/public/components/_index.scss b/x-pack/legacy/plugins/graph/public/components/_index.scss index a06209e7e4d34..a20d78e0f5f79 100644 --- a/x-pack/legacy/plugins/graph/public/components/_index.scss +++ b/x-pack/legacy/plugins/graph/public/components/_index.scss @@ -7,3 +7,4 @@ @import './settings/index'; @import './legacy_icon/index'; @import './field_manager/index'; +@import './add_data/index'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/add_data/_add_data_panel.scss b/x-pack/legacy/plugins/graph/public/components/add_data/_add_data_panel.scss new file mode 100644 index 0000000000000..e5929d36b4ee5 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/add_data/_add_data_panel.scss @@ -0,0 +1,135 @@ +.gphAddData { + width: $sidebarWidth; + border-top: 1px solid $euiBorderColor; + background-color: $euiPageBackgroundColor; + overflow: hidden; + + &__inner { + display: flex; + flex: 1; + flex-direction: column; + } + + &__body { + padding: $euiSize; + + .euiPanel { + margin-bottom: $euiSize; + } + .euiText { + margin-bottom: $euiSizeXS; + } + } + + &__editNodeName + &__editNodeName { + margin-top: $euiSizeS; + } + + &__prependIcon { + display: flex; + width: $euiSize * 2; + align-items: center; + justify-content: center; + background: $euiColorLightShade; + border-right: 1px solid $euiBorderColor; + } + + &__circleIcon { + display: flex; + width: $euiSizeL; + height: $euiSizeL; + align-items: center; + justify-content: center; + border-radius: 50%; + flex-shrink: 0; + + .gphLegacyIcon { + margin-right: 0; + text-align: center; + display: inline-flex; + width: auto; + font-size: 12px; + } + } +} + +.gphAddData__selectedNodesArea { + position: relative; + padding: $euiSize $euiSizeS; + border: $euiBorderThin; + border-radius: $euiBorderRadius; + margin-top: $euiSizeS; + margin-bottom: $euiSize; + + > span { + margin-right: $euiSizeXS; + + &:last-of-type { + margin-right: 0; + } + } + + span + span { + margin-top: $euiSizeXS; + } + + &:hover, + &:focus { + .gphAddData__selectedNodesArea__delete { + visibility: visible; + opacity: 1; + } + } + + &__delete { + @include euiBottomShadowSmall; + position: absolute; + top: 50%; + right: 0; + margin-right: -$euiSizeS; + margin-top: -$euiSizeM; + background: $euiColorEmptyShade; + padding: $euiSizeXS; + visibility: hidden; + opacity: 0; + } +} + +.gphAddData__nodesAddList { + @include euiScrollBar; + background: $euiColorLightestShade; + padding: $euiSizeS; + border-radius: $euiBorderRadius; + box-sizing: border-box; + max-height: $euiSizeXL * 10; + overflow-y: auto; + + .gphAddData__circleIcon { + margin-right: $euiSizeS; + } + + &__item { + background: $euiColorEmptyShade; + transition: box-shadow $euiAnimSpeedFast $euiAnimSlightResistance; + + &:hover { + @include euiBottomShadowSmall; + background: $euiColorEmptyShade !important; + } + + > button > span { + display: inline-flex; + flex: 1; + align-items: center; + } + } + &__itemText { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + &__itemIcon { + fill: $euiColorDarkShade; + } +} diff --git a/x-pack/legacy/plugins/graph/public/components/add_data/_index.scss b/x-pack/legacy/plugins/graph/public/components/add_data/_index.scss new file mode 100644 index 0000000000000..2e524691078f3 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/add_data/_index.scss @@ -0,0 +1 @@ +@import './add_data_panel'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/add_data/add_data_panel.tsx b/x-pack/legacy/plugins/graph/public/components/add_data/add_data_panel.tsx index 3575f638207a4..bccf4d90ad843 100644 --- a/x-pack/legacy/plugins/graph/public/components/add_data/add_data_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/add_data/add_data_panel.tsx @@ -10,7 +10,7 @@ import { EuiButtonIcon, EuiListGroup, EuiPanel, - EuiToolTip, + EuiIcon, EuiComboBox, EuiAccordion, EuiFlexGroup, @@ -20,12 +20,12 @@ import { EuiSpacer, EuiText, EuiTextAlign, + EuiListGroupItem, } from '@elastic/eui'; import { connect } from 'react-redux'; import { GraphState, metaDataSelector, selectedFieldsSelector } from '../../state_management'; import { SignificantSearchBar } from './significant_search_bar'; import { EditNodesPanel, NodeIcon } from '../edit_nodes_panel'; -import { LegacyIcon } from '../legacy_icon'; import { WorkspaceField } from '../../types'; import { iconChoices } from '../../helpers/style_choices'; @@ -76,227 +76,275 @@ function AddDataPanelComponent(props: any) { if (props.mode === 'edit') { return ; } + const significantVerticesNodesList = significantVertices.filter( + // filter out all vertices already added + vertex => + !workspace.nodes || + !workspace.nodes.some( + (workspaceNode: any) => + workspaceNode.data.term === vertex.term && workspaceNode.data.field === vertex.field + ) + ); + return ( -
-
- -

Add Data

-
+ + +
+ +

Add Data

+
- { - props.setSidebarOpen(false); - }} - /> -
- {workspace && ( -
- - - - - {(query || !props.selectedNodes || !props.selectedNodes.length > 0) && ( - { - setQuery(query); - }} - /> - )} - - {query ? ( -

- Based on current search query{' '} - setQuery(undefined)} - color="danger" - /> -

- ) : props.selectedNodes && props.selectedNodes.length > 0 ? ( - <> - -

Based on current selection of {props.selectedNodes.length} vertices:

-
-
- {props.selectedNodes.map(node => ( - - - - ))} - { - workspace.selectNone(); - props.notifyAngular(); + { + props.setSidebarOpen(false); + }} + /> +
+
+
+ {workspace && ( + + + + +

Add Significant vertices

+ + } + > + + {(query || !props.selectedNodes || !props.selectedNodes.length > 0) && ( + <> + { + setQuery(query); + }} + /> + + + )} + + {query ? ( +

+ Based on current search query{' '} + setQuery(undefined)} + color="danger" + /> +

+ ) : props.selectedNodes && props.selectedNodes.length > 0 ? ( + <> + +

+ Based on current selection of {props.selectedNodes.length} vertices: +

+
+ {/*
+ {props.selectedNodes.map(node => ( + + + + ))} + { + workspace.selectNone(); + props.notifyAngular(); + }} + /> +
*/} + + ) : ( + +

Based on vertices in the workspace

+
+ )} + + + + {significantVerticesNodesList.length > 0 ? ( + + {significantVerticesNodesList.map(vertex => ( + { + await workspace.addNodes([vertex]); + await loadInterestingNodes(workspace); + }} + label={ + <> + + + {`${vertex.field}: ${vertex.term}`} + + + + } + /> + ))} + + ) : ( +
No vertices to add
+ )} + + + + + { + await workspace.addNodes(significantVertices); + await loadInterestingNodes(workspace); }} - /> -
- - ) : ( - -

Based on vertices in the workspace

-
- )} - - !workspace.nodes || - !workspace.nodes.some( - (workspaceNode: any) => - workspaceNode.data.term === vertex.term && - workspaceNode.data.field === vertex.field - ) - ) - .map(vertex => ({ - label: `${vertex.field}: ${vertex.term}`, - icon: , - size: 's', - onClick: async () => { - await workspace.addNodes([vertex]); - await loadInterestingNodes(workspace); - }, - }))} - /> - - { - await workspace.addNodes(significantVertices); - await loadInterestingNodes(workspace); - }} + > + Add all + + + + + + + + +

Vertices by field

+ + } > - Add all - - -
-
-
- - - - ({ label: field.name }))} - selectedOptions={selectedField ? [{ label: selectedField.name }] : []} - onChange={choices => { - setSelectedField(props.fields.find(field => field.name === choices[0].label)); - }} - isClearable - /> - {selectedField && ( - <> - + ({ label: field.name }))} + selectedOptions={selectedField ? [{ label: selectedField.name }] : []} + onChange={choices => { + setSelectedField( + props.fields.find(field => field.name === choices[0].label) + ); }} - listItems={terms - .filter( - // filter out all vertices already added - vertex => - !workspace.nodes || - !workspace.nodes.some( - (workspaceNode: any) => - workspaceNode.data.term === vertex.term && - workspaceNode.data.field === vertex.field + isClearable + /> + {selectedField && ( + <> + + !workspace.nodes || + !workspace.nodes.some( + (workspaceNode: any) => + workspaceNode.data.term === vertex.term && + workspaceNode.data.field === vertex.field + ) ) - ) - .map(vertex => ({ - label: `${vertex.field}: ${vertex.term}`, - icon: , - size: 's', - onClick: async () => { - await workspace.addNodes([vertex]); + .map(vertex => ({ + label: `${vertex.field}: ${vertex.term}`, + icon: , + size: 's', + onClick: async () => { + await workspace.addNodes([vertex]); + workspace.getTermsForField(res => { + setTerms(res); + }, selectedField.name); + }, + }))} + /> + + { + await workspace.addNodes(terms); workspace.getTermsForField(res => { setTerms(res); }, selectedField.name); - }, - }))} + }} + > + Add all + + + )} + + + + + + +

Free vertex

+ + } + > + + { + setFreeField(e.target.value); + }} + />{' '} + ={' '} + { + setFreeTerm(e.target.value); + }} /> - { - await workspace.addNodes(terms); - workspace.getTermsForField(res => { - setTerms(res); - }, selectedField.name); + await workspace.addNodes([ + { + color: '#aaa', + icon: iconChoices[0], + field: freeField, + term: freeTerm, + alwaysKeep: true, + }, + ]); }} > - Add all + Add - - )} -
-
-
- - - - { - setFreeField(e.target.value); - }} - />{' '} - ={' '} - { - setFreeTerm(e.target.value); - }} - /> - { - await workspace.addNodes([ - { - color: '#aaa', - icon: iconChoices[0], - field: freeField, - term: freeTerm, - alwaysKeep: true, - }, - ]); - }} - > - Add - - - - - + + + + + )} +
- )} -
+ + ); } diff --git a/x-pack/legacy/plugins/graph/public/components/app.tsx b/x-pack/legacy/plugins/graph/public/components/app.tsx index 3c0e249db9e7f..a46d582b78865 100644 --- a/x-pack/legacy/plugins/graph/public/components/app.tsx +++ b/x-pack/legacy/plugins/graph/public/components/app.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButtonIcon, EuiSpacer } from '@elastic/eui'; +import { EuiButtonIcon, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { Provider } from 'react-redux'; @@ -70,28 +70,39 @@ export function GraphApp(props: GraphAppProps) {
- {sidebarOpen && ( - - )} - {props.isInitialized && !sidebarOpen && ( - { - setSidebarOpen(true); - }} - iconType="menuLeft" - style={{ position: 'absolute', top: 122, right: 5, zIndex: 999 }} - color="text" - /> - )} - {!props.isInitialized && ( - { - setPickerOpen(true); - }} - /> - )} + +
+ + + {!props.isInitialized && ( + { + setPickerOpen(true); + }} + /> + )} + {props.isInitialized && !sidebarOpen && ( + { + setSidebarOpen(true); + }} + iconType="menuLeft" + color="text" + /> + )} + + + {sidebarOpen && ( + + )} + +
diff --git a/x-pack/legacy/plugins/graph/public/components/edit_nodes_panel.tsx b/x-pack/legacy/plugins/graph/public/components/edit_nodes_panel.tsx index baa53f7922d77..322f39c6cf13c 100644 --- a/x-pack/legacy/plugins/graph/public/components/edit_nodes_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/edit_nodes_panel.tsx @@ -48,119 +48,129 @@ function EditNodesPanelComponent(props: any) { const [refresher, setRefresher] = useState(0); return ( -
-
- -

Edit Selection

-
- { - props.dataMode(); - }} - /> -
- {workspace && ( -
- - -

Selected vertices

-
+ + +
+ +

Edit Selection

+
+ { + props.dataMode(); + }} + /> +
+
+
+ {workspace && ( + + + + +

Selected vertices

+
- + - {workspace && - workspace.selectedNodes && - workspace.selectedNodes.length > 0 && - workspace.selectedNodes.map(node => ( - - { - node.label = e.target.value; - // super dirty hack to refresh component with only change in mutable data structure - setRefresher(refresher + 1); - props.notifyAngular(); - }} - prepend={ -
- -
- } - /> -
- ))} -
+ {workspace && + workspace.selectedNodes && + workspace.selectedNodes.length > 0 && + workspace.selectedNodes.map(node => ( + + { + node.label = e.target.value; + // super dirty hack to refresh component with only change in mutable data structure + setRefresher(refresher + 1); + props.notifyAngular(); + }} + prepend={ +
+ +
+ } + /> +
+ ))} + +
- - -

Styles

-
+ + + +

Styles

+
- + - {workspace && workspace.selectedNodes && workspace.selectedNodes.length > 0 && ( - <> - - { - workspace.selectedNodes.forEach(node => { - node.color = newColor; - }); + {workspace && workspace.selectedNodes && workspace.selectedNodes.length > 0 && ( + <> + + { + workspace.selectedNodes.forEach(node => { + node.color = newColor; + }); - setRefresher(refresher + 1); - props.notifyAngular(); - }} - /> - + setRefresher(refresher + 1); + props.notifyAngular(); + }} + /> + - - { - const { label, value } = option; - return ( - - {' '} - {label} - - ); - }} - options={iconChoices.map(currentIcon => ({ - label: currentIcon.label, - value: currentIcon, - }))} - selectedOptions={[ - { - label: workspace.selectedNodes[0].icon.label, - value: workspace.selectedNodes[0].icon, - }, - ]} - onChange={choices => { - workspace.selectedNodes.forEach(node => { - node.icon = choices[0].value!; - }); + + { + const { label, value } = option; + return ( + + {' '} + {label} + + ); + }} + options={iconChoices.map(currentIcon => ({ + label: currentIcon.label, + value: currentIcon, + }))} + selectedOptions={[ + { + label: workspace.selectedNodes[0].icon.label, + value: workspace.selectedNodes[0].icon, + }, + ]} + onChange={choices => { + workspace.selectedNodes.forEach(node => { + node.icon = choices[0].value!; + }); - setRefresher(refresher + 1); - props.notifyAngular(); - }} - compressed - /> - - + setRefresher(refresher + 1); + props.notifyAngular(); + }} + compressed + /> + + + )} +
+
+
)} - +
- )} -
+ + ); } diff --git a/x-pack/legacy/plugins/graph/public/components/graph_visualization/_graph_visualization.scss b/x-pack/legacy/plugins/graph/public/components/graph_visualization/_graph_visualization.scss index 975e4e84d6b0d..ae3a9e5b7263f 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_visualization/_graph_visualization.scss +++ b/x-pack/legacy/plugins/graph/public/components/graph_visualization/_graph_visualization.scss @@ -2,6 +2,11 @@ flex: 1; display: flex; flex-direction: column; + + &__toolbar { + } + &__toolbarButton { + } } .gphGraph { @@ -65,3 +70,76 @@ fill: $euiColorGhost; } } + +.gphVisualization__toolbar { + position: absolute; + top: $euiSizeM; + left: $euiSizeM; + + > div { + margin-bottom: $euiSizeS; + } +} + +.gphVisualization__toolbarButtonGroup { + @include euiBottomShadow; + background-color: $euiColorEmptyShade !important; + pointer-events: all; + border-radius: $euiBorderRadius; + + .euiButtonIcon { + @include size($euiSizeXL); + background-color: $euiColorEmptyShade !important; + pointer-events: all; + } +} + +.gphVisualization__toolbarButton { + @include size($euiSizeXL); + // sass-lint:disable-block no-important + background-color: $euiColorEmptyShade !important; + pointer-events: all; + + &:enabled, + &:enabled:hover, + &:enabled:focus { + @include euiBottomShadow; + } +} + +.gphVisualizationPopover { + &__description { + border-bottom: 1px solid $euiBorderColor; + padding-bottom: $euiSizeS; + margin-bottom: $euiSizeS; + } + &__edgeSummary { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + } + &__edgeSummaryText, + &__fieldTerm { + margin-top: $euiSizeXS; + } + &__fieldTerm { + span:first-child { + margin-right: $euiSizeXS; + } + span:last-child { + margin-left: $euiSizeXS; + } + } + &__edgeSummaryOverlap { + margin: 0 $euiSizeS; + } +} + +.gphVisualizationToolTipAnchor { + margin-right: $euiSizeS; + + &:last-of-type { + margin-right: 0; + } +} diff --git a/x-pack/legacy/plugins/graph/public/components/graph_visualization/graph_visualization.tsx b/x-pack/legacy/plugins/graph/public/components/graph_visualization/graph_visualization.tsx index 1eb2ea67dcacd..63fb55bedd1a9 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_visualization/graph_visualization.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_visualization/graph_visualization.tsx @@ -18,9 +18,12 @@ import { EuiFormRow, EuiListGroup, EuiIcon, - EuiPanel, + EuiToolTip, EuiContextMenuPanel, EuiContextMenuItem, + EuiFlexGroup, + EuiFlexItem, + EuiText, } from '@elastic/eui'; import { WorkspaceNode, WorkspaceEdge, WorkspaceField, UrlTemplate } from '../../types'; import { makeNodeId } from '../../services/persistence'; @@ -31,7 +34,6 @@ import { templatesSelector, updateMetaData, } from '../../state_management'; -import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public/context'; import { urlTemplateRegex } from '../../helpers/url_template'; import { LegacyIcon } from '../legacy_icon'; import { VennDiagram } from '../venn_diagram'; @@ -173,175 +175,196 @@ function GraphVisualizationComponent({ return ( <> -
- - setOpen(!open)} - /> - - } - isOpen={open} - closePopover={() => setOpen(false)} +
+ - - { - setMinDocCount(e.target.valueAsNumber); - updateLayout(clientWorkspace, e.target.valueAsNumber); + + { + d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 + + // Record the coordinates (in data space) of the center (in screen space). + zoom.scale(zoom.scale() * 1.1); + + d3el + .transition() + .duration(300) + .call(zoom.event); }} - showInput /> - - -
-
- - { - d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 + + + { + d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 - // Record the coordinates (in data space) of the center (in screen space). - zoom.scale(zoom.scale() * 1.1); + // Record the coordinates (in data space) of the center (in screen space). + zoom.scale(zoom.scale() * 0.9); - d3el - .transition() - .duration(300) - .call(zoom.event); - }} - /> - -
-
- - { - d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 + d3el + .transition() + .duration(300) + .call(zoom.event); + }} + /> + + - // Record the coordinates (in data space) of the center (in screen space). - zoom.scale(zoom.scale() * 0.9); + + + { + d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 - d3el - .transition() - .duration(300) - .call(zoom.event); - }} - /> - -
-
- - { - d3el.call(zoom.event); // https://github.com/mbostock/d3/issues/2387 + // Record the coordinates (in data space) of the center (in screen space). + zoom.translate([0, 0]); + zoom.scale(1); - // Record the coordinates (in data space) of the center (in screen space). - zoom.translate([0, 0]); - zoom.scale(1); + d3el + .transition() + .duration(300) + .call(zoom.event); + }} + /> + + - d3el - .transition() - .duration(300) - .call(zoom.event); - }} - /> - -
-
- - clientWorkspace.undo()} - /> - -
-
- - clientWorkspace.redo()} - /> - -
-
- - setSelectionOpen(!selectionOpen)} - /> - - } - isOpen={selectionOpen} - closePopover={() => setSelectionOpen(false)} + - - { - clientWorkspace.selectAll(); - setRefresher(refresher + 1); - notifyAngular(); - }} - > - All - - { - clientWorkspace.selectNone(); - setRefresher(refresher + 1); - notifyAngular(); - }} - > - None - - { - clientWorkspace.selectInvert(); - setRefresher(refresher + 1); - notifyAngular(); - }} + + clientWorkspace.undo()} + /> + + + clientWorkspace.redo()} + /> + + + + + + setSelectionOpen(!selectionOpen)} + /> + } + isOpen={selectionOpen} + closePopover={() => setSelectionOpen(false)} > - Invert - - { - clientWorkspace.selectNeighbours(); - setRefresher(refresher + 1); - notifyAngular(); - }} + + { + clientWorkspace.selectAll(); + setRefresher(refresher + 1); + notifyAngular(); + }} + > + All + + { + clientWorkspace.selectNone(); + setRefresher(refresher + 1); + notifyAngular(); + }} + > + None + + { + clientWorkspace.selectInvert(); + setRefresher(refresher + 1); + notifyAngular(); + }} + > + Invert + + { + clientWorkspace.selectNeighbours(); + setRefresher(refresher + 1); + notifyAngular(); + }} + > + Linked + + + + + + setOpen(!open)} + /> + } + isOpen={open} + closePopover={() => setOpen(false)} > - Linked - - - + + { + setMinDocCount(e.target.valueAsNumber); + updateLayout(clientWorkspace, e.target.valueAsNumber); + }} + showInput + /> + + + +
} isOpen={!popoverForceClosed} @@ -397,23 +421,38 @@ function GraphVisualizationComponent({ setSelectedEdge(undefined); }} > - Connection summary +
+ +

Connection summary

+
+
+ {edgeSummary ? ( - <> -
- - - {edgeSummary.v1} ({edgeSummary.overlap}) {edgeSummary.v2} -
- {edge.topSrc.data.field}: {edge.topSrc.data.term}{' '} +
+ + + {edgeSummary.v1} + + ({edgeSummary.overlap}) + + {edgeSummary.v2} + + + + {edge.topSrc.data.field}: {edge.topSrc.data.term} + + {edge.topTarget.data.field}: {edge.topTarget.data.term} - -
- + + +
) : ( 'loading...' )} @@ -480,6 +519,7 @@ function GraphVisualizationComponent({ y={node.ky} > } isOpen={!popoverForceClosed} @@ -493,64 +533,110 @@ function GraphVisualizationComponent({ // notifyAngular(); }} > - - {clientWorkspace.selectedNodes.length}{' '} - {clientWorkspace.selectedNodes.length === 1 ? 'vertex' : 'vertices'}{' '} - selected - -
- { - dataMode(); - }} - />{' '} - { - editMode(); - }} - />{' '} - { - setForceClosedPopover(true); - editMode(); - if (clientWorkspace.selectedNodes.length === 1) { - clientWorkspace.ungroup(clientWorkspace.selectedNodes[0]); - } else { - clientWorkspace.groupSelections( - clientWorkspace.selectedNodes[ - clientWorkspace.selectedNodes.length - 1 - ] - ); +
+ +

+ {' '} + {clientWorkspace.selectedNodes.length}{' '} + {clientWorkspace.selectedNodes.length === 1 ? 'vertex' : 'vertices'}{' '} + selected +

+
+
+ + + { + dataMode(); + }} + /> + + + { + editMode(); + }} + /> + + + {' '} - { - e.stopPropagation(); - setShowDrilldown(!showDrilldown); - }} - />{' '} - { - clientWorkspace.deleteSelection(); - }} - /> + onClick={() => { + setForceClosedPopover(true); + editMode(); + if (clientWorkspace.selectedNodes.length === 1) { + clientWorkspace.ungroup(clientWorkspace.selectedNodes[0]); + } else { + clientWorkspace.groupSelections( + clientWorkspace.selectedNodes[ + clientWorkspace.selectedNodes.length - 1 + ] + ); + } + }} + /> + + + { + e.stopPropagation(); + setShowDrilldown(!showDrilldown); + }} + /> + + + { + clientWorkspace.deleteSelection(); + }} + /> + {showDrilldown && ( ({ @@ -558,7 +644,7 @@ function GraphVisualizationComponent({ icon: template.icon ? ( ) : ( - + ), size: 's', onClick: () => { diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/_guidance_panel.scss b/x-pack/legacy/plugins/graph/public/components/guidance_panel/_guidance_panel.scss index e1423b794dcd3..9d90ecad02a86 100644 --- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/_guidance_panel.scss +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/_guidance_panel.scss @@ -1,6 +1,55 @@ .gphGuidancePanel { - max-width: 580px; - margin: $euiSizeL 0; + max-width: $euiSizeXL * 22; + align-self: center; + margin-top: $euiSizeXL; + padding: $euiSize; + + &__mainSection { + padding: $euiSizeL; + } + &__illustration { + padding: $euiSizeL; + + @media (max-width: 1100px) { + display: none; + } + } + &__moreSection { + background: $euiColorLightestShade; + padding: $euiSizeM $euiSizeL; + + h2 { + padding-bottom: $euiSizeM; + } + &__list { + display: flex; + + li { + display: flex; + padding: 0 $euiSizeL; + align-items: center; + + > span { + padding-left: $euiSizeS; + } + &:first-child { + padding-left: 0; + } + } + } + } + #graph-illustration_center { + transform-origin: 152px 138px; + animation: spin 12s ease-in-out infinite; + } + #node-and-con-green-1 { + transform-origin: 128px 199px; + animation: inverseArmMovement 12s ease-in-out infinite; + } + #node-and-con-green-2 { + transform-origin: 84px 106px; + animation: armMovement 12s ease-in-out infinite; + } } .gphGuidancePanel__list { @@ -10,10 +59,8 @@ } .gphGuidancePanel__item { - display: block; - max-width: 420px; + display: flex; position: relative; - padding-left: $euiSizeXL; margin-bottom: $euiSizeL; } @@ -26,16 +73,59 @@ } .gphGuidancePanel__itemIcon { - position: absolute; - left: 0; - top: -($euiSizeXS / 2); + display: inline-flex; width: $euiSizeL; height: $euiSizeL; padding: $euiSizeXS; + align-items: center; + justify-content: center; + border-radius: 50%; + line-height: $euiSizeL; + flex-grow: 0; + font-size: $euiSizeM; + font-weight: $euiFontWeightMedium; + border: 1px solid $euiColorPrimary; + margin-right: $euiSizeS; - &--done { - background-color: $euiColorSecondary; + &--active { + background-color: $euiColorPrimary; color: $euiColorEmptyShade; - border-radius: 50%; + } + &--isInactive { + background-color: transparent; + border-color: $euiColorDarkShade; + color: $euiColorDarkShade; + } +} + +.gphGuidancePanel__itemText { + flex: 1; +} + +@keyframes spin { + 100% { + transform: rotate(360deg); + } +} +@keyframes armMovement { + 0% { + transform: rotate(0deg); + } + 50% { + transform: rotate(30deg); + } + 100% { + transform: rotate(0); + } +} +@keyframes inverseArmMovement { + 0% { + transform: rotate(0deg); + } + 50% { + transform: rotate(-30deg); + } + 100% { + transform: rotate(0); } } diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index b4908c9b0aeb1..a21f9bb5600fd 100644 --- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -14,6 +14,8 @@ import { EuiLink, EuiCallOut, EuiScreenReaderOnly, + EuiTitle, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import classNames from 'classnames'; @@ -32,6 +34,8 @@ import { openSourceModal } from '../../services/source_modal'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { GuidancePanelIllustration } from './guidance_panel_illustration'; + export interface GuidancePanelProps { onFillWorkspace: () => void; onOpenFieldPicker: () => void; @@ -42,9 +46,11 @@ export interface GuidancePanelProps { } function ListItem({ + step, children, state, }: { + step: number; state: 'done' | 'active' | 'disabled'; children: ReactNode; }) { @@ -56,17 +62,31 @@ function ListItem({ aria-disabled={state === 'disabled'} aria-current={state === 'active' ? 'step' : undefined} > - {state !== 'disabled' && ( + {state !== 'disabled' && state === 'active' && ( + {step} + + )} + {state !== 'disabled' && state === 'done' && ( + + + + )} + {state === 'disabled' && ( + - + {step} )} - {children} + {children} ); } @@ -91,57 +111,78 @@ function GuidancePanelComponent(props: GuidancePanelProps) { }; let content = ( - - - - - - - -

- {i18n.translate('xpack.graph.guidancePanel.title', { - defaultMessage: 'Three steps to your graph', - })} -

-
-
- -
    - - - {i18n.translate( - 'xpack.graph.guidancePanel.datasourceItem.indexPatternButtonLabel', - { - defaultMessage: 'Select a data source.', - } - )} - - - - - {i18n.translate('xpack.graph.guidancePanel.fieldsItem.fieldsButtonLabel', { - defaultMessage: 'Add fields.', + +
    + + + +

    + {i18n.translate('xpack.graph.guidancePanel.title', { + defaultMessage: 'Three steps to your graph', })} - - - - - {i18n.translate('xpack.graph.guidancePanel.nodesItem.topTermsButtonLabel', { - defaultMessage: 'Graph the top terms', - })} - - ), - }} - /> - -

-
-
+ + + +
    + + + {i18n.translate( + 'xpack.graph.guidancePanel.datasourceItem.indexPatternButtonLabel', + { + defaultMessage: 'Select a data source.', + } + )} + + + + + {i18n.translate('xpack.graph.guidancePanel.fieldsItem.fieldsButtonLabel', { + defaultMessage: 'Add fields.', + })} + + + + + {i18n.translate('xpack.graph.guidancePanel.nodesItem.topTermsButtonLabel', { + defaultMessage: 'graph the top terms', + })} + + ), + }} + /> + +
+ + + + + +
+ +
+ + + +

Want to learn more?

+
+
    +
  • + + Watch video +
  • +
  • + + Read documentation +
  • +
+
+
+
); @@ -205,11 +246,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { ); } - return ( - - {content} - - ); + return
{content}
; } export const GuidancePanel = connect( diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel_illustration.js b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel_illustration.js new file mode 100644 index 0000000000000..26d0a298a3eda --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel_illustration.js @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +export const GuidancePanelIllustration = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +);