From bdfe877d80ffbf824a5a080123af5d48d0b335be Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 15 Feb 2022 16:42:21 +0300 Subject: [PATCH 01/12] move copy button near query runner --- .../views/query-response/QueryResponse.tsx | 18 ------------ .../query-runner/query-input/QueryInput.tsx | 28 +++++++++++++++++-- .../auto-complete/AutoComplete.tsx | 1 - .../auto-complete/suffix/HintList.tsx | 3 +- .../auto-complete/suffix/SuffixRenderer.tsx | 19 +++++++++---- src/telemetry/component-names.ts | 1 + 6 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/app/views/query-response/QueryResponse.tsx b/src/app/views/query-response/QueryResponse.tsx index d36e7fb63..ae8096f24 100644 --- a/src/app/views/query-response/QueryResponse.tsx +++ b/src/app/views/query-response/QueryResponse.tsx @@ -72,20 +72,11 @@ const QueryResponse = (props: IQueryResponseProps) => { toggleModal(pivotItem); }; - const handleShareQuery = () => { - const shareableLink = createShareLink(sampleQuery); - setQuery(shareableLink); - toggleShareQueryDialogState(); - }; - const toggleModal = (event: any) => { const { key } = event; if (key && key.includes('expand')) { toggleExpandResponse(); } - if (key && key.includes('share')) { - handleShareQuery(); - } }; const renderItemLink = (link: any) => { @@ -127,15 +118,6 @@ const QueryResponse = (props: IQueryResponseProps) => { {getPivotItems()} - { const { @@ -74,6 +79,11 @@ const QueryInput = (props: IQueryInputProps) => { }, 500); }; + const handleCopy = () => { + const shareableLink = createShareLink(sampleQuery); + trackedGenericCopy(shareableLink, componentNames.QUERY_COPY_BUTTON, sampleQuery); + } + return (
@@ -94,12 +104,25 @@ const QueryInput = (props: IQueryInputProps) => { onChange={(event, method) => handleOnVersionChange(method)} />
-
+
+
+
+
+ +
+
+ +
+
+
{ allowDisabledFocus={true} />
-
) +
+ ) } // @ts-ignore diff --git a/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx b/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx index 9449499a0..e25f4eccd 100644 --- a/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/AutoComplete.tsx @@ -384,7 +384,6 @@ class AutoComplete extends Component { onKeyDown={this.onKeyDown} value={queryUrl} componentRef={this.autoCompleteRef} - onRenderSuffix={(this.renderSuffix()) ? this.renderSuffix : undefined} ariaLabel={translateMessage('Query Sample Input')} role='textbox' errorMessage={getErrorMessage()} diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/HintList.tsx b/src/app/views/query-runner/query-input/auto-complete/suffix/HintList.tsx index d8f4b8ee9..87d7d7a17 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/HintList.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/HintList.tsx @@ -5,7 +5,7 @@ import { IHint } from './suffix-util'; import { styles } from './suffix.styles'; export const HintList = ({ hints }: any) => { - const listItems = hints.map((hint: IHint, index: any) =>
+ return hints.map((hint: IHint, index: any) =>
{hint.description && {hint.description} } @@ -19,5 +19,4 @@ export const HintList = ({ hints }: any) => {
); - return listItems; }; diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx index 22c589bac..129b8f548 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx @@ -86,16 +86,24 @@ const SuffixRenderer = () => { const hintsAvailable = hints.length > 0; const infoIcon: IIconProps = {iconName: 'Info'}; - if (hintsAvailable) { - return ( - <> + + return ( + <> + + {isCalloutVisible && ( { )} - ); - } - return null; + + ); } export default SuffixRenderer; diff --git a/src/telemetry/component-names.ts b/src/telemetry/component-names.ts index 2801c9bed..4b69ea496 100644 --- a/src/telemetry/component-names.ts +++ b/src/telemetry/component-names.ts @@ -17,6 +17,7 @@ export const DELETE_HISTORY_ITEM_BUTTON = 'Delete history item button'; export const RESPONSE_HEADERS_COPY_BUTTON = 'Response headers copy button'; export const DOWNLOAD_POSTMAN_COLLECTION_BUTTON = 'Download postman collection button'; export const REMOVE_RESOURCE_FROM_COLLECTION_BUTTON = 'Remove resource from collection button'; +export const QUERY_COPY_BUTTON = 'Query copy button'; // List items export const HISTORY_LIST_ITEM = 'History list item'; From c8389eb1d6675d441fc7fe7fa60674defc36b08b Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 15 Feb 2022 16:42:46 +0300 Subject: [PATCH 02/12] add margin --- src/app/views/query-runner/query-input/QueryInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/query-runner/query-input/QueryInput.tsx b/src/app/views/query-runner/query-input/QueryInput.tsx index 7cadc4670..a610499bf 100644 --- a/src/app/views/query-runner/query-input/QueryInput.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.tsx @@ -111,7 +111,7 @@ const QueryInput = (props: IQueryInputProps) => { />
-
+
From 4f53e7a5c566ab2d8c4a9d6158d9450ebc2dacc0 Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 15 Feb 2022 17:12:49 +0300 Subject: [PATCH 03/12] switch button positions --- src/app/views/query-runner/query-input/QueryInput.tsx | 10 +++++----- src/app/views/query-runner/query-runner.scss | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/app/views/query-runner/query-input/QueryInput.tsx b/src/app/views/query-runner/query-input/QueryInput.tsx index a610499bf..9c1c7c1e7 100644 --- a/src/app/views/query-runner/query-input/QueryInput.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.tsx @@ -110,17 +110,17 @@ const QueryInput = (props: IQueryInputProps) => { runQuery={runQuery} />
-
-
-
- -
+
+
+
+ +
diff --git a/src/app/views/query-runner/query-runner.scss b/src/app/views/query-runner/query-runner.scss index 47cc1312f..4e2930ced 100644 --- a/src/app/views/query-runner/query-runner.scss +++ b/src/app/views/query-runner/query-runner.scss @@ -12,3 +12,13 @@ outline-width:thick !important ; } +.copy-info-section { + @media screen and (min-width: 992px){ + margin-left: -5px !important + } + @media screen and (max-width: 991px){ + margin-left: 14px !important + } + +} + From 3628edd5bc89324a0371011550a17e107b8655ef Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Sun, 20 Feb 2022 14:19:43 +0300 Subject: [PATCH 04/12] remove flex-wrap property --- src/app/views/query-runner/query-input/QueryInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/query-runner/query-input/QueryInput.tsx b/src/app/views/query-runner/query-input/QueryInput.tsx index 9c1c7c1e7..fce9dcc8d 100644 --- a/src/app/views/query-runner/query-input/QueryInput.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.tsx @@ -111,7 +111,7 @@ const QueryInput = (props: IQueryInputProps) => { />
-
+
Date: Sun, 20 Feb 2022 18:10:00 +0300 Subject: [PATCH 05/12] disable flexwrap at 150% resolution --- .../query-runner/query-input/QueryInput.tsx | 20 +++++++++---------- src/app/views/query-runner/query-runner.scss | 13 +----------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/app/views/query-runner/query-input/QueryInput.tsx b/src/app/views/query-runner/query-input/QueryInput.tsx index a904e7c4f..1e7fc4f7b 100644 --- a/src/app/views/query-runner/query-input/QueryInput.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.tsx @@ -109,17 +109,15 @@ const QueryInput = (props: IQueryInputProps) => { runQuery={runQuery} />
-
-
-
- -
-
- -
+
+
+ +
+
+
diff --git a/src/app/views/query-runner/query-runner.scss b/src/app/views/query-runner/query-runner.scss index 4e2930ced..c8a37ace7 100644 --- a/src/app/views/query-runner/query-runner.scss +++ b/src/app/views/query-runner/query-runner.scss @@ -10,15 +10,4 @@ .ms-Dropdown:focus { outline-style:double !important; outline-width:thick !important ; -} - -.copy-info-section { - @media screen and (min-width: 992px){ - margin-left: -5px !important - } - @media screen and (max-width: 991px){ - margin-left: 14px !important - } - -} - +} \ No newline at end of file From 84b34bd6d74ef11decd18b6452aa198a90ed5e5c Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Mon, 21 Feb 2022 16:10:24 +0300 Subject: [PATCH 06/12] update QueryInput test --- .../auto-complete/suffix/SuffixRenderer.tsx | 32 +++++++++---------- src/tests/components/App.spec.tsx | 1 - .../query-runner/QueryInput.spec.tsx | 32 +++++++++++++++++-- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx index 129b8f548..7f0870605 100644 --- a/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx +++ b/src/app/views/query-runner/query-input/auto-complete/suffix/SuffixRenderer.tsx @@ -104,23 +104,23 @@ const SuffixRenderer = () => { disabled={!hintsAvailable} /> - {isCalloutVisible && ( - - + {isCalloutVisible && ( + + /{requestUrl} - - - - )} + + + + )} ); } diff --git a/src/tests/components/App.spec.tsx b/src/tests/components/App.spec.tsx index 99514e0fd..667299a12 100644 --- a/src/tests/components/App.spec.tsx +++ b/src/tests/components/App.spec.tsx @@ -100,7 +100,6 @@ describe('It should render the main GE site', () => { getByText('Toolkit component'); getByText('Adaptive cards'); getByText('Expand'); - getByText('Share'); getByText('Authentication'); getByText('Sample queries'); getByText('History'); diff --git a/src/tests/components/query-runner/QueryInput.spec.tsx b/src/tests/components/query-runner/QueryInput.spec.tsx index ec2785537..22a40d137 100644 --- a/src/tests/components/query-runner/QueryInput.spec.tsx +++ b/src/tests/components/query-runner/QueryInput.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { cleanup, render } from '@testing-library/react'; +import { cleanup, render, screen } from '@testing-library/react'; import IntlQueryInput from '../../../app/views/query-runner/query-input/QueryInput'; import { IQueryInputProps } from '../../../types/query-runner'; import { Mode } from '../../../types/enums'; @@ -68,7 +68,31 @@ jest.mock('react-redux', () => { pending: false, token: true }, - isLoadingData: false + isLoadingData: false, + autoComplete: { + data: {}, + error: null, + pending: false + }, + samples: { + pending: false, + error: null, + queries: [ + { + category: 'Sample category', + requestUrl: '/me', + method: 'GET', + humanName: 'Sample name', + docLink: 'https://graph.microsoft.com/v1.0/me' + } + ] + }, + queryRunnerStatus: { + messageType: 1, + ok: true, + status: 200, + statusText:'' + } }) }) } @@ -76,6 +100,8 @@ jest.mock('react-redux', () => { describe('Renders QueryInput component without crashing', () => { it('renders without crashing', () => { - renderQueryInput(); + const { getByText } = renderQueryInput() + getByText(/Run query/); + expect(renderQueryInput()).toBeDefined(); }); }) \ No newline at end of file From 83a1d681f99a71759d7ade72f14f0f0f7b3fc3e1 Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 22 Feb 2022 09:58:47 +0300 Subject: [PATCH 07/12] fix code smells --- src/app/views/query-response/QueryResponse.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/views/query-response/QueryResponse.tsx b/src/app/views/query-response/QueryResponse.tsx index ae8096f24..3b35f4648 100644 --- a/src/app/views/query-response/QueryResponse.tsx +++ b/src/app/views/query-response/QueryResponse.tsx @@ -17,7 +17,6 @@ import { expandResponseArea } from '../../services/actions/response-expanded-act import { translateMessage } from '../../utils/translate-messages'; import { copy } from '../common/copy'; import { convertVhToPx } from '../common/dimensions-adjustment'; -import { createShareLink } from '../common/share'; import { getPivotItems, onPivotItemClick } from './pivot-items/pivot-items'; import './query-response.scss'; import { IRootState } from '../../../types/root'; @@ -29,7 +28,7 @@ const QueryResponse = (props: IQueryResponseProps) => { const [showShareQueryDialog, setShareQuaryDialogStatus] = useState(true); const [showModal, setShowModal] = useState(false); - const [query, setQuery] = useState(''); + const [query] = useState(''); const [responseHeight, setResponseHeight] = useState('610px'); const { dimensions, sampleQuery } = useSelector((state: IRootState) => state); From 0767d409ece95cb8c70972dcce2f97b5a34ba786 Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Fri, 25 Feb 2022 16:29:05 +0300 Subject: [PATCH 08/12] restore share query behavior --- .../views/query-runner/QueryRunner.styles.ts | 7 + .../query-input/QueryInput.spec.tsx | 4 + .../query-runner/query-input/QueryInput.tsx | 206 +++++++++++++----- .../auto-complete/AutoComplete.tsx | 1 + 4 files changed, 168 insertions(+), 50 deletions(-) diff --git a/src/app/views/query-runner/QueryRunner.styles.ts b/src/app/views/query-runner/QueryRunner.styles.ts index 21e9893c7..84f761f82 100644 --- a/src/app/views/query-runner/QueryRunner.styles.ts +++ b/src/app/views/query-runner/QueryRunner.styles.ts @@ -8,6 +8,13 @@ export const queryRunnerStyles = () => { caretDown: { color: '#ffffff !important' } + }, + iconButton: { + root: { + float: 'right', + border: '1px solid', + width: '100%' + } } }; }; \ No newline at end of file diff --git a/src/app/views/query-runner/query-input/QueryInput.spec.tsx b/src/app/views/query-runner/query-input/QueryInput.spec.tsx index 164a1b56f..c20a24e40 100644 --- a/src/app/views/query-runner/query-input/QueryInput.spec.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.spec.tsx @@ -93,6 +93,10 @@ jest.mock('react-redux', () => { ok: true, status: 200, statusText:'' + }, + sidebarProperties: { + showSidebar: false, + mobileScreen: false } }) }) diff --git a/src/app/views/query-runner/query-input/QueryInput.tsx b/src/app/views/query-runner/query-input/QueryInput.tsx index 1e7fc4f7b..62c04f56e 100644 --- a/src/app/views/query-runner/query-input/QueryInput.tsx +++ b/src/app/views/query-runner/query-input/QueryInput.tsx @@ -1,23 +1,25 @@ -import { IDropdownOption, Dropdown } from '@fluentui/react'; -import React from 'react'; +import { IDropdownOption, Dropdown, Dialog, IconButton, DialogType, + FontSizes, DialogFooter, DefaultButton, IIconProps, TooltipHost, DirectionalHint } from '@fluentui/react'; +import React, { useEffect, useState } from 'react'; import { injectIntl } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; -import { componentNames } from '../../../../telemetry'; +import { componentNames, eventTypes, telemetry } from '../../../../telemetry'; import { httpMethods, IQueryInputProps } from '../../../../types/query-runner'; import { IRootState } from '../../../../types/root'; import { setSampleQuery } from '../../../services/actions/query-input-action-creators'; import { GRAPH_API_VERSIONS } from '../../../services/graph-constants'; import { getStyleFor } from '../../../utils/http-methods.utils'; +import { sanitizeQueryUrl } from '../../../utils/query-url-sanitization'; import { parseSampleUrl } from '../../../utils/sample-url-generation'; import { translateMessage } from '../../../utils/translate-messages'; import SubmitButton from '../../../views/common/submit-button/SubmitButton'; -import { trackedGenericCopy } from '../../common/copy'; +import { copy } from '../../common/copy'; import { CopyButton } from '../../common/copy/CopyButton'; import { createShareLink } from '../../common/share'; import { queryRunnerStyles } from '../QueryRunner.styles'; import { AutoComplete } from './auto-complete'; -import SuffixRenderer from './auto-complete/suffix/SuffixRenderer'; + const QueryInput = (props: IQueryInputProps) => { const { @@ -37,9 +39,26 @@ const QueryInput = (props: IQueryInputProps) => { }); const { sampleQuery, authToken, - isLoadingData: submitting } = useSelector((state: IRootState) => state); + isLoadingData: submitting, sidebarProperties } = useSelector((state: IRootState) => state); const authenticated = !!authToken.token; + const { mobileScreen } = sidebarProperties; + + const [showShareQueryDialog, setShareQuaryDialogStatus] = useState(true); + const [shareLink, setShareLink] = useState(() => createShareLink(sampleQuery)); + + const toggleShareQueryDialogState = () => { + setShareQuaryDialogStatus(prevState => !prevState); + }; + + useEffect(() => { + setShareLink(createShareLink(sampleQuery)); + }, [sampleQuery]); + + const iconProps : IIconProps = { + iconName: 'Share' + } + const showError = !authenticated && sampleQuery.selectedVerb !== 'GET'; const verbSelector: any = queryRunnerStyles().verbSelector; verbSelector.title = { @@ -47,6 +66,14 @@ const QueryInput = (props: IQueryInputProps) => { background: getStyleFor(sampleQuery.selectedVerb) }; + const shareButtonStyles = queryRunnerStyles().iconButton; + + const calloutProps = { + gapSpace: 0 + }; + + const content =
{translateMessage('Share Query')}
+ const contentChanged = (value: string) => { const query = { ...sampleQuery, ...{ sampleUrl: value } }; changeUrlVersion(value); @@ -79,59 +106,138 @@ const QueryInput = (props: IQueryInputProps) => { }; const handleCopy = () => { - const shareableLink = createShareLink(sampleQuery); - trackedGenericCopy(shareableLink, componentNames.QUERY_COPY_BUTTON, sampleQuery); + copy('share-query-text'); + trackCopyEvent(); + }; + + const trackCopyEvent = () => { + const sanitizedUrl = sanitizeQueryUrl(sampleQuery.sampleUrl); + telemetry.trackEvent(eventTypes.BUTTON_CLICK_EVENT, + { + ComponentName: componentNames.SHARE_QUERY_COPY_BUTTON, + QuerySignature: `${sampleQuery.selectedVerb} ${sanitizedUrl}` + }); } return ( -
-
- handleOnMethodChange(method)} - /> -
-
- handleOnVersionChange(method)} - /> -
-
- + <> +
+
+ handleOnMethodChange(method)} + /> +
+
+ handleOnVersionChange(method)} + /> +
+
+ +
+ {!mobileScreen && + <> +
+ runQuery()} + submitting={submitting} + allowDisabledFocus={true} + /> +
+
+ + + +
+ + }
-
-
- +
+ runQuery()} + submitting={submitting} + allowDisabledFocus={true} />
-
- +
+ + +
-
- runQuery()} - submitting={submitting} - allowDisabledFocus={true} + } +