From a28cd2e9e8875b7ad6220a0ebf6ee449c2bec135 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Wed, 21 Feb 2024 09:12:59 -0500 Subject: [PATCH 01/10] Initial commit - save work --- .../manager/src/dev-tools/ThemeSelector.tsx | 54 +++++++++++++++++++ packages/manager/src/dev-tools/dev-tools.tsx | 2 + packages/manager/src/mocks/serverHandlers.ts | 11 +++- packages/manager/src/store/index.ts | 6 ++- packages/manager/src/store/mockTheme/index.ts | 24 +++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 packages/manager/src/dev-tools/ThemeSelector.tsx create mode 100644 packages/manager/src/store/mockTheme/index.ts diff --git a/packages/manager/src/dev-tools/ThemeSelector.tsx b/packages/manager/src/dev-tools/ThemeSelector.tsx new file mode 100644 index 00000000000..3bc33045ace --- /dev/null +++ b/packages/manager/src/dev-tools/ThemeSelector.tsx @@ -0,0 +1,54 @@ +import Grid from '@mui/material/Unstable_Grid2'; +import * as React from 'react'; +import { useDispatch, useStore } from 'react-redux'; + +import { setMockTheme } from 'src/store/mockTheme'; +import { getStorage, setStorage } from 'src/utilities/storage'; + +import type { Dispatch } from 'src/hooks/types'; + +export const MOCK_THEME_STORAGE_KEY = 'devTools/theme'; + +export interface ThemeSelectionOptions { + label: string; + value: 'dark' | 'light' | 'system'; +} + +export const ThemeSelector = () => { + const dispatch: Dispatch = useDispatch(); + const store = useStore(); + const state = store.getState(); + + console.log(state); + + React.useEffect(() => { + const storedTheme = getStorage(MOCK_THEME_STORAGE_KEY); + if (storedTheme) { + dispatch(setMockTheme(storedTheme)); + } + }, [dispatch]); + + const handleSetTheme = (e: React.ChangeEvent) => { + const selectedValue = e.target.value as ThemeSelectionOptions['value']; + dispatch(setMockTheme(selectedValue)); + setStorage(MOCK_THEME_STORAGE_KEY, e.target.value); + }; + + return ( + + +

Theme Selector

+
+ + + +
+ ); +}; diff --git a/packages/manager/src/dev-tools/dev-tools.tsx b/packages/manager/src/dev-tools/dev-tools.tsx index 99ba883b528..79eca902238 100644 --- a/packages/manager/src/dev-tools/dev-tools.tsx +++ b/packages/manager/src/dev-tools/dev-tools.tsx @@ -10,6 +10,7 @@ import './dev-tools.css'; import { EnvironmentToggleTool } from './EnvironmentToggleTool'; import { FeatureFlagTool } from './FeatureFlagTool'; import { MockDataTool } from './MockDataTool'; +import { ThemeSelector } from './ThemeSelector'; function install(store: ApplicationStore) { function DevTools() { @@ -28,6 +29,7 @@ function install(store: ApplicationStore) { {!isProductionBuild || ENABLE_DEV_TOOLS ? ( + ) : null} diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 8bae0035f00..b79c38c3c68 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -9,8 +9,10 @@ import { } from '@linode/api-v4'; import { DateTime } from 'luxon'; import { rest } from 'msw'; +import { useStore } from 'react-redux'; import { regions } from 'src/__data__/regionsData'; +import { MOCK_THEME_STORAGE_KEY } from 'src/dev-tools/ThemeSelector'; import { VLANFactory, abuseTicketNotificationFactory, @@ -103,6 +105,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 = ( e: T[], @@ -117,6 +120,8 @@ export const makeResourcePage = ( results: override.results ?? e.length, }); +const store = useStore(); + const statusPage = [ rest.get('*/api/v2/incidents*', (req, res, ctx) => { const response = incidentResponseFactory.build(); @@ -1146,7 +1151,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), + }) + ); }), rest.get('*/profile/devices', (req, res, ctx) => { return res(ctx.json(makeResourcePage([]))); diff --git a/packages/manager/src/store/index.ts b/packages/manager/src/store/index.ts index 2728fe0b015..a2e55301eb9 100644 --- a/packages/manager/src/store/index.ts +++ b/packages/manager/src/store/index.ts @@ -1,4 +1,5 @@ import { Store, applyMiddleware, combineReducers, createStore } from 'redux'; +import thunk from 'redux-thunk'; import { State as AuthState } from 'src/store/authentication'; import authentication, { @@ -29,11 +30,11 @@ import mockFeatureFlags, { MockFeatureFlagState, defaultMockFeatureFlagState, } from './mockFeatureFlags'; +import mockTheme, { MockTheme, defaultMockTheme } from './mockTheme'; import pendingUpload, { State as PendingUploadState, defaultState as pendingUploadState, } from './pendingUpload'; -import thunk from 'redux-thunk'; export interface ApplicationState { authentication: AuthState; @@ -42,6 +43,7 @@ export interface ApplicationState { longviewClients: LongviewState; longviewStats: LongviewStatsState; mockFeatureFlags: MockFeatureFlagState; + mockTheme: MockTheme; pendingUpload: PendingUploadState; stackScriptDialog: StackScriptDialogState; } @@ -53,6 +55,7 @@ export const defaultState: ApplicationState = { longviewClients: defaultLongviewState, longviewStats: defaultLongviewStatsState, mockFeatureFlags: defaultMockFeatureFlagState, + mockTheme: defaultMockTheme, pendingUpload: pendingUploadState, stackScriptDialog: stackScriptDialogDefaultState, }; @@ -67,6 +70,7 @@ const reducers = combineReducers({ longviewClients: longview, longviewStats, mockFeatureFlags, + mockTheme, pendingUpload, stackScriptDialog, }); diff --git a/packages/manager/src/store/mockTheme/index.ts b/packages/manager/src/store/mockTheme/index.ts new file mode 100644 index 00000000000..163e84cd3b9 --- /dev/null +++ b/packages/manager/src/store/mockTheme/index.ts @@ -0,0 +1,24 @@ +import { Reducer } from 'redux'; +import actionCreatorFactory, { isType } from 'typescript-fsa'; + +import type { ThemeSelectionOptions } from 'src/dev-tools/ThemeSelector'; + +export type MockTheme = ThemeSelectionOptions['value']; + +export const actionCreator = actionCreatorFactory('@@manager/mock-theme'); + +export const setMockTheme = actionCreator('SET_MOCK_THEME'); + +export const defaultMockTheme: MockTheme = 'system'; + +export const reducer: Reducer = ( + state = defaultMockTheme, + action +) => { + if (isType(action, setMockTheme)) { + return action.payload; + } + return state; +}; + +export default reducer; From 83403ccf28091733d2de69c2a5c294ef6a81b568 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Wed, 21 Feb 2024 13:57:04 -0500 Subject: [PATCH 02/10] No store --- .../manager/src/dev-tools/ThemeSelector.tsx | 26 +++++++------------ packages/manager/src/mocks/serverHandlers.ts | 5 +--- packages/manager/src/store/index.ts | 6 +---- packages/manager/src/store/mockTheme/index.ts | 24 ----------------- 4 files changed, 11 insertions(+), 50 deletions(-) delete mode 100644 packages/manager/src/store/mockTheme/index.ts diff --git a/packages/manager/src/dev-tools/ThemeSelector.tsx b/packages/manager/src/dev-tools/ThemeSelector.tsx index 3bc33045ace..200b17ba018 100644 --- a/packages/manager/src/dev-tools/ThemeSelector.tsx +++ b/packages/manager/src/dev-tools/ThemeSelector.tsx @@ -1,12 +1,8 @@ import Grid from '@mui/material/Unstable_Grid2'; import * as React from 'react'; -import { useDispatch, useStore } from 'react-redux'; -import { setMockTheme } from 'src/store/mockTheme'; import { getStorage, setStorage } from 'src/utilities/storage'; -import type { Dispatch } from 'src/hooks/types'; - export const MOCK_THEME_STORAGE_KEY = 'devTools/theme'; export interface ThemeSelectionOptions { @@ -15,23 +11,22 @@ export interface ThemeSelectionOptions { } export const ThemeSelector = () => { - const dispatch: Dispatch = useDispatch(); - const store = useStore(); - const state = store.getState(); - - console.log(state); + const [mockTheme, setMockTheme] = React.useState< + ThemeSelectionOptions['value'] + >('system'); React.useEffect(() => { const storedTheme = getStorage(MOCK_THEME_STORAGE_KEY); if (storedTheme) { - dispatch(setMockTheme(storedTheme)); + setMockTheme(storedTheme); } - }, [dispatch]); + }, []); const handleSetTheme = (e: React.ChangeEvent) => { const selectedValue = e.target.value as ThemeSelectionOptions['value']; - dispatch(setMockTheme(selectedValue)); - setStorage(MOCK_THEME_STORAGE_KEY, e.target.value); + + setStorage(MOCK_THEME_STORAGE_KEY, selectedValue); + window.location.reload(); }; return ( @@ -40,10 +35,7 @@ export const ThemeSelector = () => {

Theme Selector

- handleSetTheme(e)} value={mockTheme}> diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index b79c38c3c68..f823c450d2c 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -9,7 +9,6 @@ import { } from '@linode/api-v4'; import { DateTime } from 'luxon'; import { rest } from 'msw'; -import { useStore } from 'react-redux'; import { regions } from 'src/__data__/regionsData'; import { MOCK_THEME_STORAGE_KEY } from 'src/dev-tools/ThemeSelector'; @@ -120,8 +119,6 @@ export const makeResourcePage = ( results: override.results ?? e.length, }); -const store = useStore(); - const statusPage = [ rest.get('*/api/v2/incidents*', (req, res, ctx) => { const response = incidentResponseFactory.build(); @@ -1153,7 +1150,7 @@ export const handlers = [ rest.get('*/profile/preferences', (req, res, ctx) => { return res( ctx.json({ - theme: getStorage(MOCK_THEME_STORAGE_KEY), + theme: getStorage(MOCK_THEME_STORAGE_KEY) ?? 'system', }) ); }), diff --git a/packages/manager/src/store/index.ts b/packages/manager/src/store/index.ts index a2e55301eb9..2728fe0b015 100644 --- a/packages/manager/src/store/index.ts +++ b/packages/manager/src/store/index.ts @@ -1,5 +1,4 @@ import { Store, applyMiddleware, combineReducers, createStore } from 'redux'; -import thunk from 'redux-thunk'; import { State as AuthState } from 'src/store/authentication'; import authentication, { @@ -30,11 +29,11 @@ import mockFeatureFlags, { MockFeatureFlagState, defaultMockFeatureFlagState, } from './mockFeatureFlags'; -import mockTheme, { MockTheme, defaultMockTheme } from './mockTheme'; import pendingUpload, { State as PendingUploadState, defaultState as pendingUploadState, } from './pendingUpload'; +import thunk from 'redux-thunk'; export interface ApplicationState { authentication: AuthState; @@ -43,7 +42,6 @@ export interface ApplicationState { longviewClients: LongviewState; longviewStats: LongviewStatsState; mockFeatureFlags: MockFeatureFlagState; - mockTheme: MockTheme; pendingUpload: PendingUploadState; stackScriptDialog: StackScriptDialogState; } @@ -55,7 +53,6 @@ export const defaultState: ApplicationState = { longviewClients: defaultLongviewState, longviewStats: defaultLongviewStatsState, mockFeatureFlags: defaultMockFeatureFlagState, - mockTheme: defaultMockTheme, pendingUpload: pendingUploadState, stackScriptDialog: stackScriptDialogDefaultState, }; @@ -70,7 +67,6 @@ const reducers = combineReducers({ longviewClients: longview, longviewStats, mockFeatureFlags, - mockTheme, pendingUpload, stackScriptDialog, }); diff --git a/packages/manager/src/store/mockTheme/index.ts b/packages/manager/src/store/mockTheme/index.ts deleted file mode 100644 index 163e84cd3b9..00000000000 --- a/packages/manager/src/store/mockTheme/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Reducer } from 'redux'; -import actionCreatorFactory, { isType } from 'typescript-fsa'; - -import type { ThemeSelectionOptions } from 'src/dev-tools/ThemeSelector'; - -export type MockTheme = ThemeSelectionOptions['value']; - -export const actionCreator = actionCreatorFactory('@@manager/mock-theme'); - -export const setMockTheme = actionCreator('SET_MOCK_THEME'); - -export const defaultMockTheme: MockTheme = 'system'; - -export const reducer: Reducer = ( - state = defaultMockTheme, - action -) => { - if (isType(action, setMockTheme)) { - return action.payload; - } - return state; -}; - -export default reducer; From 3910c672a7cf6aaae98724802506085e316895d0 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 09:07:59 -0500 Subject: [PATCH 03/10] Active MSW icon color --- packages/manager/.eslintrc.cjs | 2 +- .../manager/src/dev-tools/FeatureFlagTool.tsx | 13 +++++++-- .../manager/src/dev-tools/ThemeSelector.tsx | 14 ++++------ packages/manager/src/dev-tools/dev-tools.css | 10 ++++++- packages/manager/src/dev-tools/dev-tools.tsx | 8 ++++-- packages/manager/src/mocks/serverHandlers.ts | 28 +++++++++---------- 6 files changed, 46 insertions(+), 29 deletions(-) diff --git a/packages/manager/.eslintrc.cjs b/packages/manager/.eslintrc.cjs index 3c64f9b2c0e..6d53d5ec919 100644 --- a/packages/manager/.eslintrc.cjs +++ b/packages/manager/.eslintrc.cjs @@ -89,7 +89,7 @@ module.exports = { parserOptions: { // Warning if you want to set tsconfig.json, you ll need laso to set `tsconfigRootDir:__dirname` // BUT we decided not to use this feature due to a very important performance impact - // project: 'tsconfig.json', + // project: true, ecmaFeatures: { jsx: true, }, diff --git a/packages/manager/src/dev-tools/FeatureFlagTool.tsx b/packages/manager/src/dev-tools/FeatureFlagTool.tsx index 7a5b7586832..7b7ad6dec1f 100644 --- a/packages/manager/src/dev-tools/FeatureFlagTool.tsx +++ b/packages/manager/src/dev-tools/FeatureFlagTool.tsx @@ -1,14 +1,14 @@ 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'; +import { useDispatch } from 'react-redux'; import withFeatureFlagProvider from 'src/containers/withFeatureFlagProvider.container'; import { FlagSet, Flags } from 'src/featureFlags'; 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,11 @@ export const FeatureFlagTool = withFeatureFlagProvider(() => { setStorage(MOCK_FEATURE_FLAGS_STORAGE_KEY, updatedFlags); }; + const resetFlags = () => { + dispatch(setMockFeatureFlags(ldFlags)); + setStorage(MOCK_FEATURE_FLAGS_STORAGE_KEY, ''); + }; + return ( @@ -75,6 +81,9 @@ export const FeatureFlagTool = withFeatureFlagProvider(() => { ); })} + diff --git a/packages/manager/src/dev-tools/ThemeSelector.tsx b/packages/manager/src/dev-tools/ThemeSelector.tsx index 200b17ba018..f0e2e5beff3 100644 --- a/packages/manager/src/dev-tools/ThemeSelector.tsx +++ b/packages/manager/src/dev-tools/ThemeSelector.tsx @@ -5,15 +5,10 @@ import { getStorage, setStorage } from 'src/utilities/storage'; export const MOCK_THEME_STORAGE_KEY = 'devTools/theme'; -export interface ThemeSelectionOptions { - label: string; - value: 'dark' | 'light' | 'system'; -} +import type { ThemeChoice } from 'src/utilities/theme'; export const ThemeSelector = () => { - const [mockTheme, setMockTheme] = React.useState< - ThemeSelectionOptions['value'] - >('system'); + const [mockTheme, setMockTheme] = React.useState('system'); React.useEffect(() => { const storedTheme = getStorage(MOCK_THEME_STORAGE_KEY); @@ -23,8 +18,9 @@ export const ThemeSelector = () => { }, []); const handleSetTheme = (e: React.ChangeEvent) => { - const selectedValue = e.target.value as ThemeSelectionOptions['value']; + const selectedValue = e.target.value as ThemeChoice; + setMockTheme(selectedValue); setStorage(MOCK_THEME_STORAGE_KEY, selectedValue); window.location.reload(); }; @@ -35,7 +31,7 @@ export const ThemeSelector = () => {

Theme Selector

- diff --git a/packages/manager/src/dev-tools/dev-tools.css b/packages/manager/src/dev-tools/dev-tools.css index 535828c6756..3a6517f599a 100644 --- a/packages/manager/src/dev-tools/dev-tools.css +++ b/packages/manager/src/dev-tools/dev-tools.css @@ -13,12 +13,20 @@ overflow: auto; } +#dev-tools.mswEnabled svg { + color: #ff4d4f; +} + #dev-tools:hover { - height: 325px; + height: 375px; width: 100%; opacity: 0.9; } +#dev-tools:hover svg { + color: white; +} + #dev-tools .tools { display: none; } diff --git a/packages/manager/src/dev-tools/dev-tools.tsx b/packages/manager/src/dev-tools/dev-tools.tsx index 79eca902238..040bb0f018c 100644 --- a/packages/manager/src/dev-tools/dev-tools.tsx +++ b/packages/manager/src/dev-tools/dev-tools.tsx @@ -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,13 +11,16 @@ import './dev-tools.css'; import { EnvironmentToggleTool } from './EnvironmentToggleTool'; import { FeatureFlagTool } from './FeatureFlagTool'; import { MockDataTool } from './MockDataTool'; +import { isMSWEnabled } from './ServiceWorkerTool'; import { ThemeSelector } from './ThemeSelector'; function install(store: ApplicationStore) { function DevTools() { return ( -
-
🛠
+
+
+ +
diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index f823c450d2c..e2375fb63ef 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -14,7 +14,7 @@ import { regions } from 'src/__data__/regionsData'; import { MOCK_THEME_STORAGE_KEY } from 'src/dev-tools/ThemeSelector'; import { VLANFactory, - abuseTicketNotificationFactory, + // abuseTicketNotificationFactory, accountAvailabilityFactory, accountBetaFactory, accountFactory, @@ -1825,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' }, @@ -1932,8 +1932,8 @@ export const handlers = [ outageNotification, minorSeverityNotification, criticalSeverityNotification, - abuseTicket, - emailBounce, + // abuseTicket, + // emailBounce, migrationNotification, balanceNotification, blockStorageMigrationScheduledNotification, From 0147fa09f3cf57e79e727728d068b6c845ded1f7 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 11:43:52 -0500 Subject: [PATCH 04/10] Documentation update --- docs/development-guide/10-local-dev-tools.md | 18 +++++++++++-- .../manager/src/dev-tools/FeatureFlagTool.tsx | 2 +- .../manager/src/dev-tools/Preferences.tsx | 25 +++++++++++++++++++ packages/manager/src/dev-tools/dev-tools.tsx | 2 ++ 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 packages/manager/src/dev-tools/Preferences.tsx diff --git a/docs/development-guide/10-local-dev-tools.md b/docs/development-guide/10-local-dev-tools.md index 8dca8ebe66d..0365e8ef7ce 100644 --- a/docs/development-guide/10-local-dev-tools.md +++ b/docs/development-guide/10-local-dev-tools.md @@ -1,10 +1,24 @@ # Local Dev Tools -To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and environment switching. +To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and theme & environment switching. + +In order to access the dev tools, hover or click (mobile) on the 🛠 icon in the lower left corner of your browser window. The icon will be colored red if MSW is enabled. This mode is enabled by default while running the development server. To disable it, add `?dev-tools=false` to the URL, or write `dev-tools: false` to local storage. -This mode is disabled by default in production builds, but can be enabled by adding `?dev-tools=true` to the URL, or `dev-tools: true` to local storage. +This mode is disabled by default in production builds. + +## Feature Flags + +The display of the Flags in dev tools is defined in the `options` array in `FeatureFlagTool.tsx`. While it is convenient to add those switches to the dev tools, it is not always necessary as they can clutter the UI. Additionally, it is important to clean them up once the feature has been battle tested in production. + +The flags on/off values are stored in local storage for convenience and will be remembered on reload or app restart. + +By default, the boolean flags checkboxes represent their true values as returned by Launch Darkly (dev environment). Hitting the reset button will bring them back to those default values and clear local storage. + +## Theme Select + +The theme select in dev tools is a convenient way to store the theme choice while MSW is enabled (it won't affect your actual Application settings/preferences). The default is "system". ## Writing a new tool diff --git a/packages/manager/src/dev-tools/FeatureFlagTool.tsx b/packages/manager/src/dev-tools/FeatureFlagTool.tsx index 7b7ad6dec1f..6509cd132d8 100644 --- a/packages/manager/src/dev-tools/FeatureFlagTool.tsx +++ b/packages/manager/src/dev-tools/FeatureFlagTool.tsx @@ -1,8 +1,8 @@ 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'; + import withFeatureFlagProvider from 'src/containers/withFeatureFlagProvider.container'; import { FlagSet, Flags } from 'src/featureFlags'; import { Dispatch } from 'src/hooks/types'; diff --git a/packages/manager/src/dev-tools/Preferences.tsx b/packages/manager/src/dev-tools/Preferences.tsx new file mode 100644 index 00000000000..de25a3a0216 --- /dev/null +++ b/packages/manager/src/dev-tools/Preferences.tsx @@ -0,0 +1,25 @@ +import LinkIcon from '@mui/icons-material/Link'; +import * as React from 'react'; + +export const Preferences = () => { + return ( + <> +

Preferences

+ + Open preference Modal + + + + ); +}; diff --git a/packages/manager/src/dev-tools/dev-tools.tsx b/packages/manager/src/dev-tools/dev-tools.tsx index 040bb0f018c..531961e1fe2 100644 --- a/packages/manager/src/dev-tools/dev-tools.tsx +++ b/packages/manager/src/dev-tools/dev-tools.tsx @@ -11,6 +11,7 @@ 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'; @@ -34,6 +35,7 @@ function install(store: ApplicationStore) { + ) : null}
From 3c318e2aff8e7e34d5cd0532f5168d68e20593c0 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 11:58:28 -0500 Subject: [PATCH 05/10] Cleanup --- packages/manager/.eslintrc.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/.eslintrc.cjs b/packages/manager/.eslintrc.cjs index 6d53d5ec919..3c64f9b2c0e 100644 --- a/packages/manager/.eslintrc.cjs +++ b/packages/manager/.eslintrc.cjs @@ -89,7 +89,7 @@ module.exports = { parserOptions: { // Warning if you want to set tsconfig.json, you ll need laso to set `tsconfigRootDir:__dirname` // BUT we decided not to use this feature due to a very important performance impact - // project: true, + // project: 'tsconfig.json', ecmaFeatures: { jsx: true, }, From 2f10465e59be7d4012369611fc2873c5fdbf85cb Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 12:23:47 -0500 Subject: [PATCH 06/10] Added changeset: Improve dev toolsUI --- .../manager/.changeset/pr-10220-changed-1708622627827.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-10220-changed-1708622627827.md diff --git a/packages/manager/.changeset/pr-10220-changed-1708622627827.md b/packages/manager/.changeset/pr-10220-changed-1708622627827.md new file mode 100644 index 00000000000..dad5c5e47e3 --- /dev/null +++ b/packages/manager/.changeset/pr-10220-changed-1708622627827.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +Improve dev toolsUI ([#10220](https://github.com/linode/manager/pull/10220)) From d132a454a4dcdb7ae867463ff452d6da993ab1d0 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 13:23:53 -0500 Subject: [PATCH 07/10] Feedback --- docs/development-guide/10-local-dev-tools.md | 2 +- packages/manager/.changeset/pr-10220-changed-1708622627827.md | 2 +- packages/manager/src/dev-tools/FeatureFlagTool.tsx | 3 +++ packages/manager/src/dev-tools/dev-tools.css | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/development-guide/10-local-dev-tools.md b/docs/development-guide/10-local-dev-tools.md index 0365e8ef7ce..172269fb849 100644 --- a/docs/development-guide/10-local-dev-tools.md +++ b/docs/development-guide/10-local-dev-tools.md @@ -2,7 +2,7 @@ To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and theme & environment switching. -In order to access the dev tools, hover or click (mobile) on the 🛠 icon in the lower left corner of your browser window. The icon will be colored red if MSW is enabled. +In order to access the dev tools, hover or click (mobile) on the 🛠 icon in the lower left corner of your browser window. The icon will be colored green if MSW is enabled. This mode is enabled by default while running the development server. To disable it, add `?dev-tools=false` to the URL, or write `dev-tools: false` to local storage. diff --git a/packages/manager/.changeset/pr-10220-changed-1708622627827.md b/packages/manager/.changeset/pr-10220-changed-1708622627827.md index dad5c5e47e3..5344aa3cf4e 100644 --- a/packages/manager/.changeset/pr-10220-changed-1708622627827.md +++ b/packages/manager/.changeset/pr-10220-changed-1708622627827.md @@ -2,4 +2,4 @@ "@linode/manager": Changed --- -Improve dev toolsUI ([#10220](https://github.com/linode/manager/pull/10220)) +Improve dev tools UI ([#10220](https://github.com/linode/manager/pull/10220)) diff --git a/packages/manager/src/dev-tools/FeatureFlagTool.tsx b/packages/manager/src/dev-tools/FeatureFlagTool.tsx index 6509cd132d8..26213e2d33d 100644 --- a/packages/manager/src/dev-tools/FeatureFlagTool.tsx +++ b/packages/manager/src/dev-tools/FeatureFlagTool.tsx @@ -49,6 +49,9 @@ 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, ''); diff --git a/packages/manager/src/dev-tools/dev-tools.css b/packages/manager/src/dev-tools/dev-tools.css index 3a6517f599a..c619fb2c73e 100644 --- a/packages/manager/src/dev-tools/dev-tools.css +++ b/packages/manager/src/dev-tools/dev-tools.css @@ -14,7 +14,7 @@ } #dev-tools.mswEnabled svg { - color: #ff4d4f; + color: #aaff00; } #dev-tools:hover { From ac5fdcd020b7499dd227ba8328d8317329b65948 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 13:28:20 -0500 Subject: [PATCH 08/10] fix overflow issue --- packages/manager/src/dev-tools/dev-tools.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/dev-tools/dev-tools.css b/packages/manager/src/dev-tools/dev-tools.css index c619fb2c73e..23f3b0a5a28 100644 --- a/packages/manager/src/dev-tools/dev-tools.css +++ b/packages/manager/src/dev-tools/dev-tools.css @@ -10,7 +10,6 @@ width: 60px; transition: all 0.3s; z-index: 1; - overflow: auto; } #dev-tools.mswEnabled svg { @@ -21,6 +20,7 @@ height: 375px; width: 100%; opacity: 0.9; + overflow: auto; } #dev-tools:hover svg { From eb1140aeea6de7a26813375fd60be8c069f8b296 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 22 Feb 2024 14:27:21 -0500 Subject: [PATCH 09/10] improve clarity --- packages/manager/src/dev-tools/ThemeSelector.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/dev-tools/ThemeSelector.tsx b/packages/manager/src/dev-tools/ThemeSelector.tsx index f0e2e5beff3..ebb8a96f2af 100644 --- a/packages/manager/src/dev-tools/ThemeSelector.tsx +++ b/packages/manager/src/dev-tools/ThemeSelector.tsx @@ -28,7 +28,10 @@ export const ThemeSelector = () => { return ( -

Theme Selector

+

MSW Theme Selector

+

+ (only when MSW is enabled) +