Skip to content

Commit 1099e03

Browse files
authored
Chore: Release 10.0.0 (#3146)
* Fix: Dependabot upgrades - March (#3061) * Feature: support text csv (#3123)
1 parent 3a9efd3 commit 1099e03

File tree

9 files changed

+613
-211
lines changed

9 files changed

+613
-211
lines changed

package-lock.json

Lines changed: 521 additions & 151 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "graph-explorer-v2",
3-
"version": "9.8.0",
3+
"version": "10.0.0",
44
"private": true,
55
"dependencies": {
66
"@augloop/types-core": "file:packages/types-core-2.16.189.tgz",
7-
"@axe-core/webdriverjs": "4.8.4",
7+
"@axe-core/webdriverjs": "4.8.5",
88
"@azure/msal-browser": "3.10.0",
99
"@babel/core": "7.23.3",
1010
"@babel/runtime": "7.23.8",
@@ -24,28 +24,28 @@
2424
"babel-loader": "9.1.3",
2525
"babel-preset-react-app": "10.0.1",
2626
"bfj": "8.0.0",
27-
"bootstrap": "5.3.2",
27+
"bootstrap": "5.3.3",
2828
"case-sensitive-paths-webpack-plugin": "2.4.0",
2929
"css-loader": "6.10.0",
30-
"dotenv": "16.4.2",
31-
"dotenv-expand": "10.0.0",
30+
"dotenv": "16.4.5",
31+
"dotenv-expand": "11.0.6",
3232
"eslint-config-react-app": "7.0.1",
3333
"eslint-plugin-react": "7.33.2",
3434
"eslint-webpack-plugin": "4.0.1",
35-
"express": "4.18.2",
35+
"express": "4.19.2",
3636
"expvariantassignmentsdk": "file:packages/expvariantassignmentsdk-1.0.0.tgz",
3737
"file-loader": "6.2.0",
3838
"fork-ts-checker-webpack-plugin": "9.0.2",
39-
"fs-extra": "11.1.1",
39+
"fs-extra": "11.2.0",
4040
"guid-typescript": "1.0.9",
4141
"isomorphic-fetch": "3.0.0",
4242
"localforage": "1.10.0",
43-
"mini-css-extract-plugin": "2.8.0",
43+
"mini-css-extract-plugin": "2.8.1",
4444
"monaco-editor": "0.30.1",
4545
"monaco-editor-webpack-plugin": "6.0.0",
4646
"office-ui-fabric-core": "11.1.0",
4747
"postcss-flexbugs-fixes": "5.0.2",
48-
"postcss-loader": "7.3.3",
48+
"postcss-loader": "8.1.1",
4949
"postcss-preset-env": "9.3.0",
5050
"re-resizable": "6.9.11",
5151
"react": "18.2.0",
@@ -55,13 +55,13 @@
5555
"redux": "4.2.1",
5656
"redux-thunk": "2.4.2",
5757
"resolve": "1.22.8",
58-
"sass": "1.69.7",
59-
"sass-loader": "13.3.2",
60-
"style-loader": "3.3.3",
58+
"sass": "1.72.0",
59+
"sass-loader": "14.1.1",
60+
"style-loader": "3.3.4",
6161
"typescript": "5.3.3",
62-
"url": "0.11.1",
62+
"url": "0.11.3",
6363
"url-loader": "4.1.1",
64-
"webpack": "5.90.1",
64+
"webpack": "5.90.3",
6565
"webpack-dev-server": "4.15.1",
6666
"webpack-manifest-plugin": "5.0.0",
6767
"workbox-webpack-plugin": "7.0.0"
@@ -91,7 +91,7 @@
9191
],
9292
"devDependencies": {
9393
"@axe-core/playwright": "4.7.3",
94-
"@playwright/test": "1.40.1",
94+
"@playwright/test": "1.42.0",
9595
"@types/chromedriver": "81.0.1",
9696
"@types/isomorphic-fetch": "0.0.39",
9797
"@types/jest": "29.5.12",
@@ -106,7 +106,7 @@
106106
"@typescript-eslint/parser": "6.17.0",
107107
"acorn": "8.11.3",
108108
"babel-jest": "29.7.0",
109-
"chromedriver": "119.0.1",
109+
"chromedriver": "122.0.4",
110110
"eslint": "8.56.0",
111111
"html-webpack-plugin": "5.6.0",
112112
"jest": "29.7.0",
@@ -119,7 +119,7 @@
119119
"react-dev-utils": "12.0.1",
120120
"redux-logger": "3.0.6",
121121
"redux-mock-store": "1.5.4",
122-
"selenium-webdriver": "4.17.0",
122+
"selenium-webdriver": "4.18.1",
123123
"start-server-and-test": "2.0.3",
124124
"ts-jest": "29.1.2"
125125
},

src/app/services/actions/query-action-creator-util.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ export async function generateResponseDownloadUrl(
221221
}
222222
}
223223

224+
async function tryParseJson(textValue: string) {
225+
try {
226+
return JSON.parse(textValue);
227+
} catch (error) {
228+
return textValue;
229+
}
230+
}
231+
224232
export function parseResponse(
225233
response: any,
226234
respHeaders: any = {}
@@ -233,9 +241,10 @@ export function parseResponse(
233241
const contentType = getContentType(response.headers);
234242
switch (contentType) {
235243
case ContentType.Json:
236-
return response.json();
244+
return response.text().then(tryParseJson);
237245
case ContentType.XML:
238246
case ContentType.HTML:
247+
case ContentType.TextCsv:
239248
case ContentType.TextPlain:
240249
return response.text();
241250

src/app/services/actions/query-action-creators.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ export function runQuery(query: IQuery) {
145145
};
146146

147147
if (error instanceof ClientError) {
148-
status.status = 0;
149-
status.statusText = `${error.name}: ${error.message}`;
148+
status.status = error.message;
149+
status.statusText = error.name;
150150
}
151151

152152
if (queryResultsInCorsError(query.sampleUrl)) {

src/app/services/context/validation-context/ValidationProvider.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export const ValidationProvider = ({ children }: ValidationProviderProps) => {
3434
}, [resources])
3535

3636
useEffect(() => {
37+
if (!queryVersion || !query || Object.keys(resources.data).length === 0) {
38+
return;
39+
}
3740
if (version !== queryVersion && GRAPH_API_VERSIONS.includes(queryVersion)
3841
&& resources.data[queryVersion].children!.length > 0) {
3942
setVersionedResources(resources.data[queryVersion].children!);

src/app/views/query-response/response/Response.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11

2-
import { useDispatch } from 'react-redux';
32

4-
import { AppDispatch, useAppSelector } from '../../../../store';
3+
import { useAppSelector } from '../../../../store';
54
import { getContentType } from '../../../services/actions/query-action-creator-util';
6-
import { convertVhToPx, getResponseEditorHeight,
7-
getResponseHeight } from '../../common/dimensions/dimensions-adjustment';
5+
import {
6+
convertVhToPx, getResponseEditorHeight,
7+
getResponseHeight
8+
} from '../../common/dimensions/dimensions-adjustment';
89
import ResponseDisplay from './ResponseDisplay';
910
import { ResponseMessages } from './ResponseMessages';
1011

1112
const Response = () => {
12-
const { dimensions: { response }, graphResponse, responseAreaExpanded, sampleQuery, authToken, graphExplorerMode } =
13+
const { dimensions: { response }, graphResponse, responseAreaExpanded} =
1314
useAppSelector((state) => state);
1415
const { body, headers } = graphResponse;
15-
const dispatch: AppDispatch = useDispatch();
1616

1717
const defaultHeight = convertVhToPx(getResponseHeight(response.height, responseAreaExpanded), 220);
1818
const monacoHeight = getResponseEditorHeight(150);
1919

2020
const contentDownloadUrl = body?.contentDownloadUrl;
2121
const throwsCorsError = body?.throwsCorsError;
2222
const contentType = getContentType(headers);
23+
2324
return (
2425
<div style={{ display: 'block' }}>
25-
{ResponseMessages(graphResponse, sampleQuery, authToken, graphExplorerMode, dispatch)}
26+
<ResponseMessages />
2627
{!contentDownloadUrl && !throwsCorsError && headers &&
2728
<ResponseDisplay
2829
contentType={contentType}
Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Link, MessageBar, MessageBarType } from '@fluentui/react';
22
import { useState } from 'react';
3-
import { IAuthenticateResult } from '../../../../types/authentication';
4-
import { Mode } from '../../../../types/enums';
5-
import { IGraphResponse } from '../../../../types/query-response';
3+
import { useDispatch } from 'react-redux';
64

5+
import { AppDispatch, useAppSelector } from '../../../../store';
6+
import { Mode } from '../../../../types/enums';
77
import { IQuery } from '../../../../types/query-runner';
8+
import { getContentType } from '../../../services/actions/query-action-creator-util';
89
import { runQuery } from '../../../services/actions/query-action-creators';
910
import { setSampleQuery } from '../../../services/actions/query-input-action-creators';
1011
import { MOZILLA_CORS_DOCUMENTATION_LINK } from '../../../services/graph-constants';
@@ -15,31 +16,32 @@ interface ODataLink {
1516
name: string;
1617
}
1718

18-
export function ResponseMessages(
19-
graphResponse: IGraphResponse,
20-
sampleQuery: IQuery,
21-
authToken: IAuthenticateResult,
22-
graphExplorerMode: Mode,
23-
dispatch: Function) {
24-
25-
function getOdataLinkFromResponseBody(responseBody: any): ODataLink | null {
26-
const odataLinks = ['nextLink', 'deltaLink'];
27-
let data = null;
28-
if (responseBody) {
29-
odataLinks.forEach(link => {
30-
if (responseBody[`@odata.${link}`]) {
31-
data = {
32-
link: responseBody[`@odata.${link}`],
33-
name: link
34-
};
35-
}
36-
});
37-
}
38-
return data;
19+
function getOdataLinkFromResponseBody(responseBody: any): ODataLink | null {
20+
const odataLinks = ['nextLink', 'deltaLink'];
21+
let data = null;
22+
if (responseBody) {
23+
odataLinks.forEach(link => {
24+
if (responseBody[`@odata.${link}`]) {
25+
data = {
26+
link: responseBody[`@odata.${link}`],
27+
name: link
28+
};
29+
}
30+
});
3931
}
32+
return data;
33+
}
34+
35+
export const ResponseMessages = () => {
36+
const dispatch: AppDispatch = useDispatch();
37+
const messageBars = [];
38+
39+
const { graphResponse: { body, headers }, sampleQuery, authToken, graphExplorerMode
40+
} = useAppSelector((state) => state);
4041
const [displayMessage, setDisplayMessage] = useState(true);
42+
4143
const tokenPresent = !!authToken.token;
42-
const { body } = graphResponse;
44+
const contentType = getContentType(headers);
4345
const odataLink = getOdataLinkFromResponseBody(body);
4446

4547
const setQuery = () => {
@@ -51,7 +53,7 @@ export function ResponseMessages(
5153

5254
// Display link to step to next result
5355
if (odataLink) {
54-
return (
56+
messageBars.push(
5557
<MessageBar messageBarType={MessageBarType.info}>
5658
{translateMessage('This response contains an @odata property.')}: @odata.{odataLink.name}
5759
<Link onClick={() => setQuery()} underline>
@@ -63,7 +65,7 @@ export function ResponseMessages(
6365

6466
// Display link to download file response
6567
if (body?.contentDownloadUrl) {
66-
return (
68+
messageBars.push(
6769
<div>
6870
<MessageBar messageBarType={MessageBarType.warning}>
6971
{translateMessage('This response contains unviewable content')}
@@ -77,7 +79,7 @@ export function ResponseMessages(
7779

7880
// Show CORS compliance message
7981
if (body?.throwsCorsError) {
80-
return (
82+
messageBars.push(
8183
<div>
8284
<MessageBar messageBarType={MessageBarType.warning}>
8385
{translateMessage('Response content not available due to CORS policy')}
@@ -90,7 +92,7 @@ export function ResponseMessages(
9092
}
9193

9294
if (body && !tokenPresent && displayMessage && graphExplorerMode === Mode.Complete) {
93-
return (
95+
messageBars.push(
9496
<div>
9597
<MessageBar
9698
messageBarType={MessageBarType.warning}
@@ -104,4 +106,20 @@ export function ResponseMessages(
104106
</div>
105107
);
106108
}
107-
}
109+
110+
if (contentType === 'application/json' && typeof body === 'string') {
111+
messageBars.push(
112+
<div>
113+
<MessageBar
114+
messageBarType={MessageBarType.info}
115+
onDismiss={() => setDisplayMessage(false)}
116+
dismissButtonAriaLabel={translateMessage('Close')}
117+
>
118+
{translateMessage('Malformed JSON body')}
119+
</MessageBar>
120+
</div>
121+
);
122+
}
123+
124+
return messageBars;
125+
}

src/modules/authentication/AuthenticationWrapper.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ export class AuthenticationWrapper implements IAuthenticationWrapper {
5050
}
5151

5252
public async logIn(sessionId = '', sampleQuery?: IQuery): Promise<AuthenticationResult> {
53-
if(sampleQuery){
53+
if (sampleQuery) {
5454
this.sampleQuery = sampleQuery;
5555
this.performingStepUpAuth = true;
5656
}
5757
this.consentingToNewScopes = false;
5858
// eslint-disable-next-line no-useless-catch
5959
try {
6060
const authResult = await this.getAuthResult([], sessionId);
61-
if(this.performingStepUpAuth && authResult){
61+
if (this.performingStepUpAuth && authResult) {
6262
this.claimsAvailable = true;
6363
}
6464
return authResult;
@@ -180,7 +180,7 @@ export class AuthenticationWrapper implements IAuthenticationWrapper {
180180

181181
private getClaims(): string | undefined {
182182
const account = this.getAccount();
183-
if(account && (this.sampleQuery.sampleUrl !== '')){
183+
if (account && (this.sampleQuery.sampleUrl !== '')) {
184184
const claimsChallenge = new ClaimsChallenge(this.sampleQuery, account);
185185
const storedClaims = claimsChallenge.getClaimsFromStorage();
186186
return storedClaims ? window.atob(storedClaims) : undefined;

src/types/enums.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export enum ContentType {
1515
TextPlain = 'text/plain',
1616
HTML = 'text/html',
1717
BinaryResponse = 'application/octet-stream',
18+
TextCsv = 'text/csv',
1819
}
1920

2021
export enum AppTheme {

0 commit comments

Comments
 (0)