Repository navigation
change: [M3-7785] - Improve Dev Tools #10220
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
Changes from all commits
a28cd2e
83403cc
3910c67
0147fa0
3c318e2
2f10465
d132a45
ac5fdcd
eb1140a
36a42d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@linode/manager": Changed | ||
| --- | ||
|
|
||
| Improve dev tools UI ([#10220](https://github.com/linode/manager/pull/10220)) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||
| import Grid from '@mui/material/Unstable_Grid2'; | ||||||
| import { useFlags as ldUseFlags } from 'launchdarkly-react-client-sdk'; | ||||||
| import * as React from 'react'; | ||||||
| import { useDispatch } from 'react-redux'; | ||||||
|
|
||||||
|
|
@@ -8,7 +9,6 @@ import { Dispatch } from 'src/hooks/types'; | |||||
| import { useFlags } from 'src/hooks/useFlags'; | ||||||
| import { setMockFeatureFlags } from 'src/store/mockFeatureFlags'; | ||||||
| import { getStorage, setStorage } from 'src/utilities/storage'; | ||||||
|
|
||||||
| const MOCK_FEATURE_FLAGS_STORAGE_KEY = 'devTools/mock-feature-flags'; | ||||||
|
|
||||||
| const options: { flag: keyof Flags; label: string }[] = [ | ||||||
|
|
@@ -28,6 +28,7 @@ const options: { flag: keyof Flags; label: string }[] = [ | |||||
| export const FeatureFlagTool = withFeatureFlagProvider(() => { | ||||||
| const dispatch: Dispatch = useDispatch(); | ||||||
| const flags = useFlags(); | ||||||
| const ldFlags = ldUseFlags(); | ||||||
|
|
||||||
| React.useEffect(() => { | ||||||
| const storedFlags = getStorage(MOCK_FEATURE_FLAGS_STORAGE_KEY); | ||||||
|
|
@@ -48,6 +49,14 @@ export const FeatureFlagTool = withFeatureFlagProvider(() => { | |||||
| setStorage(MOCK_FEATURE_FLAGS_STORAGE_KEY, updatedFlags); | ||||||
| }; | ||||||
|
|
||||||
| /** | ||||||
| * This will reset the flags values to the Launch Darkly defaults (as returned from the LD dev environment) | ||||||
| */ | ||||||
| const resetFlags = () => { | ||||||
| dispatch(setMockFeatureFlags(ldFlags)); | ||||||
| setStorage(MOCK_FEATURE_FLAGS_STORAGE_KEY, ''); | ||||||
| }; | ||||||
|
|
||||||
| return ( | ||||||
| <Grid container> | ||||||
| <Grid xs={12}> | ||||||
|
|
@@ -75,6 +84,9 @@ export const FeatureFlagTool = withFeatureFlagProvider(() => { | |||||
| </div> | ||||||
| ); | ||||||
| })} | ||||||
| <button onClick={resetFlags} style={{ marginTop: 8 }}> | ||||||
| Reset default flags | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we reword this to
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I almost made this same comment, then deleted it, and asked for a code comment, ha. I do still think it would be nice. I was thinking of (1) more text requiring further height increase of the dev tools panel and (2) whether we'd want to specify LD if to save some trouble of updating it if we were to switch to another tool in the future - but really that's such an easy change.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same brain cell π§ . (1) We can shorthand to LD to save some width space (2) Agreed |
||||||
| </button> | ||||||
| </div> | ||||||
| </Grid> | ||||||
| </Grid> | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import LinkIcon from '@mui/icons-material/Link'; | ||
| import * as React from 'react'; | ||
|
|
||
| export const Preferences = () => { | ||
| return ( | ||
| <> | ||
| <h4 style={{ marginBottom: 4 }}>Preferences</h4> | ||
| <a | ||
| href="/profile/settings?preferenceEditor=true" | ||
| style={{ color: '#fff' }} | ||
| > | ||
| Open preference Modal | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love this. ++
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is from @jaalah-akamai! |
||
| <LinkIcon | ||
| style={{ | ||
| height: 20, | ||
| left: 4, | ||
| position: 'relative', | ||
| top: 6, | ||
| width: 20, | ||
| }} | ||
| /> | ||
| </a> | ||
| </> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import Grid from '@mui/material/Unstable_Grid2'; | ||
| import * as React from 'react'; | ||
|
|
||
| import { getStorage, setStorage } from 'src/utilities/storage'; | ||
|
|
||
| export const MOCK_THEME_STORAGE_KEY = 'devTools/theme'; | ||
|
|
||
| import type { ThemeChoice } from 'src/utilities/theme'; | ||
|
|
||
| export const ThemeSelector = () => { | ||
| const [mockTheme, setMockTheme] = React.useState<ThemeChoice>('system'); | ||
|
|
||
| React.useEffect(() => { | ||
| const storedTheme = getStorage(MOCK_THEME_STORAGE_KEY); | ||
| if (storedTheme) { | ||
| setMockTheme(storedTheme); | ||
| } | ||
| }, []); | ||
|
|
||
| const handleSetTheme = (e: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const selectedValue = e.target.value as ThemeChoice; | ||
|
|
||
| setMockTheme(selectedValue); | ||
| setStorage(MOCK_THEME_STORAGE_KEY, selectedValue); | ||
| window.location.reload(); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switching theme is not going to be as common as toggling or flags. I opted to no add this to redux as there is not a lot of value there and it would increase the complexity of this feature by a lot. |
||
| }; | ||
|
|
||
| return ( | ||
| <Grid container> | ||
| <Grid xs={12}> | ||
| <h4 style={{ marginBottom: 0 }}>MSW Theme Selector</h4> | ||
| <p style={{ marginBottom: 8, marginTop: 0 }}> | ||
| (only when MSW is enabled) | ||
| </p> | ||
| </Grid> | ||
| <Grid xs={12}> | ||
| <select onChange={handleSetTheme} value={mockTheme}> | ||
| <option value="system">System</option> | ||
| <option value="light">Light</option> | ||
| <option value="dark">Dark</option> | ||
| </select> | ||
| </Grid> | ||
| </Grid> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,13 +10,21 @@ | |
| width: 60px; | ||
| transition: all 0.3s; | ||
| z-index: 1; | ||
| overflow: auto; | ||
| } | ||
|
|
||
| #dev-tools.mswEnabled svg { | ||
| color: #aaff00; | ||
| } | ||
|
|
||
| #dev-tools:hover { | ||
| height: 325px; | ||
| height: 375px; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. increasing the height here a bit to allow for more room and the new reset button |
||
| width: 100%; | ||
| opacity: 0.9; | ||
| overflow: auto; | ||
| } | ||
|
|
||
| #dev-tools:hover svg { | ||
| color: white; | ||
| } | ||
|
|
||
| #dev-tools .tools { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import Handyman from '@mui/icons-material/Handyman'; | ||
| import Grid from '@mui/material/Unstable_Grid2'; | ||
| import React from 'react'; | ||
| import { createRoot } from 'react-dom/client'; | ||
|
|
@@ -10,12 +11,17 @@ import './dev-tools.css'; | |
| import { EnvironmentToggleTool } from './EnvironmentToggleTool'; | ||
| import { FeatureFlagTool } from './FeatureFlagTool'; | ||
| import { MockDataTool } from './MockDataTool'; | ||
| import { Preferences } from './Preferences'; | ||
| import { isMSWEnabled } from './ServiceWorkerTool'; | ||
| import { ThemeSelector } from './ThemeSelector'; | ||
|
|
||
| function install(store: ApplicationStore) { | ||
| function DevTools() { | ||
| return ( | ||
| <div id="dev-tools"> | ||
| <div>π </div> | ||
| <div className={isMSWEnabled ? 'mswEnabled' : ''} id="dev-tools"> | ||
| <div> | ||
| <Handyman /> | ||
| </div> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this way we can color it with CSS
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we also/or add text to indicate the MSW is "on"? For accessibility, color should not be the only indicator haha |
||
| <Grid className="tools" container spacing={2}> | ||
| <Grid sm={2} xs={4}> | ||
| <FeatureFlagTool /> | ||
|
|
@@ -28,6 +34,8 @@ function install(store: ApplicationStore) { | |
| {!isProductionBuild || ENABLE_DEV_TOOLS ? ( | ||
| <Grid md={3} sm={5} xs={4}> | ||
| <MockDataTool /> | ||
| <ThemeSelector /> | ||
| <Preferences /> | ||
| </Grid> | ||
| ) : null} | ||
| </Grid> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,9 +11,10 @@ import { DateTime } from 'luxon'; | |
| import { rest } from 'msw'; | ||
|
|
||
| import { regions } from 'src/__data__/regionsData'; | ||
| import { MOCK_THEME_STORAGE_KEY } from 'src/dev-tools/ThemeSelector'; | ||
| import { | ||
| VLANFactory, | ||
| abuseTicketNotificationFactory, | ||
| // abuseTicketNotificationFactory, | ||
| accountAvailabilityFactory, | ||
| accountBetaFactory, | ||
| accountFactory, | ||
|
|
@@ -103,6 +104,7 @@ import { accountLoginFactory } from 'src/factories/accountLogin'; | |
| import { accountUserFactory } from 'src/factories/accountUsers'; | ||
| import { grantFactory, grantsFactory } from 'src/factories/grants'; | ||
| import { pickRandom } from 'src/utilities/random'; | ||
| import { getStorage } from 'src/utilities/storage'; | ||
|
|
||
| export const makeResourcePage = <T>( | ||
| e: T[], | ||
|
|
@@ -1146,7 +1148,11 @@ export const handlers = [ | |
| return res(ctx.json(makeResourcePage(vlans))); | ||
| }), | ||
| rest.get('*/profile/preferences', (req, res, ctx) => { | ||
| return res(ctx.json({})); | ||
| return res( | ||
| ctx.json({ | ||
| theme: getStorage(MOCK_THEME_STORAGE_KEY) ?? 'system', | ||
| }) | ||
| ); | ||
| }), | ||
| rest.get('*/profile/devices', (req, res, ctx) => { | ||
| return res(ctx.json(makeResourcePage([]))); | ||
|
|
@@ -1819,18 +1825,18 @@ export const handlers = [ | |
| when: null, | ||
| }; | ||
|
|
||
| const emailBounce = notificationFactory.build({ | ||
| body: null, | ||
| entity: null, | ||
| label: 'We are unable to send emails to your billing email address!', | ||
| message: 'We are unable to send emails to your billing email address!', | ||
| severity: 'major', | ||
| type: 'billing_email_bounce', | ||
| until: null, | ||
| when: null, | ||
| }); | ||
| // const emailBounce = notificationFactory.build({ | ||
| // body: null, | ||
| // entity: null, | ||
| // label: 'We are unable to send emails to your billing email address!', | ||
| // message: 'We are unable to send emails to your billing email address!', | ||
| // severity: 'major', | ||
| // type: 'billing_email_bounce', | ||
| // until: null, | ||
| // when: null, | ||
| // }); | ||
|
|
||
| const abuseTicket = abuseTicketNotificationFactory.build(); | ||
| // const abuseTicket = abuseTicketNotificationFactory.build(); | ||
|
|
||
| const migrationNotification = notificationFactory.build({ | ||
| entity: { id: 0, label: 'linode-0', type: 'linode' }, | ||
|
|
@@ -1926,8 +1932,8 @@ export const handlers = [ | |
| outageNotification, | ||
| minorSeverityNotification, | ||
| criticalSeverityNotification, | ||
| abuseTicket, | ||
| emailBounce, | ||
| // abuseTicket, | ||
| // emailBounce, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed that these are annoying. I don't think I'll miss them, but not sure if anyone else on the team has a reason behind why they have historically been kept visible by default.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. feels to me like something that was implemented at once and never changed to no particular reason. If anyone is affected I will add them back but I doubt it |
||
| migrationNotification, | ||
| balanceNotification, | ||
| blockStorageMigrationScheduledNotification, | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.