From 88e22602d665c3beef3e1d150b83a9b91b0ba475 Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Wed, 15 Dec 2021 19:33:41 +0300 Subject: [PATCH 01/20] Restore resources tab --- src/app/views/sidebar/Sidebar.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/views/sidebar/Sidebar.tsx b/src/app/views/sidebar/Sidebar.tsx index 48a9ffdd7f..e9e095141c 100644 --- a/src/app/views/sidebar/Sidebar.tsx +++ b/src/app/views/sidebar/Sidebar.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { telemetry } from '../../../telemetry'; import { translateMessage } from '../../utils/translate-messages'; import History from './history/History'; +import { ResourceExplorer } from './resource-explorer'; import SampleQueries from './sample-queries/SampleQueries'; export const Sidebar = () => { @@ -13,6 +14,9 @@ export const Sidebar = () => { + + + From aa306df47cdd3a46df571750b0738b0ae98ff85a Mon Sep 17 00:00:00 2001 From: EvansA Date: Mon, 7 Feb 2022 12:05:10 +0300 Subject: [PATCH 02/20] Fix: Shorten overflowing resource links (#1353) * Add ellipsis to long links * add dynamic ellipsis to links * refactor responsive sizes * refactor range selection to resource utils file * adjust overflow widths * restore resources tab for tests * refactor overflow width calculation to utils file * disable resources tab * merge dev --- .../actions/query-action-creator-util.ts | 14 +- .../views/authentication/profile/Profile.tsx | 2 - .../screen-resolution/screen-resolution.ts | 183 ++++++++++++++++++ .../util/resolution-types.ts | 13 ++ .../views/query-runner/request/Request.tsx | 34 ++-- .../request/feedback/FeedbackForm.tsx | 2 +- src/app/views/sidebar/Sidebar.tsx | 2 +- .../resource-explorer/ResourceExplorer.tsx | 4 + .../resource-explorer/ResourceLink.tsx | 40 +++- .../resource-explorer.utils.ts | 90 +++++++++ src/messages/GE_es-ES.json | 3 +- src/messages/GE_fr-FR.json | 5 +- src/messages/GE_ja-JP.json | 5 +- src/messages/GE_pt-BR.json | 7 +- src/messages/GE_ru-RU.json | 5 +- src/tests/utils/proxy-url.spec.ts | 12 +- 16 files changed, 382 insertions(+), 39 deletions(-) create mode 100644 src/app/views/common/screen-resolution/screen-resolution.ts create mode 100644 src/app/views/common/screen-resolution/util/resolution-types.ts diff --git a/src/app/services/actions/query-action-creator-util.ts b/src/app/services/actions/query-action-creator-util.ts index eae931a843..77208b159c 100644 --- a/src/app/services/actions/query-action-creator-util.ts +++ b/src/app/services/actions/query-action-creator-util.ts @@ -11,6 +11,7 @@ import { IAction } from '../../../types/action'; import { ContentType } from '../../../types/enums'; import { IQuery } from '../../../types/query-runner'; import { IRequestOptions } from '../../../types/request'; +import { IStatus } from '../../../types/status'; import { encodeHashCharacters } from '../../utils/query-url-sanitization'; import { authProvider, GraphClient } from '../graph-client'; import { DEFAULT_USER_SCOPES } from '../graph-constants'; @@ -29,13 +30,13 @@ export async function anonymousRequest( query: IQuery, getState: Function ) { + const { proxyUrl, queryRunnerStatus } = getState(); + const { graphUrl, options } = createAnonymousRequest(query, proxyUrl, queryRunnerStatus); dispatch(queryRunningStatus(true)); - const { proxyUrl } = getState(); - const { graphUrl, options } = createAnonymousRequest(query, proxyUrl); return fetch(graphUrl, options); } -export function createAnonymousRequest(query: IQuery, proxyUrl: string) { +export function createAnonymousRequest(query: IQuery, proxyUrl: string, queryRunnerStatus: IStatus) { const escapedUrl = encodeURIComponent(query.sampleUrl); const graphUrl = `${proxyUrl}?url=${escapedUrl}`; const sampleHeaders: any = {}; @@ -47,13 +48,18 @@ export function createAnonymousRequest(query: IQuery, proxyUrl: string) { } const authToken = '{token:https://graph.microsoft.com/}'; - const headers = { + let headers = { Authorization: `Bearer ${authToken}`, 'Content-Type': 'application/json', SdkVersion: 'GraphExplorer/4.0', ...sampleHeaders }; + if (queryRunnerStatus && !queryRunnerStatus.ok) { + const updatedHeaders = { ...headers, 'cache-control': 'no-cache', pragma: 'no-cache' } + headers = updatedHeaders; + } + const options: IRequestOptions = { method: query.selectedVerb, headers diff --git a/src/app/views/authentication/profile/Profile.tsx b/src/app/views/authentication/profile/Profile.tsx index 366e7490ac..f6bd8a70e9 100644 --- a/src/app/views/authentication/profile/Profile.tsx +++ b/src/app/views/authentication/profile/Profile.tsx @@ -5,7 +5,6 @@ import { useDispatch, useSelector } from 'react-redux'; import { geLocale } from '../../../../appLocale'; import { Mode } from '../../../../types/enums'; import { IRootState } from '../../../../types/root'; -import { getPolicies } from '../../../services/actions/ocps-action-creators'; import { getProfileInfo } from '../../../services/actions/profile-action-creators'; import { translateMessage } from '../../../utils/translate-messages'; import { classNames } from '../../classnames'; @@ -22,7 +21,6 @@ const Profile = (props: any) => { useEffect(() => { if (authenticated && !profile) { dispatch(getProfileInfo()); - dispatch(getPolicies()); } }, [authenticated]); diff --git a/src/app/views/common/screen-resolution/screen-resolution.ts b/src/app/views/common/screen-resolution/screen-resolution.ts new file mode 100644 index 0000000000..c2e1ec69d4 --- /dev/null +++ b/src/app/views/common/screen-resolution/screen-resolution.ts @@ -0,0 +1,183 @@ +import { useEffect, useState } from 'react'; +import { ScreenResolution } from './util/resolution-types'; + +interface IResolution { + device: string; + width: { + minimumWidth: number; + maximumWidth: number; + }, + currentScreenWidth: number +} +export const resolution = [ + { + name: ScreenResolution.MOBILE, + dimensions: { + minimumWidth: 100, + maximumWidth: 424 + } + }, + { + name: ScreenResolution.TABLET, + dimensions: { + minimumWidth: 425, + maximumWidth: 510 + } + }, + { + name: ScreenResolution.TABLET_MEDIUM, + dimensions: { + minimumWidth: 511, + maximumWidth: 582 + } + }, + { + name: ScreenResolution.TABLET_LARGE, + dimensions: { + minimumWidth: 583, + maximumWidth: 992 + } + }, + { + name: ScreenResolution.LAPTOP_SMALL, + dimensions: { + minimumWidth: 993, + maximumWidth: 1024 + } + }, + { + name: ScreenResolution.LAPTOP_MEDIUM, + dimensions: { + minimumWidth: 1025, + maximumWidth: 1280 + } + }, + { + name: ScreenResolution.LAPTOP_LARGE, + dimensions: { + minimumWidth: 1281, + maximumWidth: 1440 + } + }, + { + name: ScreenResolution.DESKTOP, + dimensions: { + minimumWidth: 1441, + maximumWidth: 1920 + } + }, + { + name: ScreenResolution.DESKTOP_LARGE, + dimensions: { + minimumWidth: 1921, + maximumWidth: 2560 + } + }, + { + name: ScreenResolution.DESKTOP_XLARGE, + dimensions: { + minimumWidth: 2561, + maximumWidth: 3840 + } + }, + { + name: ScreenResolution.DESKTOP_XXLARGE, + dimensions: { + minimumWidth: 3841, + maximumWidth: 5120 + } + } +] + +export const textOverflowWidthRange = [ + { + key: ScreenResolution.MOBILE, + range: { + minumumOverflowWidth: 200, + maximumOverflowWidth: 210 + } + }, + { + key: ScreenResolution.TABLET, + range: { + minimumOverflowWidth: 265, + maximumOverflowWidth: 320 + } + }, + { + key: ScreenResolution.TABLET_MEDIUM, + range: { + minimumOverflowWidth: 410, + maximumOverflowWidth: 450 + } + }, + { + key: ScreenResolution.TABLET_LARGE, + range: { + minimumOverflowWidth: 485, + maximumOverflowWidth: 700 + } + }, + { + key: ScreenResolution.LAPTOP_SMALL, + range: { + minimumOverflowWidth: 130, + maximumOverflowWidth: 132 + } + }, + { + key: ScreenResolution.LAPTOP_MEDIUM, + range: { + minimumOverflowWidth: 135, + maximumOverflowWidth: 150 + } + }, + { + key: ScreenResolution.LAPTOP_LARGE, + range: { + minimumOverflowWidth: 180, + maximumOverflowWidth: 220 + } + }, + { + key: ScreenResolution.DESKTOP, + range: { + minimumOverflowWidth: 220, + maximumOverflowWidth: 310 + } + }, + { + key: ScreenResolution.DESKTOP_LARGE, + range: { + minimumOverflowWidth: 390, + maximumOverflowWidth: 500 + } + }, + { + key: ScreenResolution.DESKTOP_XLARGE, + range: { + minimumOverflowWidth: 500, + maximumOverflowWidth: 800 + } + } +] + +export const getScreenResolution = (): IResolution => { + const [windowWidth, setWindowWidth] = useState(window.innerWidth); + useEffect(() => { + const handleResize = () => { + setWindowWidth(window.innerWidth) + } + window.addEventListener('resize', handleResize); + + return () => removeEventListener('resize', handleResize) + }, []); + + const screenResolution = resolution.find((item: any) => + windowWidth >= item?.dimensions.minimumWidth && windowWidth <= item?.dimensions.maximumWidth); + return { + device: screenResolution ? screenResolution.name : '', + width: screenResolution?.dimensions ?? { minimumWidth: 0, maximumWidth: 0 }, + currentScreenWidth: windowWidth + } +} \ No newline at end of file diff --git a/src/app/views/common/screen-resolution/util/resolution-types.ts b/src/app/views/common/screen-resolution/util/resolution-types.ts new file mode 100644 index 0000000000..440d6e1f82 --- /dev/null +++ b/src/app/views/common/screen-resolution/util/resolution-types.ts @@ -0,0 +1,13 @@ +export enum ScreenResolution { + MOBILE = 'mobile', + TABLET = 'tablet', + TABLET_MEDIUM = 'tablet_medium', + TABLET_LARGE = 'tablet_large', + LAPTOP_SMALL = 'laptop_small', + LAPTOP_MEDIUM = 'laptop_medium', + LAPTOP_LARGE = 'laptop_large', + DESKTOP = 'desktop', + DESKTOP_LARGE = 'desktop_large', + DESKTOP_XLARGE = 'desktop_xlarge', + DESKTOP_XXLARGE = 'desktop_xxlarge' +} \ No newline at end of file diff --git a/src/app/views/query-runner/request/Request.tsx b/src/app/views/query-runner/request/Request.tsx index f3ed1622d5..d231126258 100644 --- a/src/app/views/query-runner/request/Request.tsx +++ b/src/app/views/query-runner/request/Request.tsx @@ -16,6 +16,7 @@ import { Mode } from '../../../../types/enums'; import { IRequestComponent } from '../../../../types/request'; import { IRootState } from '../../../../types/root'; import { setDimensions } from '../../../services/actions/dimensions-action-creator'; +import { ACCOUNT_TYPE } from '../../../services/graph-constants'; import { translateMessage } from '../../../utils/translate-messages'; import { convertPxToVh, convertVhToPx } from '../../common/dimensions-adjustment'; import { Auth } from './auth'; @@ -42,6 +43,7 @@ export class Request extends Component { const { handleOnEditorChange, mode, + profile, intl: { messages } }: any = this.props; @@ -110,18 +112,21 @@ export class Request extends Component { , ); } - pivotItems.push( - - - ) + if(profile !== ACCOUNT_TYPE.AAD){ + pivotItems.push( + + + ) + } + return pivotItems; } @@ -225,13 +230,14 @@ export class Request extends Component { } function mapStateToProps( - { graphExplorerMode, sampleQuery, theme, sidebarProperties, dimensions }: IRootState) { + { graphExplorerMode, sampleQuery, theme, sidebarProperties, dimensions, profile }: IRootState) { return { mode: graphExplorerMode, sampleBody: sampleQuery.sampleBody, theme, mobileScreen: !!sidebarProperties.mobileScreen, - dimensions + dimensions, + profile: profile?.profileType }; } diff --git a/src/app/views/query-runner/request/feedback/FeedbackForm.tsx b/src/app/views/query-runner/request/feedback/FeedbackForm.tsx index 6786470e10..43ce164dda 100644 --- a/src/app/views/query-runner/request/feedback/FeedbackForm.tsx +++ b/src/app/views/query-runner/request/feedback/FeedbackForm.tsx @@ -96,7 +96,7 @@ export default function FeedbackForm({ activated, dismissSurvey }: any) { autoDismiss: 2, campaignDefinitions: CampaignDefinitions, showEmailAddress: (policies?.data?.email !== 2), - surveyEnabled: (policies?.data?.feedback !== 2), + surveyEnabled: (profile?.profileType !== ACCOUNT_TYPE.AAD), onDismiss: (campaignId: string, submitted: boolean) => { if (submitted) { dispatch(setQueryResponseStatus({ diff --git a/src/app/views/sidebar/Sidebar.tsx b/src/app/views/sidebar/Sidebar.tsx index e9e095141c..2c098a201c 100644 --- a/src/app/views/sidebar/Sidebar.tsx +++ b/src/app/views/sidebar/Sidebar.tsx @@ -6,7 +6,7 @@ import { translateMessage } from '../../utils/translate-messages'; import History from './history/History'; import { ResourceExplorer } from './resource-explorer'; import SampleQueries from './sample-queries/SampleQueries'; - +import { ResourceExplorer } from './resource-explorer'; export const Sidebar = () => { return (
diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index fee805a1d7..6ae42ad96f 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -52,6 +52,7 @@ const unstyledResourceExplorer = (props: any) => { const [isolated, setIsolated] = useState(null); const [searchText, setSearchText] = useState(''); + const [linkLevel, setLinkLevel] = useState(-1); const performSearch = (needle: string, haystack: IResource[]) => { const keyword = needle.toLowerCase(); @@ -129,6 +130,7 @@ const unstyledResourceExplorer = (props: any) => { ]; setItems(tree); setIsolated(navLink); + setLinkLevel(navLink.level); telemetry.trackEvent(eventTypes.LISTITEM_CLICK_EVENT, { ComponentName: componentNames.RESOURCES_ISOLATE_QUERY_LIST_ITEM, @@ -140,6 +142,7 @@ const unstyledResourceExplorer = (props: any) => { setIsolated(null); setSearchText(''); const filtered = getResourcesSupportedByVersion(data, version); + setLinkLevel(-1); setItems(createResourcesList(filtered.children, version)); } @@ -245,6 +248,7 @@ const unstyledResourceExplorer = (props: any) => { link={link} isolateTree={isolateTree} resourceOptionSelected={(activity: string, context: unknown) => resourceOptionSelected(activity, context)} + linkLevel={linkLevel} classes={classes} /> }} diff --git a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx index af719761ef..cc00e2c0d9 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx @@ -2,22 +2,29 @@ import { ContextualMenuItemType, getId, IconButton, IContextualMenuItem, mergeStyleSets, TooltipHost } from '@fluentui/react'; -import React, { CSSProperties } from 'react'; +import React, { useEffect, useState, CSSProperties } from 'react'; import { FormattedMessage } from 'react-intl'; -import { ResourceLinkType, ResourceOptions } from '../../../../types/resources'; +import { IResourceLink, ResourceLinkType, ResourceOptions } from '../../../../types/resources'; import { getStyleFor } from '../../../utils/http-methods.utils'; import { translateMessage } from '../../../utils/translate-messages'; - +import { setMaximumOverflowWidth} from './resource-explorer.utils'; interface IResourceLinkProps { link: any; isolateTree: Function; resourceOptionSelected: Function; + linkLevel: number; classes: any; } const ResourceLink = (props: IResourceLinkProps) => { const { link: resourceLink, classes } = props; + const [resourceLevelOnIsolation, setResourceLevelOnIsolation] = useState(-1); + const [isolationFlag, setIsolationFlag] = useState(false); + + useEffect(() => { + setResourceLevelOnIsolation(props.linkLevel); + }, [isolationFlag]); const tooltipId = getId('tooltip'); const buttonId = getId('targetButton'); @@ -36,6 +43,17 @@ const ResourceLink = (props: IResourceLinkProps) => { const items = getMenuItems(); + const overflowProps = { + resourceLevelOnIsolation, + level: resourceLink.level, + method: resourceLink.method + } + + const isolateResourceLink = (resourceLink_: IResourceLink) => { + setIsolationFlag(true); + props.isolateTree(resourceLink_); + } + return {resourceLink.method && { > {resourceLink.method} } - {resourceLink.name} + + + {resourceLink.name} + + {items.length > 0 && @@ -77,7 +105,7 @@ const ResourceLink = (props: IResourceLinkProps) => { /> } - ; + function getMenuItems() { const menuItems: IContextualMenuItem[] = []; @@ -90,7 +118,7 @@ const ResourceLink = (props: IResourceLinkProps) => { key: 'isolate', text: translateMessage('Isolate'), itemType: ContextualMenuItemType.Normal, - onClick: () => props.isolateTree(resourceLink) + onClick: () => isolateResourceLink(resourceLink) }); } diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 9581432922..240a2ba120 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -7,6 +7,7 @@ import { ResourceLinkType } from '../../../../types/resources'; +import { getScreenResolution, textOverflowWidthRange } from '../../common/screen-resolution/screen-resolution'; interface ITreeFilter { paths: string[]; level: number; @@ -14,6 +15,18 @@ interface ITreeFilter { version: string; } +interface IOverflowWidthRange { + minimumOverflowWidth: number; + maximumOverflowWidth: number; +} + +interface IOverflowProps { + currentScreenWidth: number; + lowestDeviceWidth: number; + highestDeviceWidth: number; + overflowRange: IOverflowWidthRange; +} + export function createResourcesList( source: IResource[], version: string @@ -229,3 +242,80 @@ function flatten(content: IResourceLink[]): IResourceLink[] { }); return result; } + +export function getOverflowWidthRange(resolution: string): IOverflowWidthRange { + const overFlowRange = textOverflowWidthRange.find(k => k.key === resolution); + if (!overFlowRange) { + return { + minimumOverflowWidth: 1000, + maximumOverflowWidth: 2000 + }; + } + return { + minimumOverflowWidth: overFlowRange.range.minimumOverflowWidth || 0, + maximumOverflowWidth: overFlowRange.range.maximumOverflowWidth || 0 + }; +} + +// Adjusts overflow width based on screen resolution +export function updateOverflowWidth(overflowProps: IOverflowProps) { + const { currentScreenWidth, lowestDeviceWidth, highestDeviceWidth, overflowRange } = overflowProps; + const { minimumOverflowWidth, maximumOverflowWidth } = overflowRange; + + return (currentScreenWidth - lowestDeviceWidth) * (maximumOverflowWidth - minimumOverflowWidth) / + (highestDeviceWidth - lowestDeviceWidth) + minimumOverflowWidth; +} + +// adjusts overflow width for each resource link level +export function compensateForLinkIndent(resourceLevelOnIsolation: number, linkLevel: number, method: string) { + const levelCompensation = new Map([ + [1, -20], + [2, 10], + [3, 20], + [4, 30], + [5, 40], + [6, 60], + [7, 70], + [8, 80], + [9, 110], + [10, 120], + [11, 130], + [12, 140], + [13, 150], + [14, 160] + ]) + const currentLevel: number = resourceLevelOnIsolation === -1 ? linkLevel : + linkLevel - resourceLevelOnIsolation; + + if (currentLevel >= 16) { + return 170; + } + let compensation; + compensation = levelCompensation.get(currentLevel); + + if (method) { + compensation = compensation! + 50 + } + return compensation ? compensation : 0; +} + +export function setMaximumOverflowWidth(widthProps: any): string { + const { resourceLevelOnIsolation, level, method } = widthProps; + const { device: resolution, width, currentScreenWidth } = getScreenResolution(); + const compensation = compensateForLinkIndent(resourceLevelOnIsolation, level, method); + const { minimumOverflowWidth, maximumOverflowWidth } = getOverflowWidthRange(resolution); + + const overflowProps = { + currentScreenWidth, + lowestDeviceWidth: width.minimumWidth, + highestDeviceWidth: width.maximumWidth, + overflowRange: { + minimumOverflowWidth, + maximumOverflowWidth + } + } + + if (compensation < 0 && level !== 1 && resourceLevelOnIsolation !== -1) { return '0px'; } + + return `${updateOverflowWidth(overflowProps) - compensation}px` +} diff --git a/src/messages/GE_es-ES.json b/src/messages/GE_es-ES.json index b79ca85884..08f33adc8d 100644 --- a/src/messages/GE_es-ES.json +++ b/src/messages/GE_es-ES.json @@ -428,5 +428,6 @@ "Invalid whitespace in URL": "Espacio en blanco no válido en la dirección URL", "Response content not available due to CORS policy": "El contenido de la respuesta no está disponible en el Probador de Graph debido a la directiva CORS. Puede ejecutar esta solicitud en un cliente de API, como Postman. Más información sobre CORS y cómo funciona", "here": "aquí", - "Invalid version in URL": "Versión no válida en la dirección URL" + "Invalid version in URL": "Versión no válida en la dirección URL", + "More info": "Más información" } diff --git a/src/messages/GE_fr-FR.json b/src/messages/GE_fr-FR.json index e8dff452a4..45f60a8030 100644 --- a/src/messages/GE_fr-FR.json +++ b/src/messages/GE_fr-FR.json @@ -423,10 +423,11 @@ "Query parameters": "Paramètres de requête", "Preview collection": "Afficher un aperçu de la collection", "Download postman collection": "Télécharger la collection Postman", - "Export list as a Postman collection message": "Vous pouvez exporter la liste entière en tant que collection Postman. S’il y a des éléments dans la liste que vous ne souhaitez pas, sélectionnez-les pour les supprimer.", + "Export list as a Postman collection message": "Vous pouvez exporter la liste entière en tant que collection Postman. Si vous ne souhaitez pas utiliser certains éléments de cette liste, sélectionnez-les pour les supprimer.", "Copied": "Copié", "Invalid whitespace in URL": "Espace non valide dans l'URL", "Response content not available due to CORS policy": "Le contenu de la réponse n'est pas disponible dans l’afficheur Graph en raison de la politique CORS. Vous pouvez exécuter cette requête dans un client API, comme Postman. En savoir plus sur CORS et comprendre son fonctionnement", "here": "ici", - "Invalid version in URL": "Version non valide en URL" + "Invalid version in URL": "Version non valide dans l’URL", + "More info": "En savoir plus" } diff --git a/src/messages/GE_ja-JP.json b/src/messages/GE_ja-JP.json index e010bc0d92..2f2f298ebb 100644 --- a/src/messages/GE_ja-JP.json +++ b/src/messages/GE_ja-JP.json @@ -423,10 +423,11 @@ "Query parameters": "クエリ パラメーター", "Preview collection": "プレビュー コレクション", "Download postman collection": "Postman コレクションをダウンロード", - "Export list as a Postman collection message": "リスト全体を Postman コレクションとしてエクスポートできます。リストに不要なアイテムがある場合は、それらを選択して削除します", + "Export list as a Postman collection message": "リスト全体を Postman コレクションとしてエクスポートできます。リストに不要なアイテムがある場合は、それらを選択して削除します。", "Copied": "コピー済み", "Invalid whitespace in URL": "URL 内の空白文字は無効です", "Response content not available due to CORS policy": "CORS ポリシーにより、Graph エクスプローラーでは応答コンテンツを使用できません。この要求は、Postman などの API クライアントで実行できます。CORS の詳細を読み、そのしくみを理解してください", "here": "こちら", - "Invalid version in URL": "URL 内のバージョンが無効です。" + "Invalid version in URL": "URL 内のバージョンが無効です。", + "More info": "詳細情報" } diff --git a/src/messages/GE_pt-BR.json b/src/messages/GE_pt-BR.json index 533ef46638..fd2fd7d39a 100644 --- a/src/messages/GE_pt-BR.json +++ b/src/messages/GE_pt-BR.json @@ -390,7 +390,7 @@ "Path display": "Exibição do caminho", "More path links": "Mais links de caminho", "Resources available": "Recursos disponíveis", - "Selected Resources": "Recursos selecionados", + "Selected Resources": "Recursos Selecionados", "A documentation link for this URL exists. Click learn more to access it": "Existe um link de documentação dessa URL. Clique em Saiba mais para acessar", "Feedback": "Tem comentários?", "Comment question": "Conte-nos mais sobre sua experiência", @@ -423,10 +423,11 @@ "Query parameters": "Parâmetros de consulta", "Preview collection": "Visualizar a coleção", "Download postman collection": "Baixar a coleção de carteiros", - "Export list as a Postman collection message": "Você pode exportar a lista inteira como uma Coleção de carteiros. Se houver itens na lista que você não quer, selecione-os para removê-los", + "Export list as a Postman collection message": "Você pode exportar a lista inteira como uma Coleção do Postman. Se houver itens na lista que você não deseja, selecione-os para removê-los.", "Copied": "Copiado", "Invalid whitespace in URL": "Espaço em branco inválido na URL", "Response content not available due to CORS policy": "O conteúdo da resposta não está disponível no Graph Explorer devido à política CORS. Você pode executar essa solicitação em um cliente de API, como o Postman. Leia mais sobre o CORS e entenda como ele funciona", "here": "aqui", - "Invalid version in URL": "Versão inválida na URL" + "Invalid version in URL": "Versão inválida na URL", + "More info": "Mais informações" } diff --git a/src/messages/GE_ru-RU.json b/src/messages/GE_ru-RU.json index 73d7faf14a..e52cb4b622 100644 --- a/src/messages/GE_ru-RU.json +++ b/src/messages/GE_ru-RU.json @@ -423,10 +423,11 @@ "Query parameters": "Параметры запроса", "Preview collection": "Коллекция предварительных версий", "Download postman collection": "Скачать коллекцию Postman", - "Export list as a Postman collection message": "Можно экспортировать весь список как коллекцию Postman. Если в списке есть элементы, которые вам не нужны, выберите их, чтобы удалить", + "Export list as a Postman collection message": "Можно экспортировать весь список как коллекцию Postman. Если в списке есть элементы, которые вам не нужны, выберите их, чтобы удалить.", "Copied": "Скопировано", "Invalid whitespace in URL": "Недопустимый пробел в URL-адресе", "Response content not available due to CORS policy": "Содержимое отклика недоступно в песочнице Graph из-за политики CORS. Вы можете выполнить этот запрос в клиенте API, таком как Postman. Дополнительные сведения о CORS и том, как это работает", "here": "здесь", - "Invalid version in URL": "Недопустимая версия в URL-адресе" + "Invalid version in URL": "Недопустимая версия в URL-адресе", + "More info": "Дополнительные сведения" } diff --git a/src/tests/utils/proxy-url.spec.ts b/src/tests/utils/proxy-url.spec.ts index 169594da77..080c30ff66 100644 --- a/src/tests/utils/proxy-url.spec.ts +++ b/src/tests/utils/proxy-url.spec.ts @@ -3,6 +3,7 @@ import fetch from 'isomorphic-fetch'; import { isValidHttpsUrl } from '../../app/utils/external-link-validation'; import { createAnonymousRequest } from '../../app/services/actions/query-action-creator-util'; import { IQuery } from '../../types/query-runner'; +import { IStatus } from '../../types/status'; describe('Sandbox api fetch should', () => { @@ -24,7 +25,16 @@ describe('Sandbox api fetch should', () => { sampleBody: '' } - const { graphUrl, options } = createAnonymousRequest(query, proxyUrl); + const queryRunnerStatus: IStatus = { + messageType: 0, + ok: false, + status: 400, + statusText: '', + duration: 100, + hint: '' + } + + const { graphUrl, options } = createAnonymousRequest(query, proxyUrl, queryRunnerStatus); const response = await fetch(graphUrl, options); expect(response.ok).toBe(true); }); From b2a30a3121b8b0342a685c71fba3aca9cafc265d Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Thu, 10 Feb 2022 08:37:52 +0300 Subject: [PATCH 03/20] Update Sidebar.tsx --- src/app/views/sidebar/Sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/sidebar/Sidebar.tsx b/src/app/views/sidebar/Sidebar.tsx index 2c098a201c..e9e095141c 100644 --- a/src/app/views/sidebar/Sidebar.tsx +++ b/src/app/views/sidebar/Sidebar.tsx @@ -6,7 +6,7 @@ import { translateMessage } from '../../utils/translate-messages'; import History from './history/History'; import { ResourceExplorer } from './resource-explorer'; import SampleQueries from './sample-queries/SampleQueries'; -import { ResourceExplorer } from './resource-explorer'; + export const Sidebar = () => { return (
From 14a01552f3d782fa752e2f07e97aebe292c30200 Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 15 Feb 2022 11:19:44 +0300 Subject: [PATCH 04/20] fix overflow bug --- .../sidebar/resource-explorer/resource-explorer.utils.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 240a2ba120..97b2599a82 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -315,7 +315,10 @@ export function setMaximumOverflowWidth(widthProps: any): string { } } - if (compensation < 0 && level !== 1 && resourceLevelOnIsolation !== -1) { return '0px'; } + const overflow = updateOverflowWidth(overflowProps) - compensation; + if (overflow <= 0) { + return '0px'; + } - return `${updateOverflowWidth(overflowProps) - compensation}px` + return `${overflow}px` } From 7ba5e91bd74bec7df56cfb618831d618a34e1b57 Mon Sep 17 00:00:00 2001 From: Evans Aboge Date: Tue, 15 Feb 2022 11:25:07 +0300 Subject: [PATCH 05/20] disable link display --- .../views/sidebar/resource-explorer/resource-explorer.utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 97b2599a82..0db47a13eb 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -316,7 +316,7 @@ export function setMaximumOverflowWidth(widthProps: any): string { } const overflow = updateOverflowWidth(overflowProps) - compensation; - if (overflow <= 0) { + if (overflow < 0) { return '0px'; } From 3675da3802afdc7f101d4c522bf306b4f21bfd4f Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Thu, 10 Feb 2022 10:36:55 +0300 Subject: [PATCH 06/20] Align node items on resource explorer horizontally --- src/app/views/sidebar/resource-explorer/ResourceLink.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx index cc00e2c0d9..2dec1f6943 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx @@ -30,8 +30,8 @@ const ResourceLink = (props: IResourceLinkProps) => { const buttonId = getId('targetButton'); const iconButtonStyles = { - root: { paddingBottom: 10 }, - menuIcon: { fontSize: 20, padding: 10 } + root: { paddingBottom:10, marginTop: -5, marginRight: 2 }, + menuIcon: { fontSize: 20, padding: 5 } }; const methodButtonStyles: CSSProperties = { From 5edb6d7db415bd1e8d0665213046eefd94383f90 Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Wed, 16 Feb 2022 18:13:53 +0300 Subject: [PATCH 07/20] Simplify sortResourceLinks method --- .../sidebar/resource-explorer/resource-explorer.utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 0db47a13eb..2547c501f1 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -78,10 +78,10 @@ export function createResourcesList( } function sortResourceLinks(a: IResourceLink, b: IResourceLink): number { - if (a.links.length === 0 && a.links.length < b.links.length) { + if (a.links.length === 0 && b.links.length > 0) { return -1; } - if (b.links.length === 0 && a.links.length > b.links.length) { + if (b.links.length === 0 && a.links.length > 0) { return 1; } return 0; From d12cafcabdfe38373d8fd27094d43326c672ac6e Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Thu, 17 Feb 2022 10:46:04 +0300 Subject: [PATCH 08/20] Search all resource nodes and expand node if hit is found in child --- src/app/utils/string-operations.ts | 17 ++- .../resource-explorer/ResourceExplorer.tsx | 46 ++---- .../resource-explorer.utils.ts | 143 +++++++++++++----- .../utils/resource-payload-filter.spec.ts | 4 +- 4 files changed, 133 insertions(+), 77 deletions(-) diff --git a/src/app/utils/string-operations.ts b/src/app/utils/string-operations.ts index 51cc302526..4ef0d1d2e1 100644 --- a/src/app/utils/string-operations.ts +++ b/src/app/utils/string-operations.ts @@ -1,11 +1,24 @@ declare global { interface String { - toSentenceCase(): String; + toSentenceCase(): string; + contains(searchText: string): boolean; } } -String.prototype.toSentenceCase = function () { +/** + * Converts the first character to uppercase if character is alphanumeric and the rest to lowercase + */ +String.prototype.toSentenceCase = function (): string { return `${this.charAt(0).toUpperCase()}${this.toLowerCase().slice(1)}`; }; +/** + * Performs a case-insenstive search of a substring within a string and + * returns true if searchString appears as a substring of a string + * @param searchString search string + */ +String.prototype.contains = function (searchString: string): boolean { + return this.toLowerCase().includes(searchString.toLowerCase()); +}; + export {}; diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index 49bedfd157..e46461627a 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -40,29 +40,21 @@ const unstyledResourceExplorer = (props: any) => { { key: 'beta', text: 'beta', iconProps: { iconName: 'PartlyCloudyNight' } } ]; const [version, setVersion] = useState(versions[0].key); - const filteredPayload = getResourcesSupportedByVersion(data, version); - const navigationGroup = createResourcesList(filteredPayload.children, version); + const [searchText, setSearchText] = useState(''); + const filteredPayload = getResourcesSupportedByVersion([...data.children], version, searchText); + const navigationGroup = createResourcesList(filteredPayload, version, searchText); - const [resourceItems, setResourceItems] = useState(filteredPayload.children); + const [resourceItems, setResourceItems] = useState(filteredPayload); const [items, setItems] = useState(navigationGroup); useEffect(() => { setItems(navigationGroup); - setResourceItems(filteredPayload.children) - }, [filteredPayload.children.length]); + setResourceItems(filteredPayload) + }, [filteredPayload.length]); const [isolated, setIsolated] = useState(null); - const [searchText, setSearchText] = useState(''); const [linkLevel, setLinkLevel] = useState(-1); - const performSearch = (needle: string, haystack: IResource[]) => { - const keyword = needle.toLowerCase(); - return haystack.filter((sample: IResource) => { - const name = sample.segment.toLowerCase(); - return name.toLowerCase().includes(keyword); - }); - } - const generateBreadCrumbs = () => { if (!!isolated && isolated.paths.length > 0) { const breadcrumbItems: IBreadcrumbItem[] = []; @@ -86,25 +78,17 @@ const unstyledResourceExplorer = (props: any) => { option: IChoiceGroupOption | undefined): void => { const selectedVersion = option!.key; setVersion(selectedVersion); - const list = getResourcesSupportedByVersion(data, selectedVersion); - const dataSet = (searchText) ? performSearch(searchText, list.children) : list.children; + const dataSet = getResourcesSupportedByVersion([...data.children], selectedVersion, searchText); setResourceItems(dataSet); - setItems(createResourcesList(dataSet, selectedVersion)); + setItems(createResourcesList(dataSet, selectedVersion, searchText)); } - const changeSearchValue = (event: any, value?: string) => { - let filtered: any[] = [...data.children]; - setSearchText(value || ''); - if (value) { - filtered = performSearch(value, filtered); - } - const dataSet = getResourcesSupportedByVersion({ - children: filtered, - labels: data.labels, - segment: data.segment - }, version).children; + const changeSearchValue = async (event: any, value?: string) => { + const trimmedSearchText = value ? value.trim() : ''; + setSearchText(trimmedSearchText); + const dataSet = getResourcesSupportedByVersion([...data.children], version, trimmedSearchText); setResourceItems(dataSet); - setItems(createResourcesList(dataSet, version)); + setItems(createResourcesList(dataSet, version, trimmedSearchText)); } const navigateToBreadCrumb = (ev?: any, item?: IBreadcrumbItem): void => { @@ -142,9 +126,9 @@ const unstyledResourceExplorer = (props: any) => { const disableIsolation = (): void => { setIsolated(null); setSearchText(''); - const filtered = getResourcesSupportedByVersion(data, version); + const filtered = getResourcesSupportedByVersion(data.children, version); setLinkLevel(-1); - setItems(createResourcesList(filtered.children, version)); + setItems(createResourcesList(filtered, version)); } const clickLink = (ev?: React.MouseEvent, item? : INavLink) => { diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 2547c501f1..3ff5f52417 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -7,7 +7,10 @@ import { ResourceLinkType } from '../../../../types/resources'; -import { getScreenResolution, textOverflowWidthRange } from '../../common/screen-resolution/screen-resolution'; +import { + getScreenResolution, + textOverflowWidthRange +} from '../../common/screen-resolution/screen-resolution'; interface ITreeFilter { paths: string[]; level: number; @@ -29,7 +32,8 @@ interface IOverflowProps { export function createResourcesList( source: IResource[], - version: string + version: string, + searchText?: string ): INavLinkGroup[] { function getLinkType({ segment, links }: any): ResourceLinkType { const isGraphFunction = segment.startsWith('microsoft.graph'); @@ -48,20 +52,22 @@ export function createResourcesList( const { segment, children } = parent; const links: IResourceLink[] = []; if (methods.length > 1) { - methods.forEach((method) => { - links.push( - createNavLink( - { + if (!searchText || (searchText && segment.contains(searchText))) { + methods.forEach((method) => { + links.push( + createNavLink( + { + segment, + labels: [], + children: [] + }, segment, - labels: [], - children: [] - }, - segment, - [...paths, segment], - method.toUpperCase() - ) - ); - }); + [...paths, segment], + method.toUpperCase() + ) + ); + }); + } } // versioned children @@ -116,12 +122,16 @@ export function createResourcesList( ? ` (${versionedChildren.length})` : ''; + // if segment name does not contain search text, then found text is in child, so expand this link + const isExpanded = + searchText && !segment.contains(searchText) ? true : false; + return { key, url: key, name: `${segment}${enclosedCounter}`, labels, - isExpanded: false, + isExpanded, parent, level, paths, @@ -173,23 +183,46 @@ export function removeCounter(title: string): string { } export function getResourcesSupportedByVersion( - content: IResource, - version: string -): IResource { - const resources: IResource = { ...content }; - const children: IResource[] = []; + resources: IResource[], + version: string, + searchText?: string +): IResource[] { + let versionedResources: IResource[] = []; + resources.forEach((resource: IResource) => { + if (versionExists(resource, version)) { + resource.children = getResourcesSupportedByVersion( + resource.children || [], + version + ); + versionedResources.push(resource); + } + }); + if (searchText) { + versionedResources = searchResources(versionedResources, searchText); + } + return versionedResources; +} - resources.children.forEach((child: IResource) => { - if (versionExists(child, version)) { - children.push(child); +function searchResources(haystack: IResource[], needle: string): IResource[] { + const foundResources: IResource[] = []; + haystack.forEach((resource: IResource) => { + if (resource.segment.contains(needle)) { + foundResources.push(resource); + return; + } + if (resource.children) { + const foundChildResources = searchResources(resource.children, needle); + if (foundChildResources.length > 0) { + resource.children = foundChildResources; + foundResources.push(resource); + } } }); - resources.children = children; - return resources; + return foundResources; } -export function versionExists(child: IResource, version: string): boolean { - return !!child.labels.find((k) => k.name === version); +export function versionExists(resource: IResource, version: string): boolean { + return resource.labels.some((k) => k.name === version); } export function getAvailableMethods( @@ -244,7 +277,9 @@ function flatten(content: IResourceLink[]): IResourceLink[] { } export function getOverflowWidthRange(resolution: string): IOverflowWidthRange { - const overFlowRange = textOverflowWidthRange.find(k => k.key === resolution); + const overFlowRange = textOverflowWidthRange.find( + (k) => k.key === resolution + ); if (!overFlowRange) { return { minimumOverflowWidth: 1000, @@ -259,15 +294,28 @@ export function getOverflowWidthRange(resolution: string): IOverflowWidthRange { // Adjusts overflow width based on screen resolution export function updateOverflowWidth(overflowProps: IOverflowProps) { - const { currentScreenWidth, lowestDeviceWidth, highestDeviceWidth, overflowRange } = overflowProps; + const { + currentScreenWidth, + lowestDeviceWidth, + highestDeviceWidth, + overflowRange + } = overflowProps; const { minimumOverflowWidth, maximumOverflowWidth } = overflowRange; - return (currentScreenWidth - lowestDeviceWidth) * (maximumOverflowWidth - minimumOverflowWidth) / - (highestDeviceWidth - lowestDeviceWidth) + minimumOverflowWidth; + return ( + ((currentScreenWidth - lowestDeviceWidth) * + (maximumOverflowWidth - minimumOverflowWidth)) / + (highestDeviceWidth - lowestDeviceWidth) + + minimumOverflowWidth + ); } // adjusts overflow width for each resource link level -export function compensateForLinkIndent(resourceLevelOnIsolation: number, linkLevel: number, method: string) { +export function compensateForLinkIndent( + resourceLevelOnIsolation: number, + linkLevel: number, + method: string +) { const levelCompensation = new Map([ [1, -20], [2, 10], @@ -283,9 +331,11 @@ export function compensateForLinkIndent(resourceLevelOnIsolation: number, linkLe [12, 140], [13, 150], [14, 160] - ]) - const currentLevel: number = resourceLevelOnIsolation === -1 ? linkLevel : - linkLevel - resourceLevelOnIsolation; + ]); + const currentLevel: number = + resourceLevelOnIsolation === -1 + ? linkLevel + : linkLevel - resourceLevelOnIsolation; if (currentLevel >= 16) { return 170; @@ -294,16 +344,25 @@ export function compensateForLinkIndent(resourceLevelOnIsolation: number, linkLe compensation = levelCompensation.get(currentLevel); if (method) { - compensation = compensation! + 50 + compensation = compensation! + 50; } return compensation ? compensation : 0; } export function setMaximumOverflowWidth(widthProps: any): string { const { resourceLevelOnIsolation, level, method } = widthProps; - const { device: resolution, width, currentScreenWidth } = getScreenResolution(); - const compensation = compensateForLinkIndent(resourceLevelOnIsolation, level, method); - const { minimumOverflowWidth, maximumOverflowWidth } = getOverflowWidthRange(resolution); + const { + device: resolution, + width, + currentScreenWidth + } = getScreenResolution(); + const compensation = compensateForLinkIndent( + resourceLevelOnIsolation, + level, + method + ); + const { minimumOverflowWidth, maximumOverflowWidth } = + getOverflowWidthRange(resolution); const overflowProps = { currentScreenWidth, @@ -313,12 +372,12 @@ export function setMaximumOverflowWidth(widthProps: any): string { minimumOverflowWidth, maximumOverflowWidth } - } + }; const overflow = updateOverflowWidth(overflowProps) - compensation; if (overflow < 0) { return '0px'; } - return `${overflow}px` + return `${overflow}px`; } diff --git a/src/tests/utils/resource-payload-filter.spec.ts b/src/tests/utils/resource-payload-filter.spec.ts index d889cf3434..9c70c4a4d3 100644 --- a/src/tests/utils/resource-payload-filter.spec.ts +++ b/src/tests/utils/resource-payload-filter.spec.ts @@ -18,8 +18,8 @@ describe('Resource payload should', () => { }); it('return children with version v1.0', async () => { - const resources = getResourcesSupportedByVersion(resource, 'v1.0'); - expect(resources.children.length).toBe(64); + const resources = getResourcesSupportedByVersion(resource.children, 'v1.0'); + expect(resources.length).toBe(64); }); it('return links with version v1.0', async () => { From 03dfea74ed77a49ec21c4e460fb5cde57cf67e4e Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Thu, 24 Feb 2022 11:46:21 +0300 Subject: [PATCH 09/20] Debounce resources search --- package.json | 2 ++ .../sidebar/resource-explorer/ResourceExplorer.tsx | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index dd79f9fb69..171e3667ba 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "jest-sonar-reporter": "2.0.0", "jest-watch-typeahead": "1.0.0", "localforage": "1.7.3", + "lodash.debounce": "^4.0.8", "mini-css-extract-plugin": "1.6.2", "monaco-editor": "0.25.2", "monaco-editor-webpack-plugin": "4.2.0", @@ -92,6 +93,7 @@ "@types/enzyme-adapter-react-16": "1.0.5", "@types/isomorphic-fetch": "0.0.35", "@types/jest": "24.0.6", + "@types/lodash.debounce": "^4.0.6", "@types/react": "17.0.35", "@types/react-dom": "17.0.11", "@types/react-intl": "3.0.0", diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index 64a3e8174d..aced4aa0fe 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -3,9 +3,11 @@ import { IBreadcrumbItem, IChoiceGroupOption, INavLink, INavLinkGroup, Label, Nav, SearchBox, Spinner, SpinnerSize, Stack, styled } from '@fluentui/react'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; +import debouce from 'lodash.debounce'; + import { telemetry, eventTypes, componentNames } from '../../../../telemetry'; import { IQuery } from '../../../../types/query-runner'; @@ -83,7 +85,7 @@ const unstyledResourceExplorer = (props: any) => { setItems(createResourcesList(dataSet, selectedVersion, searchText)); } - const changeSearchValue = async (event: any, value?: string) => { + const changeSearchValue = (event: any, value?: string) => { const trimmedSearchText = value ? value.trim() : ''; setSearchText(trimmedSearchText); const dataSet = getResourcesSupportedByVersion([...data.children], version, trimmedSearchText); @@ -91,6 +93,10 @@ const unstyledResourceExplorer = (props: any) => { setItems(createResourcesList(dataSet, version, trimmedSearchText)); } + const debouncedSearch = useMemo(() => { + return debouce(changeSearchValue, 300); + }, []); + const navigateToBreadCrumb = (ev?: any, item?: IBreadcrumbItem): void => { const iterator = item!.key; if (iterator === '/') { @@ -131,7 +137,7 @@ const unstyledResourceExplorer = (props: any) => { setItems(createResourcesList(filtered, version)); } - const clickLink = (ev?: React.MouseEvent, item?: INavLink) => { + const clickLink = (ev?: React.MouseEvent, item? : INavLink) => { ev!.preventDefault(); item!.isExpanded = !item!.isExpanded; setQuery(item!); @@ -183,7 +189,7 @@ const unstyledResourceExplorer = (props: any) => { {!isolated && <> From d30a4ee25143f537482a7a5b633364238dda8ce0 Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Thu, 24 Feb 2022 15:05:13 +0300 Subject: [PATCH 10/20] Deep copy resources when searching and filtering by version --- .../sidebar/resource-explorer/ResourceExplorer.tsx | 8 +------- .../resource-explorer/resource-explorer.utils.ts | 10 +++++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index aced4aa0fe..21aaf5303c 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -43,7 +43,7 @@ const unstyledResourceExplorer = (props: any) => { ]; const [version, setVersion] = useState(versions[0].key); const [searchText, setSearchText] = useState(''); - const filteredPayload = getResourcesSupportedByVersion([...data.children], version, searchText); + const filteredPayload = getResourcesSupportedByVersion(data.children, version, searchText); const navigationGroup = createResourcesList(filteredPayload, version, searchText); const [resourceItems, setResourceItems] = useState(filteredPayload); @@ -80,17 +80,11 @@ const unstyledResourceExplorer = (props: any) => { option: IChoiceGroupOption | undefined): void => { const selectedVersion = option!.key; setVersion(selectedVersion); - const dataSet = getResourcesSupportedByVersion([...data.children], selectedVersion, searchText); - setResourceItems(dataSet); - setItems(createResourcesList(dataSet, selectedVersion, searchText)); } const changeSearchValue = (event: any, value?: string) => { const trimmedSearchText = value ? value.trim() : ''; setSearchText(trimmedSearchText); - const dataSet = getResourcesSupportedByVersion([...data.children], version, trimmedSearchText); - setResourceItems(dataSet); - setItems(createResourcesList(dataSet, version, trimmedSearchText)); } const debouncedSearch = useMemo(() => { diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 3ff5f52417..c0eead487a 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -188,7 +188,8 @@ export function getResourcesSupportedByVersion( searchText?: string ): IResource[] { let versionedResources: IResource[] = []; - resources.forEach((resource: IResource) => { + const resourcesList = JSON.parse(JSON.stringify(resources)); // deep copy + resourcesList.forEach((resource: IResource) => { if (versionExists(resource, version)) { resource.children = getResourcesSupportedByVersion( resource.children || [], @@ -197,10 +198,9 @@ export function getResourcesSupportedByVersion( versionedResources.push(resource); } }); - if (searchText) { - versionedResources = searchResources(versionedResources, searchText); - } - return versionedResources; + return searchText + ? searchResources(versionedResources, searchText) + : versionedResources; } function searchResources(haystack: IResource[], needle: string): IResource[] { From a2d5d788a152cf43cd2b523ef88e0e6192f1f7e6 Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Wed, 2 Mar 2022 18:23:24 +0300 Subject: [PATCH 11/20] On searching resources, do not expand node if parent node is not expanded. --- .../resource-explorer.utils.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index c0eead487a..5d0b47ce75 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -51,8 +51,12 @@ export function createResourcesList( ): IResourceLink[] { const { segment, children } = parent; const links: IResourceLink[] = []; + const childPaths = [...paths, segment]; if (methods.length > 1) { - if (!searchText || (searchText && segment.contains(searchText))) { + if ( + !searchText || + (searchText && childPaths.some((path) => path.contains(searchText))) + ) { methods.forEach((method) => { links.push( createNavLink( @@ -62,7 +66,7 @@ export function createResourcesList( children: [] }, segment, - [...paths, segment], + childPaths, method.toUpperCase() ) ); @@ -75,9 +79,7 @@ export function createResourcesList( children .filter((child) => versionExists(child, version)) .forEach((versionedChild) => { - links.push( - createNavLink(versionedChild, segment, [...paths, segment]) - ); + links.push(createNavLink(versionedChild, segment, childPaths)); }); return links; @@ -124,7 +126,10 @@ export function createResourcesList( // if segment name does not contain search text, then found text is in child, so expand this link const isExpanded = - searchText && !segment.contains(searchText) ? true : false; + searchText && + ![...paths, segment].some((path) => path.contains(searchText)) + ? true + : false; return { key, From a31219ef25f4586c7a6a551ab0c3305c70a388a0 Mon Sep 17 00:00:00 2001 From: Millicent Achieng Date: Wed, 2 Mar 2022 18:42:24 +0300 Subject: [PATCH 12/20] Use const on variable that's not been reassigned --- .../views/sidebar/resource-explorer/resource-explorer.utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 5d0b47ce75..521428c32e 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -192,7 +192,7 @@ export function getResourcesSupportedByVersion( version: string, searchText?: string ): IResource[] { - let versionedResources: IResource[] = []; + const versionedResources: IResource[] = []; const resourcesList = JSON.parse(JSON.stringify(resources)); // deep copy resourcesList.forEach((resource: IResource) => { if (versionExists(resource, version)) { From f3251a9a6fd25b3462f0200c0b8561451336bf39 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Thu, 3 Mar 2022 09:26:04 +0300 Subject: [PATCH 13/20] switch versions using toggle button --- .../resource-explorer/ResourceExplorer.tsx | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index 21aaf5303c..b8a558a539 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -1,16 +1,16 @@ import { - Breadcrumb, ChoiceGroup, DefaultButton, - IBreadcrumbItem, IChoiceGroupOption, INavLink, INavLinkGroup, Label, Nav, SearchBox, Spinner, SpinnerSize, - Stack, styled + Breadcrumb, DefaultButton, + IBreadcrumbItem, INavLink, INavLinkGroup, Label, Nav, + SearchBox, Spinner, SpinnerSize, + Stack, styled, Toggle } from '@fluentui/react'; +import debouce from 'lodash.debounce'; import React, { useEffect, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; -import debouce from 'lodash.debounce'; -import { telemetry, eventTypes, componentNames } from '../../../../telemetry'; +import { componentNames, eventTypes, telemetry } from '../../../../telemetry'; import { IQuery } from '../../../../types/query-runner'; - import { IResource, IResourceLink, ResourceLinkType, ResourceOptions } from '../../../../types/resources'; import { IRootState } from '../../../../types/root'; import { setSampleQuery } from '../../../services/actions/query-input-action-creators'; @@ -76,9 +76,8 @@ const unstyledResourceExplorer = (props: any) => { dispatch(addResourcePaths(getResourcePaths(item, version))); } - const changeVersion = (ev: React.FormEvent | undefined, - option: IChoiceGroupOption | undefined): void => { - const selectedVersion = option!.key; + const changeVersion = (_event: React.MouseEvent, checked?: boolean | undefined): void => { + const selectedVersion = checked ? versions[0].key : versions[1].key; setVersion(selectedVersion); } @@ -131,7 +130,7 @@ const unstyledResourceExplorer = (props: any) => { setItems(createResourcesList(filtered, version)); } - const clickLink = (ev?: React.MouseEvent, item? : INavLink) => { + const clickLink = (ev?: React.MouseEvent, item?: INavLink) => { ev!.preventDefault(); item!.isExpanded = !item!.isExpanded; setQuery(item!); @@ -189,10 +188,10 @@ const unstyledResourceExplorer = (props: any) => { />
- From e048a561525f1a38521460dbd09b7dea1fe57374 Mon Sep 17 00:00:00 2001 From: EvansA Date: Mon, 7 Mar 2022 18:06:38 +0300 Subject: [PATCH 14/20] fix: ellipsis on resources (#1533) --- .../screen-resolution/screen-resolution.ts | 183 ------------------ .../util/resolution-types.ts | 13 -- .../resource-explorer/ResourceLink.tsx | 45 ++--- .../resource-explorer.utils.ts | 123 +----------- .../resource-explorer/resources.styles.ts | 8 +- 5 files changed, 18 insertions(+), 354 deletions(-) delete mode 100644 src/app/views/common/screen-resolution/screen-resolution.ts delete mode 100644 src/app/views/common/screen-resolution/util/resolution-types.ts diff --git a/src/app/views/common/screen-resolution/screen-resolution.ts b/src/app/views/common/screen-resolution/screen-resolution.ts deleted file mode 100644 index c2e1ec69d4..0000000000 --- a/src/app/views/common/screen-resolution/screen-resolution.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { useEffect, useState } from 'react'; -import { ScreenResolution } from './util/resolution-types'; - -interface IResolution { - device: string; - width: { - minimumWidth: number; - maximumWidth: number; - }, - currentScreenWidth: number -} -export const resolution = [ - { - name: ScreenResolution.MOBILE, - dimensions: { - minimumWidth: 100, - maximumWidth: 424 - } - }, - { - name: ScreenResolution.TABLET, - dimensions: { - minimumWidth: 425, - maximumWidth: 510 - } - }, - { - name: ScreenResolution.TABLET_MEDIUM, - dimensions: { - minimumWidth: 511, - maximumWidth: 582 - } - }, - { - name: ScreenResolution.TABLET_LARGE, - dimensions: { - minimumWidth: 583, - maximumWidth: 992 - } - }, - { - name: ScreenResolution.LAPTOP_SMALL, - dimensions: { - minimumWidth: 993, - maximumWidth: 1024 - } - }, - { - name: ScreenResolution.LAPTOP_MEDIUM, - dimensions: { - minimumWidth: 1025, - maximumWidth: 1280 - } - }, - { - name: ScreenResolution.LAPTOP_LARGE, - dimensions: { - minimumWidth: 1281, - maximumWidth: 1440 - } - }, - { - name: ScreenResolution.DESKTOP, - dimensions: { - minimumWidth: 1441, - maximumWidth: 1920 - } - }, - { - name: ScreenResolution.DESKTOP_LARGE, - dimensions: { - minimumWidth: 1921, - maximumWidth: 2560 - } - }, - { - name: ScreenResolution.DESKTOP_XLARGE, - dimensions: { - minimumWidth: 2561, - maximumWidth: 3840 - } - }, - { - name: ScreenResolution.DESKTOP_XXLARGE, - dimensions: { - minimumWidth: 3841, - maximumWidth: 5120 - } - } -] - -export const textOverflowWidthRange = [ - { - key: ScreenResolution.MOBILE, - range: { - minumumOverflowWidth: 200, - maximumOverflowWidth: 210 - } - }, - { - key: ScreenResolution.TABLET, - range: { - minimumOverflowWidth: 265, - maximumOverflowWidth: 320 - } - }, - { - key: ScreenResolution.TABLET_MEDIUM, - range: { - minimumOverflowWidth: 410, - maximumOverflowWidth: 450 - } - }, - { - key: ScreenResolution.TABLET_LARGE, - range: { - minimumOverflowWidth: 485, - maximumOverflowWidth: 700 - } - }, - { - key: ScreenResolution.LAPTOP_SMALL, - range: { - minimumOverflowWidth: 130, - maximumOverflowWidth: 132 - } - }, - { - key: ScreenResolution.LAPTOP_MEDIUM, - range: { - minimumOverflowWidth: 135, - maximumOverflowWidth: 150 - } - }, - { - key: ScreenResolution.LAPTOP_LARGE, - range: { - minimumOverflowWidth: 180, - maximumOverflowWidth: 220 - } - }, - { - key: ScreenResolution.DESKTOP, - range: { - minimumOverflowWidth: 220, - maximumOverflowWidth: 310 - } - }, - { - key: ScreenResolution.DESKTOP_LARGE, - range: { - minimumOverflowWidth: 390, - maximumOverflowWidth: 500 - } - }, - { - key: ScreenResolution.DESKTOP_XLARGE, - range: { - minimumOverflowWidth: 500, - maximumOverflowWidth: 800 - } - } -] - -export const getScreenResolution = (): IResolution => { - const [windowWidth, setWindowWidth] = useState(window.innerWidth); - useEffect(() => { - const handleResize = () => { - setWindowWidth(window.innerWidth) - } - window.addEventListener('resize', handleResize); - - return () => removeEventListener('resize', handleResize) - }, []); - - const screenResolution = resolution.find((item: any) => - windowWidth >= item?.dimensions.minimumWidth && windowWidth <= item?.dimensions.maximumWidth); - return { - device: screenResolution ? screenResolution.name : '', - width: screenResolution?.dimensions ?? { minimumWidth: 0, maximumWidth: 0 }, - currentScreenWidth: windowWidth - } -} \ No newline at end of file diff --git a/src/app/views/common/screen-resolution/util/resolution-types.ts b/src/app/views/common/screen-resolution/util/resolution-types.ts deleted file mode 100644 index 440d6e1f82..0000000000 --- a/src/app/views/common/screen-resolution/util/resolution-types.ts +++ /dev/null @@ -1,13 +0,0 @@ -export enum ScreenResolution { - MOBILE = 'mobile', - TABLET = 'tablet', - TABLET_MEDIUM = 'tablet_medium', - TABLET_LARGE = 'tablet_large', - LAPTOP_SMALL = 'laptop_small', - LAPTOP_MEDIUM = 'laptop_medium', - LAPTOP_LARGE = 'laptop_large', - DESKTOP = 'desktop', - DESKTOP_LARGE = 'desktop_large', - DESKTOP_XLARGE = 'desktop_xlarge', - DESKTOP_XXLARGE = 'desktop_xxlarge' -} \ No newline at end of file diff --git a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx index 2dec1f6943..e6b2bd0d62 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceLink.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceLink.tsx @@ -2,13 +2,12 @@ import { ContextualMenuItemType, getId, IconButton, IContextualMenuItem, mergeStyleSets, TooltipHost } from '@fluentui/react'; -import React, { useEffect, useState, CSSProperties } from 'react'; +import React, { CSSProperties } from 'react'; import { FormattedMessage } from 'react-intl'; -import { IResourceLink, ResourceLinkType, ResourceOptions } from '../../../../types/resources'; +import { ResourceLinkType, ResourceOptions } from '../../../../types/resources'; import { getStyleFor } from '../../../utils/http-methods.utils'; import { translateMessage } from '../../../utils/translate-messages'; -import { setMaximumOverflowWidth} from './resource-explorer.utils'; interface IResourceLinkProps { link: any; isolateTree: Function; @@ -19,16 +18,11 @@ interface IResourceLinkProps { const ResourceLink = (props: IResourceLinkProps) => { const { link: resourceLink, classes } = props; - const [resourceLevelOnIsolation, setResourceLevelOnIsolation] = useState(-1); - const [isolationFlag, setIsolationFlag] = useState(false); - - useEffect(() => { - setResourceLevelOnIsolation(props.linkLevel); - }, [isolationFlag]); const tooltipId = getId('tooltip'); const buttonId = getId('targetButton'); + const iconButtonStyles = { root: { paddingBottom:10, marginTop: -5, marginRight: 2 }, menuIcon: { fontSize: 20, padding: 5 } @@ -43,17 +37,6 @@ const ResourceLink = (props: IResourceLinkProps) => { const items = getMenuItems(); - const overflowProps = { - resourceLevelOnIsolation, - level: resourceLink.level, - method: resourceLink.method - } - - const isolateResourceLink = (resourceLink_: IResourceLink) => { - setIsolationFlag(true); - props.isolateTree(resourceLink_); - } - return {resourceLink.method && { > {resourceLink.method} } - - - {resourceLink.name} + + + {resourceLink.name} + - {items.length > 0 && { role='button' id={buttonId} aria-describedby={tooltipId} - className={linkStyle.button} styles={iconButtonStyles} menuIconProps={{ iconName: 'MoreVertical' }} title={translateMessage('More actions')} @@ -118,7 +94,7 @@ const ResourceLink = (props: IResourceLinkProps) => { key: 'isolate', text: translateMessage('Isolate'), itemType: ContextualMenuItemType.Normal, - onClick: () => isolateResourceLink(resourceLink) + onClick: () => props.isolateTree(resourceLink) }); } @@ -136,8 +112,9 @@ const ResourceLink = (props: IResourceLinkProps) => { const linkStyle = mergeStyleSets( { - link: { display: 'flex', lineHeight: 'normal' }, - button: { float: 'right', position: 'absolute', right: 0 } + link: { display: 'flex', lineHeight: 'normal', width: '100%', overflow: 'hidden' }, + resourceLinkNameContainer: { textAlign: 'left', flex: '1', overflow:'hidden', display: 'flex' }, + resourceLinkText: { textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap' } } ); diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index 521428c32e..f1a03cd465 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -6,11 +6,6 @@ import { IResourceLink, ResourceLinkType } from '../../../../types/resources'; - -import { - getScreenResolution, - textOverflowWidthRange -} from '../../common/screen-resolution/screen-resolution'; interface ITreeFilter { paths: string[]; level: number; @@ -18,18 +13,6 @@ interface ITreeFilter { version: string; } -interface IOverflowWidthRange { - minimumOverflowWidth: number; - maximumOverflowWidth: number; -} - -interface IOverflowProps { - currentScreenWidth: number; - lowestDeviceWidth: number; - highestDeviceWidth: number; - overflowRange: IOverflowWidthRange; -} - export function createResourcesList( source: IResource[], version: string, @@ -127,7 +110,7 @@ export function createResourcesList( // if segment name does not contain search text, then found text is in child, so expand this link const isExpanded = searchText && - ![...paths, segment].some((path) => path.contains(searchText)) + ![...paths, segment].some((path) => path.contains(searchText)) ? true : false; @@ -281,108 +264,4 @@ function flatten(content: IResourceLink[]): IResourceLink[] { return result; } -export function getOverflowWidthRange(resolution: string): IOverflowWidthRange { - const overFlowRange = textOverflowWidthRange.find( - (k) => k.key === resolution - ); - if (!overFlowRange) { - return { - minimumOverflowWidth: 1000, - maximumOverflowWidth: 2000 - }; - } - return { - minimumOverflowWidth: overFlowRange.range.minimumOverflowWidth || 0, - maximumOverflowWidth: overFlowRange.range.maximumOverflowWidth || 0 - }; -} - -// Adjusts overflow width based on screen resolution -export function updateOverflowWidth(overflowProps: IOverflowProps) { - const { - currentScreenWidth, - lowestDeviceWidth, - highestDeviceWidth, - overflowRange - } = overflowProps; - const { minimumOverflowWidth, maximumOverflowWidth } = overflowRange; - - return ( - ((currentScreenWidth - lowestDeviceWidth) * - (maximumOverflowWidth - minimumOverflowWidth)) / - (highestDeviceWidth - lowestDeviceWidth) + - minimumOverflowWidth - ); -} - -// adjusts overflow width for each resource link level -export function compensateForLinkIndent( - resourceLevelOnIsolation: number, - linkLevel: number, - method: string -) { - const levelCompensation = new Map([ - [1, -20], - [2, 10], - [3, 20], - [4, 30], - [5, 40], - [6, 60], - [7, 70], - [8, 80], - [9, 110], - [10, 120], - [11, 130], - [12, 140], - [13, 150], - [14, 160] - ]); - const currentLevel: number = - resourceLevelOnIsolation === -1 - ? linkLevel - : linkLevel - resourceLevelOnIsolation; - - if (currentLevel >= 16) { - return 170; - } - let compensation; - compensation = levelCompensation.get(currentLevel); - - if (method) { - compensation = compensation! + 50; - } - return compensation ? compensation : 0; -} - -export function setMaximumOverflowWidth(widthProps: any): string { - const { resourceLevelOnIsolation, level, method } = widthProps; - const { - device: resolution, - width, - currentScreenWidth - } = getScreenResolution(); - const compensation = compensateForLinkIndent( - resourceLevelOnIsolation, - level, - method - ); - const { minimumOverflowWidth, maximumOverflowWidth } = - getOverflowWidthRange(resolution); - - const overflowProps = { - currentScreenWidth, - lowestDeviceWidth: width.minimumWidth, - highestDeviceWidth: width.maximumWidth, - overflowRange: { - minimumOverflowWidth, - maximumOverflowWidth - } - }; - const overflow = updateOverflowWidth(overflowProps) - compensation; - if (overflow < 0) { - return '0px'; - } - - return `${overflow}px`; -} diff --git a/src/app/views/sidebar/resource-explorer/resources.styles.ts b/src/app/views/sidebar/resource-explorer/resources.styles.ts index 50fd229121..5b0cd48231 100644 --- a/src/app/views/sidebar/resource-explorer/resources.styles.ts +++ b/src/app/views/sidebar/resource-explorer/resources.styles.ts @@ -20,10 +20,14 @@ export const resourceExplorerStyles = (theme: ITheme) => { export const navStyles: any = (properties: any) => ({ chevronIcon: [ properties.isExpanded && { - transform: 'rotate(0deg)' + transform: 'rotate(0deg)', + position: 'relative', + top: '-3px' }, !properties.isExpanded && { - transform: 'rotate(-90deg)' + transform: 'rotate(-90deg)', + position: 'relative', + top: '-3px' } ], chevronButton: [ From e5bb4b1f51f3a8394dd056c11e8452b4a5e32f0f Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Wed, 9 Mar 2022 13:23:13 +0300 Subject: [PATCH 15/20] generate flattened postman collection --- .../resource-explorer/panels/postman.util.ts | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/panels/postman.util.ts b/src/app/views/sidebar/resource-explorer/panels/postman.util.ts index cc93b2b747..e28ed6cddd 100644 --- a/src/app/views/sidebar/resource-explorer/panels/postman.util.ts +++ b/src/app/views/sidebar/resource-explorer/panels/postman.util.ts @@ -23,37 +23,36 @@ export function generatePostmanCollection( } function generateItemsFromPaths(resources: IResourceLink[]): Item[] { - const folderNames = resources - .map((resource) => { - if (resource.paths.length > 1) { - return resource.paths[1]; - } - }) - .filter((value, i, arr) => arr.indexOf(value) === i) // selects distinct folder names - .sort(); + const list: Item[] = []; + resources.forEach(resource => { + const { + method, + name, + url, + version, + paths: path + } = resource; + + path.shift(); + path.unshift(version!); - const folderItems: any = folderNames.map((folder) => { - const items = resources - .filter((resource) => resource.url.match(`^/${folder}/?`)) - .map((resource) => { - const { method, url, version, paths: path } = resource; - path.shift(); - path.unshift(version!); - const item: Item = { - name: url, - request: { - method: method!, - url: { - raw: `${GRAPH_URL}/${version}${url}`, - protocol: 'https', - host: ['graph', 'microsoft', 'com'], - path - } - } - }; - return item; - }); - return { name: folder, item: items }; + const item: Item = { + name, + request: { + method: method!, + url: { + raw: `${GRAPH_URL}/${version}${url}`, + protocol: 'https', + host: [ + 'graph', + 'microsoft', + 'com' + ], + path + } + } + } + list.push(item); }); - return folderItems; + return list; } From da42774a74322a6ef17f81c8d89bb7d98ec755c9 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Wed, 9 Mar 2022 13:41:38 +0300 Subject: [PATCH 16/20] add multiple versions to collection --- src/app/views/sidebar/resource-explorer/panels/postman.util.ts | 2 +- .../views/sidebar/resource-explorer/resource-explorer.utils.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/views/sidebar/resource-explorer/panels/postman.util.ts b/src/app/views/sidebar/resource-explorer/panels/postman.util.ts index e28ed6cddd..801324e327 100644 --- a/src/app/views/sidebar/resource-explorer/panels/postman.util.ts +++ b/src/app/views/sidebar/resource-explorer/panels/postman.util.ts @@ -37,7 +37,7 @@ function generateItemsFromPaths(resources: IResourceLink[]): Item[] { path.unshift(version!); const item: Item = { - name, + name: `${name}-${version}`, request: { method: method!, url: { diff --git a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts index f1a03cd465..94b59a96c4 100644 --- a/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts +++ b/src/app/views/sidebar/resource-explorer/resource-explorer.utils.ts @@ -248,6 +248,7 @@ export function getResourcePaths( content.forEach((element: IResourceLink) => { element.version = version; element.url = `${getUrlFromLink(element)}`; + element.key = element.key?.includes(version) ? element.key : `${element.key}-${element.version}` }); } return content; From 094d2082f9a5eb30627ed4afce930568e74b3f04 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Wed, 9 Mar 2022 16:14:55 +0300 Subject: [PATCH 17/20] remove folder collections from test --- .../sidebar/resource-explorer/panels/postman.util.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/panels/postman.util.spec.ts b/src/app/views/sidebar/resource-explorer/panels/postman.util.spec.ts index c214a37a75..06fe4535e6 100644 --- a/src/app/views/sidebar/resource-explorer/panels/postman.util.spec.ts +++ b/src/app/views/sidebar/resource-explorer/panels/postman.util.spec.ts @@ -12,7 +12,6 @@ describe('Postman collection should', () => { const item: any = filtered.links[0]; const paths = getResourcePaths(item, version); const collection = generatePostmanCollection(paths); - const folderItems: any = collection.item[0]; - expect(folderItems.item.length).toBe(33); + expect(collection.item.length).toBe(33); }); }); From 2266cf082d3a82df39829ee1af80231e692ca53e Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Mon, 14 Mar 2022 17:38:08 +0300 Subject: [PATCH 18/20] discard entire collection without opening preview --- package-lock.json | 226 ++++++------------ package.json | 3 +- .../command-options/CommandOptions.tsx | 56 ++++- src/messages/GE.json | 4 +- 4 files changed, 129 insertions(+), 160 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7754d47e01..688e8e3cb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2959,6 +2959,15 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==" }, + "@types/lodash.debounce": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz", + "integrity": "sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, "@types/lodash.isequal": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.5.tgz", @@ -3237,7 +3246,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -3739,14 +3747,11 @@ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "requires": { "cliui": "^6.0.0", - "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } @@ -3754,11 +3759,7 @@ "yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==" } } }, @@ -3897,14 +3898,12 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, "array-flatten": { "version": "1.1.1", @@ -3931,8 +3930,7 @@ "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "array.prototype.filter": { "version": "1.0.1", @@ -3986,8 +3984,7 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "ast-types-flow": { "version": "0.0.7", @@ -4015,8 +4012,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "atob-lite": { "version": "2.0.0", @@ -4168,8 +4164,11 @@ "dev": true }, "fsevents": { - "version": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true }, "has-flag": { "version": "4.0.0", @@ -4431,7 +4430,6 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -4458,7 +4456,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", "test-exclude": "^6.0.0" } }, @@ -4487,8 +4484,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^4.1.0" } }, "color-convert": { @@ -4508,7 +4504,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -4576,7 +4571,6 @@ "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", @@ -4606,8 +4600,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "^3.1.0" }, "dependencies": { "is-glob": { @@ -4818,7 +4811,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -5014,7 +5006,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -5026,7 +5017,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -5035,7 +5025,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -5044,7 +5033,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -5055,7 +5043,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -5064,7 +5051,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -5075,7 +5061,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -5085,8 +5070,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -5141,7 +5125,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -5186,8 +5169,7 @@ "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "compressible": { "version": "2.0.18", @@ -5272,8 +5254,7 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { "version": "2.6.4", @@ -5533,8 +5514,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "dedent": { "version": "0.7.0", @@ -5595,7 +5575,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -6038,6 +6017,31 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, "eslint": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", @@ -6330,10 +6334,7 @@ "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" }, "p-limit": { "version": "1.3.0", @@ -6874,7 +6875,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -6884,7 +6884,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -7167,8 +7166,7 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "fork-ts-checker-webpack-plugin": { "version": "7.0.0-alpha.12", @@ -7293,15 +7291,6 @@ "mime-types": "^2.1.12" } }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "requires": { - "fetch-blob": "^3.1.2" - } - }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -7448,8 +7437,7 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "glob": { "version": "7.2.0", @@ -7592,7 +7580,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -7603,7 +7590,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -7613,7 +7599,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7622,7 +7607,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7633,7 +7617,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7971,7 +7954,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -8018,8 +8000,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.2.4", @@ -8055,7 +8036,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -8072,7 +8052,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -8087,8 +8066,7 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "2.1.1", @@ -8160,7 +8138,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -8279,8 +8256,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isomorphic-fetch": { "version": "3.0.0", @@ -9930,8 +9906,7 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "kleur": { "version": "3.0.3", @@ -10150,8 +10125,7 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, "map-stream": { "version": "0.1.0", @@ -10163,7 +10137,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -10297,7 +10270,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -10307,7 +10279,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -10543,7 +10514,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -10554,7 +10524,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -10563,7 +10532,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -10572,7 +10540,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -10581,7 +10548,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -10591,8 +10557,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -10600,7 +10565,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -10630,7 +10594,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "^3.0.0" } @@ -10867,8 +10830,7 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "path-exists": { "version": "4.0.0", @@ -12048,7 +12010,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -12129,8 +12090,7 @@ "repeat-element": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" }, "repeat-string": { "version": "1.6.1", @@ -12189,8 +12149,7 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "resolve.exports": { "version": "1.1.0", @@ -12200,8 +12159,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "retry": { "version": "0.13.1", @@ -12328,7 +12286,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "~0.1.10" } @@ -12653,7 +12610,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -12665,7 +12621,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -12731,7 +12686,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -12747,7 +12701,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -12756,7 +12709,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -12765,7 +12717,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -12774,7 +12725,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -12783,7 +12733,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -12794,7 +12743,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -12803,7 +12751,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -12814,7 +12761,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -12824,14 +12770,12 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -12839,7 +12783,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -12850,7 +12793,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -12861,7 +12803,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "^3.2.0" }, @@ -12870,7 +12811,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -12906,7 +12846,6 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, "requires": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -12982,7 +12921,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -13081,7 +13019,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -13091,7 +13028,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -13100,7 +13036,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -13109,7 +13044,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -13120,7 +13054,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -13129,7 +13062,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -13140,7 +13072,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -13150,8 +13081,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -13525,7 +13455,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -13534,7 +13463,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -13545,7 +13473,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -13761,7 +13688,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -13791,7 +13717,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -13801,7 +13726,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -13812,7 +13736,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -13822,8 +13745,7 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" } } }, @@ -13843,8 +13765,7 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { "version": "0.11.0", @@ -13897,8 +13818,7 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, "util-deprecate": { "version": "1.0.2", @@ -14019,12 +13939,6 @@ "minimalistic-assert": "^1.0.0" } }, - "web-streams-polyfill": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", - "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", - "dev": true - }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 9c7872ca38..692d127743 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "@types/enzyme-adapter-react-16": "1.0.5", "@types/isomorphic-fetch": "0.0.35", "@types/jest": "24.0.6", + "@types/lodash.debounce": "^4.0.6", "@types/react": "17.0.35", "@types/react-dom": "17.0.11", "@types/react-intl": "3.0.0", @@ -123,4 +124,4 @@ "reportFile": "test-report.xml", "indent": 4 } -} \ No newline at end of file +} diff --git a/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx b/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx index 69b36fb490..4bf0ec3b03 100644 --- a/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx +++ b/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx @@ -1,19 +1,29 @@ -import { CommandBar, CommandBarButton, getTheme, IButtonProps, ICommandBarItemProps } from '@fluentui/react'; +import { + CommandBar, CommandBarButton, DefaultButton, Dialog, DialogFooter, DialogType, + getId, getTheme, IButtonProps, ICommandBarItemProps, PrimaryButton +} from '@fluentui/react'; import React, { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { IRootState } from '../../../../../types/root'; +import { removeResourcePaths } from '../../../../services/actions/resource-explorer-action-creators'; import { translateMessage } from '../../../../utils/translate-messages'; import PathsReview from '../panels/PathsReview'; import { resourceExplorerStyles } from '../resources.styles'; + interface ICommandOptions { version: string; } const CommandOptions = (props: ICommandOptions) => { + const dispatch = useDispatch(); const [isOpen, setIsOpen] = useState(false); + const [isDialogHidden, setIsDialogHidden] = useState(true); const { version } = props; const theme = getTheme(); + const { resources: { paths } } = useSelector((state: IRootState) => state); const itemStyles = resourceExplorerStyles(theme).itemStyles; const commandStyles = resourceExplorerStyles(theme).commandBarStyles; const options: ICommandBarItemProps[] = [ @@ -25,20 +35,47 @@ const CommandOptions = (props: ICommandOptions) => { } ]; + const farItems: ICommandBarItemProps[] = [ + { + key: 'delete-all', + iconProps: { iconName: 'Delete' }, + style: { + marginLeft: 30 + }, + onClick: () => toggleIsDialogHidden() + } + ] + const toggleSelectedResourcesPreview = () => { let open = isOpen; open = !open; setIsOpen(open); } + const removeAllResources = () => { + dispatch(removeResourcePaths(paths)); + } + const CustomButton: React.FunctionComponent = (props_: any) => { - return ; + return ; + }; + + const deleteResourcesDialogProps = { + type: DialogType.normal, + title: translateMessage('Delete collection'), + closeButtonAriaLabel: 'Close', + subText: translateMessage('Do you want to remove all the items you have added to the collection?') }; + const toggleIsDialogHidden = () => { + setIsDialogHidden(!isDialogHidden); + } + return (
{ version={version} toggleSelectedResourcesPreview={toggleSelectedResourcesPreview} /> +
) } diff --git a/src/messages/GE.json b/src/messages/GE.json index a4ab6dddc4..6f15ece2fe 100644 --- a/src/messages/GE.json +++ b/src/messages/GE.json @@ -431,5 +431,7 @@ "Invalid version in URL": "Invalid version in URL", "More info": "More info", "Could not connect to the sandbox": "Could not connect to the sandbox", - "Failed to get profile information": "Failed to get profile information" + "Failed to get profile information": "Failed to get profile information", + "Do you want to remove all the items you have added to the collection?": "Do you want to remove all the items you have added to the collection?", + "Delete collection": "Delete collection" } \ No newline at end of file From 841973183feb8ffec26de55999d6115d927d6703 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Tue, 15 Mar 2022 12:17:30 +0300 Subject: [PATCH 19/20] make label inline --- .../sidebar/resource-explorer/ResourceExplorer.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx index b8a558a539..a650b17c22 100644 --- a/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx +++ b/src/app/views/sidebar/resource-explorer/ResourceExplorer.tsx @@ -77,7 +77,7 @@ const unstyledResourceExplorer = (props: any) => { } const changeVersion = (_event: React.MouseEvent, checked?: boolean | undefined): void => { - const selectedVersion = checked ? versions[0].key : versions[1].key; + const selectedVersion = checked ? versions[1].key : versions[0].key; setVersion(selectedVersion); } @@ -188,11 +188,11 @@ const unstyledResourceExplorer = (props: any) => { />
- } From 216706f22a81fa57591a1408702dafd44c411250 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Wed, 30 Mar 2022 06:46:11 +0300 Subject: [PATCH 20/20] remove caret; add ariaLabel --- package.json | 4 ++-- .../resource-explorer/command-options/CommandOptions.tsx | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 64cbc14725..fe66da6d1c 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "@types/enzyme-adapter-react-16": "1.0.5", "@types/isomorphic-fetch": "0.0.35", "@types/jest": "24.0.6", - "@types/lodash.debounce": "^4.0.6", + "@types/lodash.debounce": "4.0.6", "@types/react": "17.0.35", "@types/react-dom": "17.0.11", "@types/react-intl": "3.0.0", @@ -124,4 +124,4 @@ "reportFile": "test-report.xml", "indent": 4 } -} +} \ No newline at end of file diff --git a/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx b/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx index 4bf0ec3b03..6949902cd6 100644 --- a/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx +++ b/src/app/views/sidebar/resource-explorer/command-options/CommandOptions.tsx @@ -30,6 +30,7 @@ const CommandOptions = (props: ICommandOptions) => { { key: 'preview', text: translateMessage('Preview collection'), + ariaLabel: translateMessage('Preview collection'), iconProps: { iconName: 'View' }, onClick: () => toggleSelectedResourcesPreview() } @@ -42,6 +43,7 @@ const CommandOptions = (props: ICommandOptions) => { style: { marginLeft: 30 }, + ariaLabel: translateMessage('Delete'), onClick: () => toggleIsDialogHidden() } ]