Skip to content

Commit

Permalink
feat: add banner about cloud offering
Browse files Browse the repository at this point in the history
  • Loading branch information
markphelps committed May 13, 2024
1 parent 057191a commit 772d109
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 5 deletions.
10 changes: 10 additions & 0 deletions ui/src/app/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ import {
useListNamespacesQuery
} from './namespaces/namespacesSlice';
import CommandDialog from '~/components/command/CommandDialog';
import Banner from '~/components/Banner';
import { selectDismissedBanner } from './events/eventSlice';

function InnerLayout() {
const { session } = useSession();
const [sidebarOpen, setSidebarOpen] = useState(false);

const dismissedBanner = useSelector(selectDismissedBanner);
const dispatch = useAppDispatch();

const { namespaceKey } = useParams();
Expand Down Expand Up @@ -75,6 +78,13 @@ function InnerLayout() {
<Sidebar setSidebarOpen={setSidebarOpen} sidebarOpen={sidebarOpen} />
<div className="bg-white flex min-h-screen flex-col md:pl-64">
<Header setSidebarOpen={setSidebarOpen} />
{!dismissedBanner && (
<Banner
title="Introducing Flipt Hybrid Cloud"
description="Learn about our latest offering that enhances Flipt Open Source with managed security and support"
href="https://docs.flipt.io/cloud/overview"
/>
)}
<main className="flex px-6 py-10">
<div className="w-full overflow-x-auto px-4 sm:px-6 lg:px-8">
<Outlet />
Expand Down
11 changes: 9 additions & 2 deletions ui/src/app/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
AcademicCapIcon,
BookOpenIcon,
ChatBubbleLeftIcon,
CloudIcon,
CodeBracketIcon,
CommandLineIcon,
PuzzlePieceIcon,
Expand All @@ -20,9 +21,16 @@ const gettingStartedTiles = [
icon: AcademicCapIcon,
name: 'Get Started',
description: 'Learn how to create your first feature flag',
className: 'sm:col-span-2',
href: 'https://www.flipt.io/docs/introduction'
},
{
icon: CloudIcon,
name: 'Introducing Flipt Hybrid Cloud',
className: 'sm:col-span-2',
description:
'Learn more about our managed offering with enhanced security and support',
href: 'https://www.flipt.io/docs/cloud/overview'
},
{
icon: CommandLineIcon,
name: 'Try the CLI',
Expand All @@ -40,7 +48,6 @@ const gettingStartedTiles = [
icon: PuzzlePieceIcon,
name: 'Integrate Your Application',
description: 'Use our SDKs to integrate your applications in your language',
className: 'sm:col-span-2',
href: 'https://www.flipt.io/docs/integration/overview'
}
];
Expand Down
14 changes: 12 additions & 2 deletions ui/src/app/events/eventSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { RootState } from '~/store';
export const eventKey = 'event';
interface IEventState {
completedOnboarding: boolean;
dismissedBanner: boolean;
}

const initialState: IEventState = {
completedOnboarding: false
completedOnboarding: false,
dismissedBanner: false
};

export const eventSlice = createSlice({
Expand All @@ -16,15 +18,23 @@ export const eventSlice = createSlice({
reducers: {
onboardingCompleted: (state) => {
state.completedOnboarding = true;
},
bannerDismissed: (state) => {
state.dismissedBanner = true;
}
}
});

export const { onboardingCompleted } = eventSlice.actions;
export const { onboardingCompleted, bannerDismissed } = eventSlice.actions;

export const selectCompletedOnboarding = createSelector(
[(state: RootState) => state.user],
(user) => user.completedOnboarding
);

export const selectDismissedBanner = createSelector(
[(state: RootState) => state.user],
(user) => user.dismissedBanner
);

export default eventSlice.reducer;
44 changes: 44 additions & 0 deletions ui/src/components/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { XMarkIcon } from '@heroicons/react/20/solid';
import { useDispatch } from 'react-redux';
import { bannerDismissed } from '~/app/events/eventSlice';

type BannerProps = {
title: string;
description: string;
href: string;
};

export default function Banner(props: BannerProps) {
const { title, description, href } = props;

const dispatch = useDispatch();

return (
<div className="bg-violet-700 flex items-center gap-x-6 px-6 py-2.5 sm:px-3.5 sm:before:flex-1">
<p className="text-white text-sm leading-6">
<a href={href}>
<strong className="font-semibold">{title}</strong>
<svg
viewBox="0 0 2 2"
className="mx-2 inline h-0.5 w-0.5 fill-current"
aria-hidden="true"
>
<circle cx={1} cy={1} r={1} />
</svg>
{description}&nbsp;
<span aria-hidden="true">&rarr;</span>
</a>
</p>
<div className="flex flex-1 justify-end">
<button
type="button"
className="-m-3 p-3 focus-visible:outline-offset-[-4px]"
onClick={() => dispatch(bannerDismissed())}
>
<span className="sr-only">Dismiss</span>
<XMarkIcon className="text-white h-5 w-5" aria-hidden="true" />
</button>
</div>
</div>
);
}
5 changes: 4 additions & 1 deletion ui/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import { eventSlice, eventKey } from './app/events/eventSlice';
const listenerMiddleware = createListenerMiddleware();

listenerMiddleware.startListening({
matcher: isAnyOf(eventSlice.actions.onboardingCompleted),
matcher: isAnyOf(
eventSlice.actions.onboardingCompleted,
eventSlice.actions.bannerDismissed
),
effect: (_action, api) => {
// save to local storage
localStorage.setItem(
Expand Down

0 comments on commit 772d109

Please sign in to comment.