Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into lens/toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 committed Jun 18, 2020
2 parents a278772 + af5874d commit bfb6898
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 28 deletions.
71 changes: 68 additions & 3 deletions x-pack/plugins/apm/public/components/app/ServiceMap/Controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,64 @@ function doZoom(cy: cytoscape.Core | undefined, increment: number) {
}
}

function useDebugDownloadUrl(cy?: cytoscape.Core) {
const [downloadUrl, setDownloadUrl] = useState<string | undefined>(undefined);
const debug = sessionStorage.getItem('apm_debug') === 'true';

// Handle elements changes to update the download URL
useEffect(() => {
const elementsHandler: cytoscape.EventHandler = (event) => {
// @ts-ignore The `true` argument to `cy.json` is to flatten the elements
// (instead of having them broken into nodes/edges.) DefinitelyTyped has
// this wrong.
const elementsJson = event.cy.json(true)?.elements.map((element) => ({
data: element.data,
}));
setDownloadUrl(
elementsJson.length > 0 && debug
? `data:application/json;charset=utf-8,${encodeURIComponent(
JSON.stringify({ elements: elementsJson }, null, ' ')
)}`
: undefined
);
};

if (cy) {
cy.on('add remove', elementsHandler);
}

return () => {
if (cy) {
cy.off('add remove', undefined, elementsHandler);
}
};
}, [cy, debug]);

return downloadUrl;
}

export function Controls() {
const cy = useContext(CytoscapeContext);
const { urlParams } = useUrlParams();
const currentSearch = urlParams.kuery ?? '';
const [zoom, setZoom] = useState((cy && cy.zoom()) || 1);
const downloadUrl = useDebugDownloadUrl(cy);

// Handle zoom events
useEffect(() => {
const zoomHandler: cytoscape.EventHandler = (event) => {
setZoom(event.cy.zoom());
};

if (cy) {
cy.on('zoom', (event) => {
setZoom(event.cy.zoom());
});
cy.on('zoom', zoomHandler);
}

return () => {
if (cy) {
cy.off('zoom', undefined, zoomHandler);
}
};
}, [cy]);

function center() {
Expand Down Expand Up @@ -102,6 +148,9 @@ export function Controls() {
const centerLabel = i18n.translate('xpack.apm.serviceMap.center', {
defaultMessage: 'Center',
});
const downloadLabel = i18n.translate('xpack.apm.serviceMap.download', {
defaultMessage: 'Download',
});
const viewFullMapLabel = i18n.translate('xpack.apm.serviceMap.viewFullMap', {
defaultMessage: 'View full service map',
});
Expand Down Expand Up @@ -165,6 +214,22 @@ export function Controls() {
</EuiToolTip>
</Panel>
)}
{downloadUrl && (
<Panel hasShadow={true} paddingSize="none">
<EuiToolTip
anchorClassName="eui-displayInline"
content={downloadLabel}
>
<Button
aria-label={downloadLabel}
color="text"
download="service-map.json"
href={downloadUrl}
iconType="download"
/>
</EuiToolTip>
</Panel>
)}
</ControlsContainer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiForm,
EuiFieldNumber,
EuiToolTip,
EuiCodeEditor,
EuiSpacer,
EuiFilePicker,
} from '@elastic/eui';
import { storiesOf } from '@storybook/react';
import React, { useState, useEffect } from 'react';
Expand Down Expand Up @@ -99,47 +102,91 @@ storiesOf(STORYBOOK_PATH, module).add(
const [json, setJson] = useState<string>(
getSessionJson() || JSON.stringify(exampleResponseTodo, null, 2)
);
const [error, setError] = useState<string | undefined>();

const [elements, setElements] = useState<any[]>([]);
useEffect(() => {
try {
setElements(JSON.parse(json).elements);
} catch (error) {
console.log(error);
} catch (e) {
setError(e.message);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<div>
<Cytoscape elements={elements} height={600} width={1340} />
<EuiForm isInvalid={error !== undefined} error={error}>
<EuiFlexGroup>
<EuiFlexItem>
<EuiCodeEditor
mode="json"
theme="github"
width="100%"
value={json}
setOptions={{ fontSize: '12px' }}
onChange={(value) => {
setJson(value);
}}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup direction="column">
<EuiFilePicker
display={'large'}
fullWidth={true}
style={{ height: '100%' }}
initialPromptText="Upload a JSON file"
onChange={(event) => {
const item = event?.item(0);

<EuiFlexGroup>
<EuiFlexItem>
<EuiButton
onClick={() => {
setElements(JSON.parse(json).elements);
setSessionJson(json);
}}
>
Render JSON
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiCodeEditor
mode="json"
theme="github"
width="100%"
value={json}
setOptions={{ fontSize: '12px' }}
onChange={(value) => {
setJson(value);
}}
/>
if (item) {
const f = new FileReader();
f.onload = (onloadEvent) => {
const result = onloadEvent?.target?.result;
if (typeof result === 'string') {
setJson(result);
}
};
f.readAsText(item);
}
}}
/>
<EuiSpacer />
<EuiButton
onClick={() => {
try {
setElements(JSON.parse(json).elements);
setSessionJson(json);
setError(undefined);
} catch (e) {
setError(e.message);
}
}}
>
Render JSON
</EuiButton>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiForm>
</div>
);
},
{
info: { propTables: false, source: false },
info: {
propTables: false,
source: false,
text: `
Enter JSON map data into the text box or upload a file and click "Render JSON" to see the results. You can enable a download button on the service map by putting
\`\`\`
sessionStorage.setItem('apm_debug', 'true')
\`\`\`
into the JavaScript console and reloading the page.`,
},
}
);

Expand Down

0 comments on commit bfb6898

Please sign in to comment.