+ >
+ )
+}
\ No newline at end of file
diff --git a/src/LoadingIndicator.tsx b/src/LoadingIndicator.tsx
index bf664ff..eff0556 100644
--- a/src/LoadingIndicator.tsx
+++ b/src/LoadingIndicator.tsx
@@ -1,9 +1,11 @@
export const LoadingIndicator = () => {
- return (
+ const showMessage = true // This can be set based on your application's state
+
+ return showMessage ? (
Loading...
- )
-}
\ No newline at end of file
+ ) : null
+}
diff --git a/src/Nav.tsx b/src/Nav.tsx
new file mode 100644
index 0000000..e31a2db
--- /dev/null
+++ b/src/Nav.tsx
@@ -0,0 +1,25 @@
+// components/NavBar.js
+import { Link } from 'react-router-dom'
+import { useFeatureFlag } from './useFeatureFlag'
+import { customRoutes } from './App'
+import { flags } from './feature-management/flags'
+
+export const Nav = () => {
+ const enabledRoutes = customRoutes.filter((route) => {
+ const routeFlag = route.featureFlag
+ ? useFeatureFlag(flags[route.featureFlag])
+ : true
+ return routeFlag
+ })
+
+ return (
+
+ )
+}
diff --git a/src/feature-management/FeatureFlagsProvider.tsx b/src/feature-management/FeatureFlagsProvider.tsx
index 621d713..3f43be4 100644
--- a/src/feature-management/FeatureFlagsProvider.tsx
+++ b/src/feature-management/FeatureFlagsProvider.tsx
@@ -1,17 +1,16 @@
-import React, {useEffect, useState} from "react";
-import Rox from "rox-browser";
-import {flags} from "./flags.ts";
-import {FeatureFlagsContext, initialFlagState} from "./index.ts";
+import React, { useEffect, useState } from 'react'
+import Rox from 'rox-browser'
+import { flags } from './flags.ts'
+import { FeatureFlagsContext, initialFlagState } from './index.ts'
// TODO: insert your SDK key from https://cloudbees.io/ below.
const sdkKey = ''
type Props = {
children?: React.ReactNode
-};
-
-export const FeatureFlagsProvider = ({children} : Props): React.ReactNode => {
+}
+export const FeatureFlagsProvider = ({ children }: Props): React.ReactNode => {
const [flagState, setFlagState] = useState(initialFlagState)
const [error, setError] = useState(undefined)
@@ -24,44 +23,42 @@ export const FeatureFlagsProvider = ({children} : Props): React.ReactNode => {
}
initialised.current = true
- setFlagState({...flagState, loading: true})
+ setFlagState({ ...flagState, loading: true })
+ // Register the flags
Rox.register('', flags)
- const initFeatureFlags = async() => {
-
+ const initFeatureFlags = async () => {
// Easy to forget to insert your SDK key where shown above, so let's check & remind you!
// @ts-ignore
if (sdkKey === '') {
- throw new Error("You haven't yet inserted your SDK key into FeatureFlagsProvider.tsx - the application below will not update until you do so. Please check the README.adoc for instructions.")
+ throw new Error()
+ // "You haven't yet inserted your SDK key into FeatureFlagsProvider.tsx - the application below will not update until you do so. Please check the README.adoc for instructions."
}
await Rox.setup(sdkKey, {
configurationFetchedHandler(fetcherResult: Rox.RoxFetcherResult) {
- if (fetcherResult.fetcherStatus === "APPLIED_FROM_NETWORK") {
+ if (fetcherResult.fetcherStatus === 'APPLIED_FROM_NETWORK') {
setFlagState({
...flagState,
})
}
- }
+ },
})
- setFlagState({...flagState, loading: false})
+ setFlagState({ ...flagState, loading: false })
}
initFeatureFlags().catch((e) => {
console.error(e.message)
setError(e.message)
- setFlagState({...flagState, loading: false})
+ setFlagState({ ...flagState, loading: false })
})
-
}, [flagState])
return (
- {error && (
-
{error}
- )}
+ {error &&
{error}
}
{children}
diff --git a/src/feature-management/flags.ts b/src/feature-management/flags.ts
index f93673f..386a6b7 100644
--- a/src/feature-management/flags.ts
+++ b/src/feature-management/flags.ts
@@ -1,18 +1,21 @@
-import {Flag, RoxString, RoxNumber} from "rox-browser";
+import { Flag, RoxString } from 'rox-browser'
type IFeatureFlags = typeof flags
export interface IFeatureFlagsState extends IFeatureFlags {
- loading: boolean;
+ loading: boolean
}
export const flags = {
+ home: new Flag(true),
+ about: new Flag(false),
// Boolean - should the message be shown?
showMessage: new Flag(),
// String - the message to show.
- message: new RoxString('This is the default message; try changing some flag values!'),
+ message: new RoxString(
+ 'This is the default message; try changing some flag values!'
+ ),
// String (with options) - the color of the message text.
- fontColor: new RoxString('Black', ['Red', 'Green', 'Blue', 'Black']),
- // Number (with options) - the size of the message text.
- fontSize: new RoxNumber(12, [12, 16, 24]),
-}
+ fontColor: new RoxString('White', ['Red', 'Green', 'Blue', 'Black']),
+ // Removed the fontSize flag as it was no longer necessary.
+}
\ No newline at end of file
diff --git a/src/feature-management/index.ts b/src/feature-management/index.ts
index 76e54e1..2368640 100644
--- a/src/feature-management/index.ts
+++ b/src/feature-management/index.ts
@@ -1,11 +1,12 @@
-import {createContext, useContext} from "react";
-import {flags, IFeatureFlagsState} from "./flags.ts";
+import { createContext, useContext } from 'react'
+import { flags, IFeatureFlagsState } from './flags.ts'
export const initialFlagState: IFeatureFlagsState = {
...flags,
- loading: false
+ loading: false,
}
-export const FeatureFlagsContext = createContext(initialFlagState);
+export const FeatureFlagsContext = createContext(initialFlagState)
-export const useFeatureFlags: () => IFeatureFlagsState = () => useContext(FeatureFlagsContext);
\ No newline at end of file
+export const useFeatureFlags: () => IFeatureFlagsState = () =>
+ useContext(FeatureFlagsContext)
diff --git a/src/main.tsx b/src/main.tsx
index f5fec51..cb42f1c 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -2,12 +2,15 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
-import {FeatureFlagsProvider} from "./feature-management/FeatureFlagsProvider.tsx";
+import { FeatureFlagsProvider } from './feature-management/FeatureFlagsProvider.tsx'
+import { BrowserRouter } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')!).render(
-
+
+
+
- ,
+
)
diff --git a/src/useFeatureFlag.ts b/src/useFeatureFlag.ts
new file mode 100644
index 0000000..b291666
--- /dev/null
+++ b/src/useFeatureFlag.ts
@@ -0,0 +1,21 @@
+import { useMemo } from 'react'
+import { type RoxNumber, type RoxString, Flag } from 'rox-browser'
+
+type FlagValue = T extends Flag
+ ? boolean
+ : T extends RoxString
+ ? string
+ : T extends RoxNumber
+ ? number
+ : never
+
+export const useFeatureFlag = (
+ flag: T
+) =>
+ useMemo>(() => {
+ if (flag instanceof Flag) {
+ return flag.isEnabled() as FlagValue
+ } else {
+ return flag.getValue() as FlagValue
+ }
+ }, [flag])
diff --git a/yarn.lock b/yarn.lock
index 7b7cc97..cdfdb01 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -836,6 +836,11 @@ convert-source-map@^2.0.0:
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+cookie@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610"
+ integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
+
cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -1500,6 +1505,21 @@ react-refresh@^0.14.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
+react-router-dom@^7.6.2:
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.6.2.tgz#e97e386ab390b6503a2a7968124b7a3237fb10c7"
+ integrity sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA==
+ dependencies:
+ react-router "7.6.2"
+
+react-router@7.6.2:
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.6.2.tgz#9f48b343bead7d0a94e28342fc4f9ae29131520e"
+ integrity sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==
+ dependencies:
+ cookie "^1.0.1"
+ set-cookie-parser "^2.6.0"
+
react@^18.2.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
@@ -1580,6 +1600,11 @@ semver@^7.6.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
+set-cookie-parser@^2.6.0:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
+ integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
+
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"