From 44436e1dc0d4686193f6496dd869c030b068fdb1 Mon Sep 17 00:00:00 2001 From: DrillableBit Date: Mon, 9 Dec 2024 03:34:31 +0100 Subject: [PATCH] FeatureFlags, common colors --- .../_display/DiscordInviteCard.tsx | 7 + .../_display/EthernetStatusEffect.tsx | 2 +- .../_display/ImageOverlayWrapper.tsx | 2 +- .../_components/_display/SectionDivider.tsx | 19 ++- frontend/src/_components/_nav/Footer.tsx | 20 +-- frontend/src/_components/_nav/Navbar.tsx | 128 +++++++++++------- .../_nav/_footer_parts/Supporters.tsx | 15 +- .../_nav/_nav_parts/AuthNavbar.tsx | 6 +- frontend/src/_data/featureFlags.ts | 46 +++++++ .../app/(unprotected_pages)/about/page.tsx | 2 +- .../src/app/(unprotected_pages)/bots/page.tsx | 10 +- .../app/(unprotected_pages)/examples/page.tsx | 25 +++- .../app/(unprotected_pages)/status/page.tsx | 68 ++++++---- .../src/app/(unprotected_pages)/todo/page.tsx | 29 ---- frontend/src/app/page.tsx | 21 +-- frontend/tailwind.config.js | 10 +- 16 files changed, 263 insertions(+), 147 deletions(-) create mode 100644 frontend/src/_data/featureFlags.ts delete mode 100644 frontend/src/app/(unprotected_pages)/todo/page.tsx diff --git a/frontend/src/_components/_display/DiscordInviteCard.tsx b/frontend/src/_components/_display/DiscordInviteCard.tsx index 451a2590..6d8d294b 100644 --- a/frontend/src/_components/_display/DiscordInviteCard.tsx +++ b/frontend/src/_components/_display/DiscordInviteCard.tsx @@ -1,3 +1,4 @@ +import { getFeatureFlags } from "@/_data/featureFlags"; import Image from "next/image"; import React from "react"; @@ -16,6 +17,8 @@ interface DiscordInviteCardProps { onlineCount, serverImageUrl, }) => { + const discordData = getFeatureFlags().heroDiscordUsersInfo; + return (
@@ -38,14 +41,18 @@ interface DiscordInviteCardProps {

{serverName}

{description}

+ {discordData ?
+
{onlineCount} Online
{memberCount} Members
+
+ : null } { }} >
{ // Determine the background class based on the darken prop const bgClass = { - 1: 'bg-customGreenDarken1', - 2: 'bg-customGreenDarken2', - 3: 'bg-customGreenDarken3', - 9: 'bg-customGreenDarken9', + 1: 'brightness-100', + 2: 'brightness-95', + 3: 'brightness-90', + 5: 'brightness-75', + 9: 'brightness-50', + // 1: 'bg-customGreenDarken1', + // 2: 'bg-customGreenDarken2', + // 3: 'bg-customGreenDarken3', + // 9: 'bg-customGreenDarken9', }[darken || 1]; // Default to bg-customGreenDarken1 if no darken value is provided return ( -
+
{/* Full-width line */} -
+
{title ? (
{/* Outer border trapezoid */} -
+
{/* Inner background trapezoid */}

{title}

diff --git a/frontend/src/_components/_nav/Footer.tsx b/frontend/src/_components/_nav/Footer.tsx index c025d738..a752a056 100644 --- a/frontend/src/_components/_nav/Footer.tsx +++ b/frontend/src/_components/_nav/Footer.tsx @@ -1,29 +1,29 @@ import React from "react"; -import { footerLinks } from "@/_data/footerLinks"; +import { footerLinks } from "@/_data/footerLinks"; import SocialComponent from "./_footer_parts/SocialNavItem"; import ServicesComponent from "./_footer_parts/ServicesNavItem"; import SupportersComponent from "./_footer_parts/Supporters"; import SectionDivider from "../_display/SectionDivider"; +import { getFeatureFlags } from "@/_data/featureFlags"; const Footer: React.FC = () => { + const servies = getFeatureFlags().footerServices; + return (
- +
- - - - - + {servies ? : null} + + -
- © {new Date().getFullYear()} AI Arena. All rights reserved. + © {new Date().getFullYear()} AI Arena. All rights reserved.
); }; -export default Footer; \ No newline at end of file +export default Footer; diff --git a/frontend/src/_components/_nav/Navbar.tsx b/frontend/src/_components/_nav/Navbar.tsx index 583fdadf..d13d9c59 100644 --- a/frontend/src/_components/_nav/Navbar.tsx +++ b/frontend/src/_components/_nav/Navbar.tsx @@ -8,7 +8,8 @@ import MobileNavItem from "./_nav_parts/MobileNavItem"; import AuthNavBar from "./_nav_parts/AuthNavbar"; import { getPublicPrefix } from "@/_lib/getPublicPrefix"; import { usePathname } from "next/navigation"; - +import { getFeatureFlags } from "@/_data/featureFlags"; +import { useUserContext } from "../providers/UserProvider"; const navLinks = [ { @@ -16,54 +17,56 @@ const navLinks = [ path: `${getPublicPrefix()}/`, showLoggedIn: true, showLoggedOut: true, + featureFlag: null, }, { title: "Wiki", path: "https://aiarena.net/wiki/", showLoggedIn: true, showLoggedOut: true, + featureFlag: null, }, { title: "Competitions", path: `${getPublicPrefix()}/competitions/`, showLoggedIn: true, showLoggedOut: true, + featureFlag: null, }, { title: "About us", path: `${getPublicPrefix()}/about/`, showLoggedIn: true, showLoggedOut: true, + featureFlag: null, }, { title: "Status", path: `${getPublicPrefix()}/status/`, showLoggedIn: true, showLoggedOut: true, + featureFlag: getFeatureFlags().statusPage, }, { title: "Bots", path: `${getPublicPrefix()}/bots/`, showLoggedIn: true, showLoggedOut: true, + featureFlag: getFeatureFlags().botsPage, }, { title: "Profile", path: `${getPublicPrefix()}/profile/`, showLoggedIn: true, showLoggedOut: false, + featureFlag: null, }, { title: "Examples", path: `${getPublicPrefix()}/examples/`, showLoggedIn: true, showLoggedOut: true, - }, - { - title: "ToDo", - path: `${getPublicPrefix()}/todo/`, - showLoggedIn: true, - showLoggedOut: true, + featureFlag: getFeatureFlags().examples, }, ]; @@ -74,7 +77,7 @@ const navbarTitle = { function Navbar() { const [navbar, setNavbar] = useState(false); const router = usePathname(); - + const { user } = useUserContext(); const handleMenu = () => { if (navbar === true) { @@ -114,7 +117,10 @@ function Navbar() { <>
) : null} diff --git a/frontend/src/_components/_nav/_footer_parts/Supporters.tsx b/frontend/src/_components/_nav/_footer_parts/Supporters.tsx index 666da192..6acbd789 100644 --- a/frontend/src/_components/_nav/_footer_parts/Supporters.tsx +++ b/frontend/src/_components/_nav/_footer_parts/Supporters.tsx @@ -4,21 +4,30 @@ import Image from "next/image"; import { Supporters } from "@/_data/footerLinks"; import WrappedTitle from "@/_components/_display/WrappedTitle"; import { getPublicPrefix } from "@/_lib/getPublicPrefix"; +import { getFeatureFlags } from "@/_data/featureFlags"; interface SupportersComponentProps { - supporters: Supporters[]; + supporterData: Supporters[]; } const SupportersComponent: React.FC = ({ - supporters, + supporterData, }) => { + + const supporters = getFeatureFlags().supporters + return (
-

{supporters[0].name}

+ + {supporters? + <> +

{supporterData[0].name}

Thank you for your support!
Your contributions help us keep going.

+ + : null}
diff --git a/frontend/src/_components/_nav/_nav_parts/AuthNavbar.tsx b/frontend/src/_components/_nav/_nav_parts/AuthNavbar.tsx index 01742662..13a9bc78 100644 --- a/frontend/src/_components/_nav/_nav_parts/AuthNavbar.tsx +++ b/frontend/src/_components/_nav/_nav_parts/AuthNavbar.tsx @@ -10,9 +10,7 @@ import { useSignOut } from "@/_components/_hooks/useSignOut"; import { useUserContext } from "@/_components/providers/UserProvider"; import { useRouter } from "next/navigation"; - export default function AuthNavBar() { - const router = useRouter(); // Next.js router for navigation const { user, setUser, fetching } = useUserContext(); const [signOut, isSigningOut] = useSignOut(); @@ -50,11 +48,11 @@ export default function AuthNavBar() { - Log in + Login
)}
); -} \ No newline at end of file +} diff --git a/frontend/src/_data/featureFlags.ts b/frontend/src/_data/featureFlags.ts new file mode 100644 index 00000000..2e0618e6 --- /dev/null +++ b/frontend/src/_data/featureFlags.ts @@ -0,0 +1,46 @@ +// Define the type for feature flags +type FeatureFlags = { + heroTasks: boolean; + heroDiscordUsersInfo: boolean; + footerServices: boolean; + statusServerStatus: boolean; + statusPage: boolean; + botsPage: boolean; + competitionMaps: boolean; + competitionVideo: boolean; + supporters:boolean; + examples:boolean; +}; + +// Set this to true to override DEV behavior +const devBehaviorOverride = true; + +// Feature flags configuration function +export function getFeatureFlags(): FeatureFlags { + // Check if DEV mode is enabled and not overridden + const isDevMode = process.env.NODE_ENV === 'development' && !devBehaviorOverride; + + // Default feature flags + const defaultFlags: FeatureFlags = { + heroTasks: false, + heroDiscordUsersInfo: false, + footerServices: false, + statusServerStatus: false, + statusPage: true, + botsPage: false, + competitionMaps: false, + competitionVideo: false, + supporters:false, + examples:false, + }; + + // If DEV mode is enabled, set all flags to true + if (isDevMode) { + return Object.fromEntries( + Object.keys(defaultFlags).map(key => [key, true]) + ) as FeatureFlags; // Cast the result to the FeatureFlags type + } + + // Return default flags in other cases + return defaultFlags; +} \ No newline at end of file diff --git a/frontend/src/app/(unprotected_pages)/about/page.tsx b/frontend/src/app/(unprotected_pages)/about/page.tsx index 1b13219d..8ddf1bb5 100644 --- a/frontend/src/app/(unprotected_pages)/about/page.tsx +++ b/frontend/src/app/(unprotected_pages)/about/page.tsx @@ -17,7 +17,7 @@ const AboutUs = () => { <> {/* AI Arena Overview */} -
+

What is AI Arena?

diff --git a/frontend/src/app/(unprotected_pages)/bots/page.tsx b/frontend/src/app/(unprotected_pages)/bots/page.tsx index 198fbfc8..c16a422e 100644 --- a/frontend/src/app/(unprotected_pages)/bots/page.tsx +++ b/frontend/src/app/(unprotected_pages)/bots/page.tsx @@ -8,11 +8,19 @@ import WrappedTitle from "@/_components/_display/WrappedTitle"; import mockBots from "@/_data/mockBots.json"; import { formatDate } from "@/_lib/dateUtils"; import Link from "next/link"; - +import {getFeatureFlags} from "@/_data/featureFlags" +import { notFound } from "next/navigation"; export default function Page() { + const botsPage = getFeatureFlags().botsPage + if (!botsPage) { + notFound(); + return null; + } + return ( + <> { + const examples = getFeatureFlags().examples; + if (!examples) { + notFound(); + return false; + } + return ( <>
@@ -35,7 +43,8 @@ const ExamplePage: React.FC = () => {

- An example of SHINY  + An example of  + SHINY  text.

@@ -45,22 +54,24 @@ const ExamplePage: React.FC = () => {

- An example of SHINY  - text. + An example of  + SHINY  + text.

- With a SHINY  + With a SHINY  Box.

- An example of SHINY  - text. + An example of  + SHINY  + text.

- With a SHINY  + With a SHINY  Box.

diff --git a/frontend/src/app/(unprotected_pages)/status/page.tsx b/frontend/src/app/(unprotected_pages)/status/page.tsx index 1ac4e76e..830a816b 100644 --- a/frontend/src/app/(unprotected_pages)/status/page.tsx +++ b/frontend/src/app/(unprotected_pages)/status/page.tsx @@ -6,6 +6,8 @@ import Image from "next/image"; import React from "react"; import mockUptimeData from "@/_data/mockUptime.json"; import PreFooterSpacer from "@/_components/_display/PreFooterSpacer"; +import { notFound } from "next/navigation"; // Import the notFound function +import { getFeatureFlags }from "@/_data/featureFlags" const ActivityFeed = () => { const activities = [ @@ -26,10 +28,8 @@ const ActivityFeed = () => { { time: "3d ago", event: "Bot SharkbotTest was updated." }, ]; - - return ( -
+
    {activities.map((activity, index) => ( @@ -53,13 +53,13 @@ const UptimeGraph = ({ data: { hour: string; uptime: number }[]; }) => { return ( -
    +
    -
    +
    {data.map((entry, index) => (
    { return ( -
    +
    • @@ -107,7 +107,7 @@ const Stats = () => { const Thanks = () => { return ( -
      +
      Thank you Spacemen for supporting AI arena!

      Heart icon

      @@ -115,28 +115,48 @@ const Thanks = () => { ); }; -const HomePage = () => { +const HomePage = () => { + const statusPage = getFeatureFlags().statusPage + const serverStatus = getFeatureFlags().statusServerStatus + const supporters = getFeatureFlags().supporters + + + if (!statusPage) { + notFound() + return null + } + const uptimeData = mockUptimeData; return ( <> -
      -
      -
      - -
      -
      - - +
      +
      +
      + +
      +
      + + {supporters? + : null} + +
      -
      + { -
      - {uptimeData.map((server) => ( - - ))} + serverStatus ? +
      + {uptimeData.map((server) => ( + + ))} +
      + : null + }
      -
      - + ); }; diff --git a/frontend/src/app/(unprotected_pages)/todo/page.tsx b/frontend/src/app/(unprotected_pages)/todo/page.tsx deleted file mode 100644 index 86a89bcc..00000000 --- a/frontend/src/app/(unprotected_pages)/todo/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client" - -import React from "react"; - - -const ToDoPage: React.FC = () => { - return ( - <> -
      -

      Todo

      - -
        -
      • -

        -There has to be a way to bypass the twitch commercial.

        -
      • -
      • -

        - Implement SSR & GQL db

        -
      • -
      • -

        - Adding content shift guards for hydrated content

        -
      • - -
      -
      - - ); -}; - -export default ToDoPage; diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index d002f22c..8e8a7e55 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -21,6 +21,8 @@ import InitiationHeroTasks from "@/_components/_display/InitiationHeroTasks"; import { ImageOverlayWrapper } from "@/_components/_display/ImageOverlayWrapper"; import DiscordInviteCard from "@/_components/_display/DiscordInviteCard"; import { getPublicPrefix } from "@/_lib/getPublicPrefix"; +import { getFeatureFlags } from "@/_data/featureFlags"; +import MainButton from "@/_components/_props/MainButton"; const tasks = [ { @@ -56,6 +58,7 @@ export default function Page() { const [competitions, setCompetitions] = useState([]); const [news, setNews] = useState([]); const [error, setError] = useState(null); + const heroTasks = getFeatureFlags().heroTasks; const newsData = useNews(); @@ -76,12 +79,14 @@ export default function Page() { AI Arena
      -

      - Welcome to the AI Arena! -

      -
      - -
      +

      Welcome to the AI Arena!

      + {heroTasks ? ( +
      + +
      + ) : ( + + )}
      @@ -90,7 +95,7 @@ export default function Page() { imageUrl={`/generated_assets/dall_e_bg_2.webp`} alt="Discord background" sectionDivider={true} - sectionDividerDarken={2} + sectionDividerDarken={5} blurAmount="blur-md" opacityAmount="opacity-70" > @@ -114,7 +119,7 @@ export default function Page() { imageUrl={`/demo_assets/demo-news.webp`} alt="Space Background" sectionDivider={true} - sectionDividerDarken={2} + sectionDividerDarken={5} blurAmount="blur-sm" opacityAmount="opacity-80" > diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index ca49e2ad..42ce1b25 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -5,6 +5,11 @@ const CustomHighlightVar = 'rgba(154, 255, 70, 1)'; const CustomPrimaryVar = 'rgba(134, 194, 50, 1)'; +// const CustomPrimaryVar = `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor( +// Math.random() * 256 +// )}, ${Math.floor(Math.random() * 256)}, 1)`; + + const CustomBackgroundColorVar = 'rgba(134, 194, 50, 1)'; @@ -46,7 +51,8 @@ module.exports = { - customGreenHighlight1: 'rgba(255, 255, 0, 1)', + customGreenHighlight1: 'rgba(255, 255, 0, 1)', + // customGreenHighlight1: 'rgba(0, 0, 255, 1)', customGreenDarken1: 'rgba(104, 144, 20, 1)', customGreenDarken2: 'rgba(84, 110, 15, 1)', customGreenDarken3: 'rgba(64, 84, 5, 1)', @@ -82,7 +88,7 @@ module.exports = { borderColor: { - customGreen: 'rgba(134, 194, 50, 1)', + customGreen: CustomPrimaryVar, softTeal: '#32B3A4', mellowYellow: '#F5A623', },