Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fluent v9 upgrades feature branch #3428

Open
wants to merge 39 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
777b8d0
Update dependencies
musale Oct 30, 2024
2e63a79
Merge branch 'dev' into feat/fluent-v4
musale Nov 13, 2024
c843775
Merge branch 'dev' into feat/fluent-v9-upgrade
musale Nov 14, 2024
867d0af
Add dependencies
musale Nov 14, 2024
a02496f
Add dependencies
musale Nov 14, 2024
e039e12
Lock dependencies
musale Nov 14, 2024
a4b0ec0
Add theming support for fluent ui v9
musale Nov 14, 2024
327b302
feat: update the sidebar tabs to use fluent UI v9 (#3431)
musale Nov 19, 2024
6349725
feat: update the heading, icons and menu items on the header (#3432)
musale Nov 19, 2024
fe67391
feat: upgrade the sample queries tab to use fluent UI v9 components (…
musale Nov 19, 2024
bc2ad9f
use tab and tablist components
ElinorW Nov 26, 2024
7abdbfd
migrate theme popover to v9
Mnickii Nov 26, 2024
5277684
modify request headers
ElinorW Nov 27, 2024
97da4d7
modify access token area
ElinorW Nov 27, 2024
8a3eb39
update copy button
ElinorW Nov 27, 2024
4c81805
revert loadGETheme removal for v8 components
Mnickii Nov 28, 2024
7f546a9
use customized radio Group
Mnickii Nov 28, 2024
7dfd148
adjusst icon size
Mnickii Nov 28, 2024
f4aa8d5
remove checked
Mnickii Dec 2, 2024
1f9d50a
feat: migrate the history tab components to fluent UI v9 (#3444)
musale Dec 3, 2024
0becb35
detect system theme in theme-chooser and set as default
Mnickii Dec 3, 2024
82be809
resolve changes
ElinorW Dec 4, 2024
87a0e4a
migrate components with MessageBar and type
Mnickii Dec 4, 2024
21ba3c9
include system theme appwise
Mnickii Dec 4, 2024
4db27b5
use v9 component
Mnickii Dec 5, 2024
6b56ffa
Merge branch 'dev' into feat/fluent-v9-upgrade
musale Dec 9, 2024
7a3a077
Fix merging from dev issues
musale Dec 9, 2024
a12130a
Merge branch 'feat/fluent-v9-upgrade' into feat/message-status
Mnickii Dec 9, 2024
4d8f773
Merge branch 'feat/fluent-v9-upgrade' into feat/theme-popover
Mnickii Dec 9, 2024
25d1888
fix messageBarType
Mnickii Dec 9, 2024
f2f521c
update height
ElinorW Dec 9, 2024
c25fe22
fix: update the sample queries signed in/out click functionality (#3483)
musale Dec 10, 2024
08411d8
add system to options
Mnickii Dec 10, 2024
be5a415
Merge pull request #3442 from microsoftgraph/feat/theme-popover
Mnickii Dec 11, 2024
fc4cd4b
fix tests
Mnickii Dec 11, 2024
e5e2ba4
Merge pull request #3479 from microsoftgraph/feat/message-status
Mnickii Dec 11, 2024
f11865e
Merge pull request #3441 from microsoftgraph/feat/fluent-v9-request-body
Mnickii Dec 11, 2024
c427d6e
remove system default for now
Mnickii Dec 11, 2024
e4957e6
Merge pull request #3490 from microsoftgraph/fix/theme
Mnickii Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,363 changes: 719 additions & 644 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
"dependencies": {
"@augloop/types-core": "file:packages/types-core-2.16.189.tgz",
"@axe-core/webdriverjs": "4.10.0",
"@fluentui/react-components": "9.55.1",
"@azure/msal-browser": "3.26.1",
"@babel/core": "7.26.0",
"@babel/runtime": "7.26.0",
"@fluentui/react": "8.121.1",
"@fluentui/react-components": "9.56.1",
"@fluentui/react-icons": "2.0.265",
"@fluentui/react-icons-mdl2": "1.3.76",
"@microsoft/applicationinsights-react-js": "17.3.4",
"@microsoft/applicationinsights-web": "3.3.3",
Expand Down
6 changes: 3 additions & 3 deletions src/app/services/actions/permissions-action-creator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ describe('Permissions action creators', () => {
statusText: translateMessage('Revoking'),
status: translateMessage('Please wait while we revoke this permission'),
ok: false,
messageType: 0
messageBarType: 'info'
}
}
]
Expand Down Expand Up @@ -357,7 +357,7 @@ describe('Permissions action creators', () => {
statusText: translateMessage('Revoking '),
status: translateMessage('Please wait while we revoke this permission'),
ok: false,
messageType: 0
messageBarType: 'info'
}
}
]
Expand Down Expand Up @@ -416,7 +416,7 @@ describe('Permissions action creators', () => {
statusText: translateMessage('Revoking'),
status: translateMessage('Please wait while we revoke this permission'),
ok: false,
messageType: 0
messageBarType: 'info'
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Query Action Creators', () => {
ok: false,
statusText: 'Something worked!',
status: 200,
messageType: 1,
messageBarType: 'success',
hint: 'Something worked!'
}

Expand Down
14 changes: 7 additions & 7 deletions src/app/services/actions/revoke-scopes.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const revokeScopes = createAsyncThunk(
const requiredPermissions = REVOKING_PERMISSIONS_REQUIRED_SCOPES.split(' ');
const defaultUserScopes = DEFAULT_USER_SCOPES.split(' ');

dispatchScopesStatus(dispatch, 'Please wait while we revoke this permission', 'Revoking ', 0);
dispatchScopesStatus(dispatch, 'Please wait while we revoke this permission', 'Revoking ', 'info');
const revokePermissionUtil = await RevokePermissionsUtil.initialize(profile.user!.id!);

if (!consentedScopes || consentedScopes.length === 0) {
Expand Down Expand Up @@ -62,7 +62,7 @@ export const revokeScopes = createAsyncThunk(
const updatedScopes = await updatePermissions(permissionsUpdateObject);

if (updatedScopes) {
dispatchScopesStatus(dispatch, 'Permission revoked', 'Success', 4);
dispatchScopesStatus(dispatch, 'Permission revoked', 'Success', 'success');
dispatch(getConsentedScopesSuccess(updatedScopes));
trackRevokeConsentEvent(REVOKE_STATUS.success, permissionToRevoke);
return updatedScopes;
Expand All @@ -77,7 +77,7 @@ export const revokeScopes = createAsyncThunk(
} catch (errorMessage: any) {
if (errorMessage instanceof RevokeScopesError) {
const { errorText, statusText, status, messageType } = errorMessage;
dispatchScopesStatus(dispatch, statusText, status, messageType);
dispatchScopesStatus(dispatch, statusText, status, 'error');
const permissionObject = {
permissionToRevoke,
statusCode: statusText,
Expand All @@ -88,20 +88,20 @@ export const revokeScopes = createAsyncThunk(
} else {
const { code, message } = errorMessage;
trackRevokeConsentEvent(REVOKE_STATUS.failure, 'Failed to revoke consent');
dispatchScopesStatus(dispatch, message ? message : 'Failed to revoke consent', code ? code : 'Failed', 1);
dispatchScopesStatus(dispatch, message ? message : 'Failed to revoke consent', code ? code : 'Failed', 'error');
return rejectWithValue(errorMessage);
}
}
}
);

const dispatchScopesStatus = (dispatch: Function, statusText: string, status: string, messageType: number) => {
const dispatchScopesStatus = (dispatch: Function, statusText: string, status: string, messageBarType: string) => {
dispatch(
setQueryResponseStatus({
statusText: translateMessage(status),
status: translateMessage(statusText),
ok: false,
messageType
messageBarType
})
)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ async function updatePermissions(permissionsUpdateObject: IPermissionUpdate): Pr
}
else if ((retryCount < maxRetryCount) && !isRevokeSuccessful) {
await new Promise(resolve => setTimeout(resolve, retryDelay * 2));
dispatchScopesStatus(dispatch, 'We are retrying the revoking operation', 'Retrying', 5);
dispatchScopesStatus(dispatch, 'We are retrying the revoking operation', 'Retrying', 'info');

permissionsUpdateObject.retryCount += 1;
return updatePermissions(permissionsUpdateObject);
Expand Down
6 changes: 3 additions & 3 deletions src/app/services/slices/auth.slice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BrowserAuthError } from '@azure/msal-browser';
import { MessageBarType } from '@fluentui/react';

import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';

import { authenticationWrapper } from '../../../modules/authentication';
Expand Down Expand Up @@ -112,7 +112,7 @@ export const consentToScopes = createAsyncThunk(
statusText: translateMessage('Success'),
status: translateMessage('Scope consent successful'),
ok: true,
messageType: MessageBarType.success
messageBarType: 'success'
})
);
dispatch(fetchAllPrincipalGrants());
Expand All @@ -125,7 +125,7 @@ export const consentToScopes = createAsyncThunk(
statusText: translateMessage('Scope consent failed'),
status: errorCode,
ok: false,
messageType: MessageBarType.error,
messageBarType: 'error',
hint: getConsentAuthErrorHint(errorCode)
})
);
Expand Down
8 changes: 4 additions & 4 deletions src/app/services/slices/graph-response.slice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BrowserAuthError } from '@azure/msal-browser';
import { MessageBarType } from '@fluentui/react';

import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';

import { authenticationWrapper } from '../../../modules/authentication';
Expand Down Expand Up @@ -156,7 +156,7 @@ async function processResponse(response: Response, respHeaders: { [key: string]:

const generateStatus = ({ duration, response }: { duration: number; response: Response }): IStatus => {
const status: IStatus = {
messageType: MessageBarType.error,
messageBarType: 'error',
ok: false,
duration,
status: response.status || 400,
Expand All @@ -171,7 +171,7 @@ const generateStatus = ({ duration, response }: { duration: number; response: Re
if (response && response.ok) {
CURRENT_RETRIES = 0;
status.ok = true;
status.messageType = MessageBarType.success;
status.messageBarType = 'success';
}
return status;
}
Expand Down Expand Up @@ -232,7 +232,7 @@ function generateHistoryItem(
async function handleError(error: Error, query: IQuery) {
let body = null;
const status: IStatus = {
messageType: MessageBarType.error,
messageBarType: 'error',
ok: false,
status: 400,
statusText: 'Bad Request'
Expand Down
2 changes: 1 addition & 1 deletion src/app/services/slices/permission-grants.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const fetchAllPrincipalGrants = createAsyncThunk(
statusText: translateMessage('Permissions'),
status: translateMessage('You require the following permissions to read'),
ok: false,
messageType: 0
messageBarType: 'error'
}));
throw new Error('Permission required');
}
Expand Down
34 changes: 7 additions & 27 deletions src/app/utils/dynamic-sort.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { dynamicSort } from './dynamic-sort';
import { SortOrder } from '../../types/enums';

import { dynamicSort } from './dynamic-sort';
interface INameAge {
name: string
age: number
}
describe('Dynamic Sort', () => {

it('should sort an array of objects in ascending order', () => {
Expand All @@ -16,7 +19,7 @@ describe('Dynamic Sort', () => {
{ name: 'Lucy', age: 18 }
];

const sortedArray = arrayToSort.sort(dynamicSort('name', SortOrder.ASC));
const sortedArray = arrayToSort.sort(dynamicSort<INameAge>('name', SortOrder.ASC));
expect(expected).toEqual(sortedArray);
});

Expand All @@ -33,30 +36,7 @@ describe('Dynamic Sort', () => {
{ name: 'Ann', age: 14 }
];

const sortedArray = arrayToSort.sort(dynamicSort('name', SortOrder.DESC));
const sortedArray = arrayToSort.sort(dynamicSort<INameAge>('name', SortOrder.DESC));
expect(expected).toEqual(sortedArray);
});

it('should return unsorted object array when property does not exist', () => {
const arrayToSort = [
{ name: 'Ann', age: 14 },
{ name: 'Lucy', age: 18 },
{ name: 'Diana', age: 11 }
];

const sortedArray = arrayToSort.sort(dynamicSort('gender', SortOrder.DESC));
expect(arrayToSort).toEqual(sortedArray);
});

it('should return unsorted object array when property is empty', () => {
const arrayToSort = [
{ name: 'Ann', age: 14 },
{ name: 'Lucy', age: 18 },
{ name: 'Diana', age: 11 }
];

const sortedArray = arrayToSort.sort(dynamicSort('', SortOrder.DESC));
expect(arrayToSort).toEqual(sortedArray);
});

});
6 changes: 3 additions & 3 deletions src/app/utils/dynamic-sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import { SortOrder } from '../../types/enums';
* @param {SortOrder} sortOrder the direction to follow Ascending / Descending
* You pass this helper to the array sort function
*/
export function dynamicSort(property: string | null, sortOrder: SortOrder) {
export function dynamicSort<T>(property: keyof T, sortOrder: SortOrder) {
let order = 1;
if (sortOrder === SortOrder.DESC) {
order = -1;
}
if (property) {
return (first: any, second: any) => {
return (first: T, second: T) => {
const result = (first[property] < second[property]) ? -1 : (first[property] > second[property]) ? 1 : 0;
return result * order;
};
}
return (first: any, second: any) => {
return (first: T, second: T) => {
const result = (first < second) ? -1 : (first > second) ? 1 : 0;
return result * order;
};
Expand Down
47 changes: 33 additions & 14 deletions src/app/views/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Announced, getTheme, ITheme, styled } from '@fluentui/react';
import { getTheme, ITheme, styled } from '@fluentui/react';
import { FluentProvider, teamsHighContrastTheme, Theme, webDarkTheme, webLightTheme } from '@fluentui/react-components';
import { bindActionCreators, Dispatch } from '@reduxjs/toolkit';
import { Resizable } from 're-resizable';
Expand Down Expand Up @@ -27,20 +27,22 @@ import { toggleSidebar } from '../services/slices/sidebar-properties.slice';
import { changeTheme } from '../services/slices/theme.slice';
import { parseSampleUrl } from '../utils/sample-url-generation';
import { substituteTokens } from '../utils/token-helpers';
import { headerMessagingV9 } from './app-sections/HeaderMessagingV9';
import { translateMessage } from '../utils/translate-messages';
import { StatusMessages, TermsOfUseMessage } from './app-sections';
import { headerMessaging } from './app-sections/HeaderMessaging';
import { StatusMessagesV9, TermsOfUseMessageV9 } from './app-sections';
import { appStyles } from './App.styles';
import { classNames } from './classnames';
import Notification from './common/banners/Notification';
import { KeyboardCopyEvent } from './common/copy-button/KeyboardCopyEvent';
import PopupsWrapper from './common/popups/PopupsWrapper';
import { createShareLink } from './common/share';
import { MainHeader } from './main-header/MainHeader';
// import { MainHeader } from './main-header/MainHeader';
import { MainHeaderV9 } from './main-header/MainHeaderV9';
import { QueryResponse } from './query-response';
import { QueryRunner } from './query-runner';
import { parse } from './query-runner/util/iframe-message-parser';
import { Sidebar } from './sidebar/Sidebar';
// import { Sidebar } from './sidebar/Sidebar';
import { SidebarV9 } from './sidebar/SidebarV9';
export interface IAppProps {
theme?: ITheme;
styles?: object;
Expand Down Expand Up @@ -68,6 +70,13 @@ interface IAppState {
sidebarTabSelection: string;
}

const getSystemTheme = (): string => {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
};

class App extends Component<IAppProps, IAppState> {
private mediaQueryList = window.matchMedia('(max-width: 992px)');
private currentTheme: ITheme = getTheme();
Expand Down Expand Up @@ -128,6 +137,12 @@ class App extends Component<IAppProps, IAppState> {
// Listens for messages from host document
window.addEventListener('message', this.receiveMessage, false);
this.handleSharedQueries();

// Load the theme from local storage or use the system theme as the default
const savedTheme = localStorage.getItem('appTheme') ?? getSystemTheme();
// @ts-ignore
this.props.actions.changeTheme(savedTheme);
loadGETheme(savedTheme); // Remove when cleaning up
};

public handleSharedQueries() {
Expand Down Expand Up @@ -407,18 +422,19 @@ class App extends Component<IAppProps, IAppState> {
this.removeFlexBasisProperty();
this.removeSidebarHeightProperty();

const fluentV9Themes: Record<string, Theme>= {
const fluentV9Themes: Record<string, Theme> = {
'light': webLightTheme,
'dark': webDarkTheme,
'high-contrast': teamsHighContrastTheme
}
return (
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
<FluentProvider theme={fluentV9Themes[this.props.appTheme]}>
<ThemeContext.Provider value={this.props.appTheme}>
<PopupsProvider>
<div className={`ms-Grid ${classes.app}`} style={{ paddingLeft: mobileScreen && '15px' }}>
<MainHeader
{/* <MainHeader
toggleSidebar={this.toggleSidebar}
/>
<Announced
Expand All @@ -427,7 +443,9 @@ class App extends Component<IAppProps, IAppState> {
? translateMessage('Sidebar minimized')
: translateMessage('Sidebar maximized')
}
/>
/> */}

<MainHeaderV9 />
<div className={`ms-Grid-row ${classes.appRow}`} style={{
flexWrap: mobileScreen && 'wrap',
marginRight: showSidebar || (graphExplorerMode === Mode.TryIt) && '-20px',
Expand Down Expand Up @@ -455,14 +473,15 @@ class App extends Component<IAppProps, IAppState> {
height: ''
}}
>
<Sidebar currentTab={this.state.sidebarTabSelection}
{/* <Sidebar currentTab={this.state.sidebarTabSelection}
setSidebarTabSelection={this.setSidebarTabSelection} showSidebar={showSidebar}
toggleSidebar={this.toggleSidebar}
mobileScreen={mobileScreen} />
mobileScreen={mobileScreen} /> */}
<SidebarV9/>
</Resizable>
)}
{graphExplorerMode === Mode.TryIt &&
headerMessaging(query)}
headerMessagingV9(query)}

{displayContent && (
<Resizable
Expand Down Expand Up @@ -496,7 +515,7 @@ class App extends Component<IAppProps, IAppState> {
display: 'flex', flexDirection: 'column', alignItems: 'stretch', flex: 1
}}>
<div style={mobileScreen ? this.statusAreaMobileStyle : this.statusAreaFullScreenStyle}>
<StatusMessages />
<StatusMessagesV9 />
</div>
<QueryResponse />
</div>
Expand All @@ -505,7 +524,7 @@ class App extends Component<IAppProps, IAppState> {
)}
</div>
<div style={mobileScreen ? this.statusAreaMobileStyle : this.statusAreaFullScreenStyle}>
<TermsOfUseMessage />
<TermsOfUseMessageV9 />
</div>
</div>
<CollectionPermissionsProvider>
Expand Down Expand Up @@ -557,4 +576,4 @@ const mapDispatchToProps = (dispatch: Dispatch) => {
const StyledApp = styled(App, appStyles as any);

//@ts-ignore
export default connect(mapStateToProps, mapDispatchToProps)(StyledApp);
export default connect(mapStateToProps, mapDispatchToProps)(StyledApp);
Loading
Loading