diff --git a/config/rollup/common.js b/config/rollup/common.js index 6d2cb03..064fd32 100644 --- a/config/rollup/common.js +++ b/config/rollup/common.js @@ -41,6 +41,7 @@ export const postcssPlugin = (options = {}) => ( autoModules: false, modules: { generateScopedName: '[name]__[local]___[hash:base64:5]', + hashPrefix: 'prefix', }, ...options, }) diff --git a/src/Components/NetworkTable/NetworkTable.styles.scss b/src/Components/NetworkTable/NetworkTable.styles.scss index abddcb6..9c9c35f 100644 --- a/src/Components/NetworkTable/NetworkTable.styles.scss +++ b/src/Components/NetworkTable/NetworkTable.styles.scss @@ -5,7 +5,6 @@ border-top: $border; } - .network-table-header { display: flex; width: 100%; @@ -27,13 +26,14 @@ width: 12%; align-self: center; padding-right: $size-xs-s; + min-width: $table-column-min-width; &:last-child { padding-right: 0; } &.show-waterfall { - width: 9%; + width: 10%; } &.file { @@ -44,8 +44,7 @@ } } - &.domain, - &.waterfall{ + &.domain { width: 15%; } } diff --git a/src/Components/NetworkTable/NetworkTableBody.jsx b/src/Components/NetworkTable/NetworkTableBody.jsx index 1c99158..999ddc4 100644 --- a/src/Components/NetworkTable/NetworkTableBody.jsx +++ b/src/Components/NetworkTable/NetworkTableBody.jsx @@ -7,6 +7,7 @@ import NetworkTableRow from './NetworkTableRow'; import { TABLE_ENTRY_HEIGHT } from '../../constants'; import { useResizeObserver } from '../../hooks/useResizeObserver'; import Styles from './NetworkTable.styles.scss'; +import { useTheme } from '../../state/theme/Context'; /* eslint no-underscore-dangle: 0 */ @@ -41,19 +42,26 @@ const NetworkTableBody = ({ height }) => { actions, callbacks, } = useNetwork(); + const { enableAutoScroll } = useTheme(); + const numberOfNewEntries = state.get('numberOfNewEntries'); const data = state.get('data'); const totalNetworkTime = state.get('totalNetworkTime'); const selectedReqIndex = state.get('selectedReqIndex'); const ref = useRef(null); - const { elementDims } = useResizeObserver(ref); + const { elementDims } = useResizeObserver(ref?.current?._outerRef || ref?.current); useEffect(() => actions.setTableHeaderWidth(elementDims.width), [elementDims]); useEffect(() => { - const outerRef = ref?.current?._outerRef; - if (outerRef.scrollTop + outerRef.offsetHeight + TABLE_ENTRY_HEIGHT >= outerRef.scrollHeight) { - ref.current._outerRef.scrollTop = outerRef.scrollHeight; + if (enableAutoScroll && ref?.current?._outerRef) { + const outerRef = ref?.current?._outerRef; + const needToScroll = outerRef.scrollTop + + outerRef.offsetHeight + + (numberOfNewEntries * TABLE_ENTRY_HEIGHT) >= outerRef.scrollHeight; + if (needToScroll) { + ref.current._outerRef.scrollTop = outerRef.scrollHeight; + } } }, [data, ref]); diff --git a/src/Components/NetworkTable/TimeChart.jsx b/src/Components/NetworkTable/TimeChart.jsx index ad19331..a2dda6c 100644 --- a/src/Components/NetworkTable/TimeChart.jsx +++ b/src/Components/NetworkTable/TimeChart.jsx @@ -20,10 +20,7 @@ const TimeChart = ({ placement="left" title={} > - + {chartAttributes.map((chartProps) => ( {isCopied ? 'Copied!' : 'Copy All'} + + ); +}; + +CopyAllButton.propTypes = { + text: PropTypes.object, +}; + +CopyAllButton.defaultProps = { + text: 'testi testi', +}; + +export default CopyAllButton; diff --git a/src/Components/ReqDetail/CopyAllButton.styles.scss b/src/Components/ReqDetail/CopyAllButton.styles.scss new file mode 100644 index 0000000..bb9b208 --- /dev/null +++ b/src/Components/ReqDetail/CopyAllButton.styles.scss @@ -0,0 +1,17 @@ +@import "./../../styles/variables"; + +.copy-button { + height: $filter-button-height; + color: $brand-blue; + font-size: $font-size-h6; + + .copy-text { + padding-left: $size-xs; + } + + .copy-icon { + fill: $brand-blue; + height: $size-s; + width: $size-s; + } +} diff --git a/src/Components/ReqDetail/Response.jsx b/src/Components/ReqDetail/Response.jsx index 62b59c7..7a68bc2 100644 --- a/src/Components/ReqDetail/Response.jsx +++ b/src/Components/ReqDetail/Response.jsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Styles from './Response.styles.scss'; +import CopyAllButton from './CopyAllButton'; const NoResponseText = () => (

This request has no response data available.

@@ -16,9 +17,12 @@ const Response = ({ data }) => { return (
-
+      
+ +
+ {content} -
+
); }; diff --git a/src/Components/ReqDetail/Response.styles.scss b/src/Components/ReqDetail/Response.styles.scss index 7e29d89..135786d 100644 --- a/src/Components/ReqDetail/Response.styles.scss +++ b/src/Components/ReqDetail/Response.styles.scss @@ -12,4 +12,16 @@ .response-content { font-size: $font-size-small; width: 100%; + display: flex; + flex-direction: column; + + .copy-button { + align-self: end; + } + + .response-body { + font-family: monospace; + white-space: pre-wrap; + word-break: break-all; + } } diff --git a/src/Components/ReqDetail/headers/General.jsx b/src/Components/ReqDetail/headers/General.jsx index f199203..56259db 100644 --- a/src/Components/ReqDetail/headers/General.jsx +++ b/src/Components/ReqDetail/headers/General.jsx @@ -7,7 +7,7 @@ import { GENERAL_HEADERS } from '../../../constants'; const General = ({ data }) => (
{Object.entries(GENERAL_HEADERS).map(([dataKey, { key, name }]) => ( -

@@ -17,7 +17,7 @@ const General = ({ data }) => ( {key === 'status' && data.error ? data.error : data[key]} -

+
))} ); diff --git a/src/Containers/MainContainer.styles.scss b/src/Containers/MainContainer.styles.scss index 091786f..f6ebc4a 100644 --- a/src/Containers/MainContainer.styles.scss +++ b/src/Containers/MainContainer.styles.scss @@ -12,5 +12,6 @@ height: 100%; width: 100%; overflow: auto; + overflow-x: hidden; outline: none; } diff --git a/src/Containers/NetworkTableContainer.jsx b/src/Containers/NetworkTableContainer.jsx index 72e1313..5de49fa 100644 --- a/src/Containers/NetworkTableContainer.jsx +++ b/src/Containers/NetworkTableContainer.jsx @@ -27,7 +27,7 @@ const NetworkTableContainer = () => { if (ref?.current) { setTableBodyHeight(ref.current.clientHeight - TABLE_HEADER_HEIGHT); } - }, [ref]); + }, [ref, actualData]); if (error) { return ( diff --git a/src/Containers/ReqDetailContainer.styles.scss b/src/Containers/ReqDetailContainer.styles.scss index ecf682c..a6147c5 100644 --- a/src/Containers/ReqDetailContainer.styles.scss +++ b/src/Containers/ReqDetailContainer.styles.scss @@ -66,5 +66,6 @@ $tab-height: 35px; padding: $size-s $size-m; height: calc(100% - #{$tab-height}); overflow: auto; + outline: none; } } diff --git a/src/constants.js b/src/constants.js index 3401fc1..d4e551e 100644 --- a/src/constants.js +++ b/src/constants.js @@ -227,14 +227,15 @@ export const TIMINGS = { }; export const TIME_CHART_SVG_PROPS = { - viewBox: '0 0 250 20', + height: '15', + viewBox: '0 0 200 20', version: '1.1', preserveAspectRatio: 'xMinYMin meet', }; export const TIME_CHART_DEFAULT_PROPS = { - height: 16, - y: 3.5, + height: 30, + y: 0, }; export const ROW_ID_PREFIX = 'network-viewer-table-row-'; @@ -293,6 +294,7 @@ export const NETWORK_VIEWER_DEFAULT_OPTIONS = { showPauseResume: false, showTimeline: false, showWaterfall: true, + enableAutoScroll: false, }; export const PAYLOAD_CAPTIONS = Object.freeze({ diff --git a/src/hooks/useResizeObserver.js b/src/hooks/useResizeObserver.js index 6056805..3d6b978 100644 --- a/src/hooks/useResizeObserver.js +++ b/src/hooks/useResizeObserver.js @@ -8,25 +8,23 @@ export const useResizeObserver = (elementRef) => { height: 0, }); useEffect(() => { - const element = elementRef.current; - const onResize = () => { - if (element._outerRef) { + if (elementRef) { setElementDims({ - width: element._outerRef.clientWidth, - height: element._outerRef.clientHeight, + width: elementRef.clientWidth, + height: elementRef.clientHeight, }); } }; const resizeObserver = new ResizeObserver(onResize); - if (element._outerRef) { - resizeObserver.observe(element._outerRef); + if (elementRef) { + resizeObserver.observe(elementRef); } return () => { - if (element._outerRef) { - resizeObserver.unobserve(element._outerRef); + if (elementRef) { + resizeObserver.unobserve(elementRef); } }; }, [elementRef]); diff --git a/src/icons/IconCheckMark.jsx b/src/icons/IconCheckMark.jsx new file mode 100644 index 0000000..ec0a113 --- /dev/null +++ b/src/icons/IconCheckMark.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const IconCheckMark = ({ className }) => ( + + + +); + +IconCheckMark.propTypes = { + className: PropTypes.string, +}; + +IconCheckMark.defaultProps = { + className: '', +}; + +export default IconCheckMark; diff --git a/src/icons/IconCopy.jsx b/src/icons/IconCopy.jsx new file mode 100644 index 0000000..60d8c3f --- /dev/null +++ b/src/icons/IconCopy.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const IconCopy = ({ className }) => ( + + + +); + +IconCopy.propTypes = { + className: PropTypes.string, +}; + +IconCopy.defaultProps = { + className: '', +}; + +export default IconCopy; diff --git a/src/state/network/reducer.js b/src/state/network/reducer.js index 3d8a0b2..570575e 100644 --- a/src/state/network/reducer.js +++ b/src/state/network/reducer.js @@ -30,6 +30,7 @@ const initialState = new Map({ showReqDetail: false, reqDetail: null, tableHeaderWidth: '100%', + numberOfNewEntries: 0, }); const reducer = (state = initialState, { @@ -58,11 +59,15 @@ const reducer = (state = initialState, { search: state.get('search'), }); + const prevData = state.get('data'); + const numberOfNewEntries = filteredData.size - prevData.size; + newState .set('error', null) .set('rawData', payload) .set('data', filteredData) .set('actualData', sortedData) + .set('numberOfNewEntries', numberOfNewEntries) .set('totalNetworkTime', totalNetworkTime) .set('dataSummary', new Map({ totalRequests, diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 852e0f7..2c602b7 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -80,6 +80,7 @@ $size-xxxl: $size-base * 11; // 44px; //  2x      8       24      32      40      56      72      88 $filter-button-height: 26px; +$table-column-min-width: 60px; $xs: 480px; $grid-sm: 576px; diff --git a/tests/__tests__/Components/Filters/__snapshots__/Search.spec.jsx.snap b/tests/__tests__/Components/Filters/__snapshots__/Search.spec.jsx.snap index 783073f..43021b8 100644 --- a/tests/__tests__/Components/Filters/__snapshots__/Search.spec.jsx.snap +++ b/tests/__tests__/Components/Filters/__snapshots__/Search.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`Search renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Components/Import/__snapshots__/ImportHar.spec.jsx.snap b/tests/__tests__/Components/Import/__snapshots__/ImportHar.spec.jsx.snap index f70a622..78d23d7 100644 --- a/tests/__tests__/Components/Import/__snapshots__/ImportHar.spec.jsx.snap +++ b/tests/__tests__/Components/Import/__snapshots__/ImportHar.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`ImportHAR renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableHeader.spec.jsx.snap b/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableHeader.spec.jsx.snap index f8c72e8..9a55283 100644 --- a/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableHeader.spec.jsx.snap +++ b/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableHeader.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`NetworkTableHeader renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableRow.spec.jsx.snap b/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableRow.spec.jsx.snap index 256bb7e..4776383 100644 --- a/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableRow.spec.jsx.snap +++ b/tests/__tests__/Components/NetworkTable/__snapshots__/NetworkTableRow.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`NetworkTableRow renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Components/ReqDetail/__snapshots__/Headers.spec.jsx.snap b/tests/__tests__/Components/ReqDetail/__snapshots__/Headers.spec.jsx.snap index 7ad0cf3..49818fc 100644 --- a/tests/__tests__/Components/ReqDetail/__snapshots__/Headers.spec.jsx.snap +++ b/tests/__tests__/Components/ReqDetail/__snapshots__/Headers.spec.jsx.snap @@ -140,7 +140,7 @@ exports[`Headers renders without crashing 1`] = `
-

@@ -149,8 +149,8 @@ exports[`Headers renders without crashing 1`] = ` https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice -

-

+

@@ -159,8 +159,8 @@ exports[`Headers renders without crashing 1`] = ` GET -

-

+

@@ -169,8 +169,8 @@ exports[`Headers renders without crashing 1`] = ` 200 -

-

+

@@ -179,7 +179,7 @@ exports[`Headers renders without crashing 1`] = ` :80 -

+
diff --git a/tests/__tests__/Components/ReqDetail/__snapshots__/Response.spec.jsx.snap b/tests/__tests__/Components/ReqDetail/__snapshots__/Response.spec.jsx.snap index ec17a81..15d47f3 100644 --- a/tests/__tests__/Components/ReqDetail/__snapshots__/Response.spec.jsx.snap +++ b/tests/__tests__/Components/ReqDetail/__snapshots__/Response.spec.jsx.snap @@ -2,9 +2,14 @@ exports[`Response renders without crashing for content 1`] = `
-
+  
+ +
+ {"foo": "bar"} -
+
`; diff --git a/tests/__tests__/Components/ReqDetail/headers/__snapshots__/General.spec.jsx.snap b/tests/__tests__/Components/ReqDetail/headers/__snapshots__/General.spec.jsx.snap index 4c33c69..bac1972 100644 --- a/tests/__tests__/Components/ReqDetail/headers/__snapshots__/General.spec.jsx.snap +++ b/tests/__tests__/Components/ReqDetail/headers/__snapshots__/General.spec.jsx.snap @@ -2,23 +2,23 @@ exports[`General renders intercept error 1`] = `
-

Request URL: -

-

+

Request Method: -

-

+

@@ -27,51 +27,51 @@ exports[`General renders intercept error 1`] = ` ERR_TIMED_OUT -

-

+

Remote Address: -

+
`; exports[`General renders without crashing 1`] = `
-

Request URL: -

-

+

Request Method: -

-

+

Status Code: -

-

+

Remote Address: -

+
`; diff --git a/tests/__tests__/Containers/__snapshots__/FilterContainer.spec.jsx.snap b/tests/__tests__/Containers/__snapshots__/FilterContainer.spec.jsx.snap index 5a49aca..e570f47 100644 --- a/tests/__tests__/Containers/__snapshots__/FilterContainer.spec.jsx.snap +++ b/tests/__tests__/Containers/__snapshots__/FilterContainer.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`FilterContainer renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Containers/__snapshots__/MainContainer.spec.jsx.snap b/tests/__tests__/Containers/__snapshots__/MainContainer.spec.jsx.snap index c4c850d..900667c 100644 --- a/tests/__tests__/Containers/__snapshots__/MainContainer.spec.jsx.snap +++ b/tests/__tests__/Containers/__snapshots__/MainContainer.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`MainContainer renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Containers/__snapshots__/NetworkTableContainer.spec.jsx.snap b/tests/__tests__/Containers/__snapshots__/NetworkTableContainer.spec.jsx.snap index fa951a8..b9ec071 100644 --- a/tests/__tests__/Containers/__snapshots__/NetworkTableContainer.spec.jsx.snap +++ b/tests/__tests__/Containers/__snapshots__/NetworkTableContainer.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`NetworkTableContainer renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Containers/__snapshots__/ReqDetailContainer.spec.jsx.snap b/tests/__tests__/Containers/__snapshots__/ReqDetailContainer.spec.jsx.snap index 2a0d3c3..042786a 100644 --- a/tests/__tests__/Containers/__snapshots__/ReqDetailContainer.spec.jsx.snap +++ b/tests/__tests__/Containers/__snapshots__/ReqDetailContainer.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`ReqDetailContainer renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/Containers/__snapshots__/TimelineContainer.spec.jsx.snap b/tests/__tests__/Containers/__snapshots__/TimelineContainer.spec.jsx.snap index 3011e5b..c7dd8be 100644 --- a/tests/__tests__/Containers/__snapshots__/TimelineContainer.spec.jsx.snap +++ b/tests/__tests__/Containers/__snapshots__/TimelineContainer.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`TimelineContainer renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/__snapshots__/NetworkViewer.spec.jsx.snap b/tests/__tests__/__snapshots__/NetworkViewer.spec.jsx.snap index ca283d4..d7c8e65 100644 --- a/tests/__tests__/__snapshots__/NetworkViewer.spec.jsx.snap +++ b/tests/__tests__/__snapshots__/NetworkViewer.spec.jsx.snap @@ -32,6 +32,7 @@ exports[`renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, diff --git a/tests/__tests__/state/__snapshots__/NetworkProvider.spec.jsx.snap b/tests/__tests__/state/__snapshots__/NetworkProvider.spec.jsx.snap index 2985015..cca4d48 100644 --- a/tests/__tests__/state/__snapshots__/NetworkProvider.spec.jsx.snap +++ b/tests/__tests__/state/__snapshots__/NetworkProvider.spec.jsx.snap @@ -26,6 +26,7 @@ exports[`NetworkProvider renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null, @@ -77,6 +78,7 @@ exports[`NetworkProvider renders without crashing 1`] = ` "tableHeaderWidth": "100%", "selectedReqIndex": null, "reqDetail": null, + "numberOfNewEntries": 0, "showReqDetail": false, "typeFilter": Object { "name": null,