diff --git a/README.md b/README.md index f71bd465..c21f6dae 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,6 @@ Run `mix dash` and `mix help dash.` for more info. - SECRET_KEY_BASE - Base secret key. This should be a strong cryptographcially generated secret. - BASIC_AUTH_USERNAME - Username for site-wide basic auth. - BASIC_AUTH_PASSWORD - Password for site-wide basic auth. +- AUTH_PUBLIC_KEY - Public key for JWT auth provided by auth server. Used in authentication. +- AUTH_SERVER - Server used for login links. e.g. "auth.myhubs.net" +- FXA_SERVER - Firefox Accounts server used for account management links. e.g. "accounts.firefox.com" diff --git a/assets/package-lock.json b/assets/package-lock.json index 6002cd5d..0721b848 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -10,7 +10,8 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-redux": "^7.2.8", - "react-router-dom": "^6.2.2" + "react-router-dom": "^6.2.2", + "react-toastify": "^9.0.5" }, "devDependencies": { "@babel/preset-env": "^7.16.11", @@ -2971,6 +2972,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6022,6 +6031,18 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "node_modules/react-toastify": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.5.tgz", + "integrity": "sha512-dszPCeQINY+Nm6HmsiAXT/7wsazPqv0S/RuhIYLAW+fTKcd3T1iRjZG0XqrN9nvAzqaE5J6uxMaiBrOevxjY8g==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/redux": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", @@ -9161,6 +9182,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -11451,6 +11477,14 @@ } } }, + "react-toastify": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.5.tgz", + "integrity": "sha512-dszPCeQINY+Nm6HmsiAXT/7wsazPqv0S/RuhIYLAW+fTKcd3T1iRjZG0XqrN9nvAzqaE5J6uxMaiBrOevxjY8g==", + "requires": { + "clsx": "^1.1.1" + } + }, "redux": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", diff --git a/assets/package.json b/assets/package.json index 4ebf3bdf..e68c6538 100644 --- a/assets/package.json +++ b/assets/package.json @@ -10,7 +10,8 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-redux": "^7.2.8", - "react-router-dom": "^6.2.2" + "react-router-dom": "^6.2.2", + "react-toastify": "^9.0.5" }, "devDependencies": { "@babel/preset-env": "^7.16.11", diff --git a/assets/src/components/common/icons/index.js b/assets/src/components/common/icons/index.js index c2babd7d..712e77f4 100644 --- a/assets/src/components/common/icons/index.js +++ b/assets/src/components/common/icons/index.js @@ -9,6 +9,8 @@ import logOut from "./log-out.svg"; import external from "./external.svg"; import backButton from "./back-button.svg"; import copy from "./copy.svg"; +import valid from "./valid.svg"; +import invalid from "./invalid.svg"; import "./Icon.css"; @@ -49,3 +51,11 @@ export function IconBackButton() { export function IconCopy() { return copy; } + +export function IconValid() { + return valid; +} + +export function IconInvalid() { + return invalid; +} diff --git a/assets/src/components/common/icons/invalid.svg b/assets/src/components/common/icons/invalid.svg new file mode 100644 index 00000000..1b38dc6f --- /dev/null +++ b/assets/src/components/common/icons/invalid.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/src/components/common/icons/valid.svg b/assets/src/components/common/icons/valid.svg new file mode 100644 index 00000000..f3b69232 --- /dev/null +++ b/assets/src/components/common/icons/valid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/src/components/containers/HomeContainer.js b/assets/src/components/containers/HomeContainer.js index 0428c93d..53186c26 100644 --- a/assets/src/components/containers/HomeContainer.js +++ b/assets/src/components/containers/HomeContainer.js @@ -9,12 +9,12 @@ import { useCreateHubMutation } from "../services/hubs"; import { selectAccount } from "../store/account"; import { featureIsEnabled, CREATE_HUBS } from "../utils/feature-flags"; import { HubBuilding } from "../display/HubBuilding"; -import { CREATING } from "../utils/hub-constants"; +import { STATUS_CREATING } from "../utils/hub-constants"; function HubLoading({ isBuildingHub }) { return isBuildingHub ? ( <> - + ) : ( @@ -32,7 +32,7 @@ export function HomeContainer() { return (
- {isLoading && } + {isLoading ? : ""} {isError && Unable to load Hubs} {isReady && (!hasHubs ? You don't have any hubs : hubs.map((hub) => ))} diff --git a/assets/src/components/display/Header.js b/assets/src/components/display/Header.js index 97916c11..c588f47b 100644 --- a/assets/src/components/display/Header.js +++ b/assets/src/components/display/Header.js @@ -3,6 +3,7 @@ import { Link } from "react-router-dom"; import { useSelector } from "react-redux"; import "./Header.css"; +import { FXA_SERVER } from "../utils/app-config"; import { IconLogOut, IconExternal } from "../common/icons"; import logoBlack from "../../images/logo-black.svg"; import { selectAccount } from "../store/account"; @@ -43,12 +44,7 @@ export function Header() { profile picture {account.email} {/* TODO Pull domain from some configuration */} - + Manage your Firefox Account diff --git a/assets/src/components/display/Hub.js b/assets/src/components/display/Hub.js index 119d5012..392fea59 100644 --- a/assets/src/components/display/Hub.js +++ b/assets/src/components/display/Hub.js @@ -8,7 +8,7 @@ import { Spinner } from "../common/Spinner"; import { IconDrive, IconUsers, IconExternal } from "../common/icons"; import { CLUSTER_DOMAIN } from "../utils/app-config"; import { formatNumber, formatMegabytes } from "../utils/formatNumber"; -import { READY } from "../utils/hub-constants"; +import { STATUS_READY, STATUS_CREATING, STATUS_UPDATING } from "../utils/hub-constants"; export function Hub({ tier, name, status, subdomain, currentCcu, currentStorageMb, hubId }) { const ccu = `${formatNumber(currentCcu)}`; @@ -23,7 +23,7 @@ export function Hub({ tier, name, status, subdomain, currentCcu, currentStorageM {name}
- {status === READY ? ( + {status === STATUS_READY ? ( <>
@@ -49,7 +49,8 @@ export function Hub({ tier, name, status, subdomain, currentCcu, currentStorageM
- Building your new hub... + {status === STATUS_CREATING ? "Building your new hub..." : ""} + {status === STATUS_UPDATING ? "Updating your hub..." : ""}
diff --git a/assets/src/components/display/HubForm.js b/assets/src/components/display/HubForm.js index d64dab56..37da61d1 100644 --- a/assets/src/components/display/HubForm.js +++ b/assets/src/components/display/HubForm.js @@ -1,11 +1,13 @@ -import React, { useState } from "react"; +import React, { useState, useRef } from "react"; import PropTypes from "prop-types"; import "./HubForm.css"; import { CLUSTER_DOMAIN } from "../utils/app-config"; import { LinkButton } from "../common/LinkButton"; -import { IconDrive, IconUsers } from "../common/icons"; +import { IconDrive, IconUsers, IconValid, IconInvalid } from "../common/icons"; import { formatMegabytes } from "../utils/formatNumber"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; function HubNickname({ hub, setHub }) { const [nameValidity, setNameValidity] = useState({ valid: true }); @@ -37,20 +39,98 @@ HubNickname.propTypes = { setHub: PropTypes.func, }; +function HubWebAddress({ hub, setHub }) { + const [subdomainValidity, setSubdomainValidity] = useState({ valid: true }); + + let validationMessage = ""; + if (hub.subdomain.length < 3) { + validationMessage = "Must be at least 3 characters"; + } else if (hub.subdomain.startsWith("-") || hub.subdomain.endsWith("-")) { + validationMessage = "Cannot start or end with a hyphen (-)"; + } else if (/[^a-zA-Z0-9-]+/.test(hub.subdomain)) { + validationMessage = "Only supports letters (a to z), digits (0 to 9), and hyphens (-)"; + } + + return ( +
+
+ Web Address (URL) + {subdomainValidity.valid ? ( + + Supports letters (a to z), digits (0 to 9), and hyphens (-) + + ) : ( + {validationMessage} + )} +
+
+ { + setSubdomainValidity(e.target.validity); + setHub({ ...hub, subdomain: e.target.value }); + }} + /> + {subdomainValidity.valid ? : } + + {hub.subdomain.toLowerCase()}.{CLUSTER_DOMAIN} + +
+
+ ); +} +HubWebAddress.propTypes = { + hub: PropTypes.object, + setHub: PropTypes.func, +}; + export function HubForm({ hub, setHub, isSubmitting, onSubmit }) { - const onFormSubmit = (e) => { - e.preventDefault(); - onSubmit(hub); - }; + const [isValid, setIsValid] = useState(false); + const formRef = useRef(); const tierChoices = [ { tier: "free", disabled: true, ccuLimit: 5, storageLimitMb: 250 }, { tier: "mvp", disabled: false, ccuLimit: null, storageLimitMb: null }, ]; + const toastConfig = { + position: "top-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + theme: "colored", + }; + + const onFormSubmit = (e) => { + e.preventDefault(); + onSubmit(hub).then((resp) => { + const errorMessage = "There was an error updating your hub"; + const successMessage = "Hub has been updated"; + + resp.error ? toast.error(errorMessage, toastConfig) : toast.success(successMessage, toastConfig); + }); + }; + + const submitEnabled = !isSubmitting && isValid; + return (
-
+ { + if (formRef.current) { + setIsValid(formRef.current.checkValidity()); + } + }} + onSubmit={onFormSubmit} + >
@@ -85,27 +165,13 @@ export function HubForm({ hub, setHub, isSubmitting, onSubmit }) { ))}
-
-
- Web Address (URL) - - Supports letters (a to z), digits (0 to 9), and hyphens (-) - -
-
- setHub({ ...hub, subdomain: e.target.value })} /> -   - - {hub.subdomain}.{CLUSTER_DOMAIN} - -
-
+
-
@@ -120,6 +186,7 @@ export function HubForm({ hub, setHub, isSubmitting, onSubmit }) { Capacity -
+
); } diff --git a/assets/src/components/display/Landing.js b/assets/src/components/display/Landing.js index c86d6140..e5e3310a 100644 --- a/assets/src/components/display/Landing.js +++ b/assets/src/components/display/Landing.js @@ -1,14 +1,14 @@ import React from "react"; import "./Landing.css"; +import { AUTH_SERVER } from "../utils/app-config"; import { LinkButton } from "../common/LinkButton"; import { Avatar } from "../common/Avatar"; import logoWhite from "../../images/logo-white.svg"; export function Landing() { const client = location.origin + location.pathname.replace(/\/$/, ""); - // TODO Use the CLUSTER_DOMAIN app config value here, assuming the auth server on the dev cluster is functional. - const loginUrl = `https://auth.myhubs.net/login?idp=fxa&client=${client}`; + const loginUrl = `https://${AUTH_SERVER}/login?idp=fxa&client=${client}`; return (
@@ -26,9 +26,8 @@ export function Landing() {
- {/* TODO Get the proper links here */} - Privacy policy - Terms and Conditions + Privacy policy + Terms and Conditions
diff --git a/assets/src/components/hooks/hubs.js b/assets/src/components/hooks/hubs.js index 824cf898..87c87847 100644 --- a/assets/src/components/hooks/hubs.js +++ b/assets/src/components/hooks/hubs.js @@ -38,9 +38,11 @@ export function useHub(hubId) { const [submitHub, { isLoading: isSubmitting }] = useUpdateHubMutation(); - const updateHub = async (hub) => { - await submitHub(hub); - dispatch(setHubEntity(hub)); + const updateHub = (hub) => { + return submitHub(hub).then((resp) => { + if (!resp.error) dispatch(setHubEntity(hub)); + return resp; + }); }; const isReady = isSuccess || currentHub; diff --git a/assets/src/components/store/account.js b/assets/src/components/store/account.js index 6bb66aba..67e27772 100644 --- a/assets/src/components/store/account.js +++ b/assets/src/components/store/account.js @@ -7,6 +7,7 @@ export const accountSlice = createSlice({ isLoggedIn: false, isForbidden: false, hasHubs: false, + hasCreatingHubs: false, profilePicture: "", displayName: "", email: "", @@ -20,6 +21,7 @@ export const accountSlice = createSlice({ state.displayName = action.payload.displayName; state.email = action.payload.email; state.isForbidden = action.payload.isForbidden; + state.hasCreatingHubs = action.payload.hasCreatingHubs; }, logOut(state) { state.isLoggedIn = false; @@ -28,6 +30,7 @@ export const accountSlice = createSlice({ state.profilePicture = ""; state.displayName = ""; state.email = ""; + state.hasCreatingHubs = false; }, }, }); diff --git a/assets/src/components/utils/app-config.js b/assets/src/components/utils/app-config.js index 98f4c090..9a59791d 100644 --- a/assets/src/components/utils/app-config.js +++ b/assets/src/components/utils/app-config.js @@ -1,3 +1,3 @@ window.APP_CONFIG = window.APP_CONFIG || {}; -export const { CLUSTER_DOMAIN } = window.APP_CONFIG; +export const { CLUSTER_DOMAIN, AUTH_SERVER, FXA_SERVER } = window.APP_CONFIG; diff --git a/assets/src/components/utils/hub-constants.js b/assets/src/components/utils/hub-constants.js index 7301ca23..d2fed04b 100644 --- a/assets/src/components/utils/hub-constants.js +++ b/assets/src/components/utils/hub-constants.js @@ -1,2 +1,3 @@ -export const READY = "ready"; -export const CREATING = "creating"; +export const STATUS_READY = "ready"; +export const STATUS_CREATING = "creating"; +export const STATUS_UPDATING = "updating"; diff --git a/assets/src/css/app.css b/assets/src/css/app.css index 642c0e35..0172de44 100644 --- a/assets/src/css/app.css +++ b/assets/src/css/app.css @@ -40,7 +40,8 @@ a { h1 { text-align: center; } -button { + +button.primary { min-width: 150px; height: 45px; margin: 0; @@ -56,8 +57,6 @@ button { line-height: 0; text-transform: none; letter-spacing: normal; -} -button.primary { color: white; background-color: #0d73a6; border-color: #0d73a6; diff --git a/assets/test/components/display/HubForm.test.js b/assets/test/components/display/HubForm.test.js index df5062b8..0d12a7f9 100644 --- a/assets/test/components/display/HubForm.test.js +++ b/assets/test/components/display/HubForm.test.js @@ -4,7 +4,7 @@ import { render } from "../../helpers/setup"; import { HubForm } from "../../../src/components/display/HubForm"; test("Hub form free tier is disabled", async () => { - const hub = { tier: "mvp", ccuLimit: 10, storageLimitMb: 10 }; + const hub = { subdomain: "test", tier: "mvp", ccuLimit: 10, storageLimitMb: 10 }; const { findByRole } = render(); @@ -13,7 +13,7 @@ test("Hub form free tier is disabled", async () => { }); test("Hub form mvp tier is enabled", async () => { - const hub = { tier: "mvp", ccuLimit: 10, storageLimitMb: 10 }; + const hub = { subdomain: "test", tier: "mvp", ccuLimit: 10, storageLimitMb: 10 }; const { findByRole } = render(); diff --git a/client/components/shared/Button/Button.module.scss b/client/components/shared/Button/Button.module.scss index be1c5bbc..769b5aa0 100644 --- a/client/components/shared/Button/Button.module.scss +++ b/client/components/shared/Button/Button.module.scss @@ -29,25 +29,25 @@ -------------------------------*/ .button_primary_solid { @include rect_button_base(); - background-color: $interaction-primary; - border: solid 2px $interaction-primary; - color: $text-reverse; + background-color: $color-interaction-primary; + border: solid 2px $color-interaction-primary; + color: $color-text-reverse; &:hover:enabled { - background-color: $interaction-primary-hover; - border: solid 2px $interaction-primary-hover; + background-color: $color-interaction-primary-hover; + border: solid 2px $color-interaction-primary-hover; } &_active, &:focus { - border: solid 2px $interaction-primary-active; - background-color: $interaction-primary-active; + border: solid 2px $color-interaction-primary-active; + background-color: $color-interaction-primary-active; } &:disabled, &[disabled] { - background-color: $interaction-primary-disabled; - border: solid 2px $interaction-primary-disabled; + background-color: $color-interaction-primary-disabled; + border: solid 2px $color-interaction-primary-disabled; } } @@ -57,28 +57,27 @@ .button_primary_outline { @include rect_button_base(); background-color: transparent; - border: solid 2px $interaction-primary; - color: $interaction-primary; + border: solid 2px $color-interaction-primary; + color: $color-interaction-primary; &:hover:enabled { - background-color: $interaction-primary-alt-hover; - border: solid 2px $interaction-primary-hover; - color: $interaction-primary-hover; - + background-color: $color-interaction-primary-alt-hover; + border: solid 2px $color-interaction-primary-hover; + color: $color-interaction-primary-hover; } &_active, &:focus { - background-color: $interaction-primary-alt-active; - border: solid 2px $interaction-primary-active; - color: $interaction-primary-active; + background-color: $color-interaction-primary-alt-active; + border: solid 2px $color-interaction-primary-active; + color: $color-interaction-primary-active; } &:disabled, &[disabled] { background-color: transparent; - border: solid 2px $interaction-primary-alt-disabled; - color: $text-subtitle; + border: solid 2px $color-interaction-primary-alt-disabled; + color: $color-text-subtitle; } } @@ -89,26 +88,26 @@ @include rect_button_base(); background-color: transparent; border: 0; - color: $interaction-primary; + color: $color-interaction-primary; &:hover:enabled { - background-color: $interaction-primary-alt-hover; - border: solid 2px $interaction-primary-alt-hover; - color: $interaction-primary-hover; + background-color: $color-interaction-primary-alt-hover; + border: solid 2px $color-interaction-primary-alt-hover; + color: $color-interaction-primary-hover; } &_active, &:focus { - background-color: $interaction-primary-alt-active; - border: solid 2px$interaction-primary-alt-active; - color: $interaction-primary-active; + background-color: $color-interaction-primary-alt-active; + border: solid 2px$color-interaction-primary-alt-active; + color: $color-interaction-primary-active; } &:disabled, &[disabled] { background-color: transparent; - border: solid 2px $interaction-primary-alt-disabled; - color: $text-subtitle; + border: solid 2px $color-interaction-primary-alt-disabled; + color: $color-text-subtitle; } } @@ -123,25 +122,25 @@ -------------------------------*/ .button_secondary_solid { @include rect_button_base(); - background-color: $interaction-secondary; - border: solid 2px $interaction-secondary; - color: $text-subtitle; + background-color: $color-interaction-secondary; + border: solid 2px $color-interaction-secondary; + color: $color-text-subtitle; &:hover:enabled { - background-color: $interaction-secondary-hover; - border: solid 2px $interaction-secondary-hover; + background-color: $color-interaction-secondary-hover; + border: solid 2px $color-interaction-secondary-hover; } &_active, &:focus { - border: solid 2px $interaction-secondary-active; - background-color: $interaction-secondary-active; + border: solid 2px $color-interaction-secondary-active; + background-color: $color-interaction-secondary-active; } &:disabled, &[disabled] { - background-color: $interaction-secondary-disabled; - border: solid 2px $interaction-secondary-disabled; + background-color: $color-interaction-secondary-disabled; + border: solid 2px $color-interaction-secondary-disabled; } } @@ -151,24 +150,24 @@ .button_secondary_outline { @include rect_button_base(); background-color: transparent; - border: solid 2px $interaction-secondary; - color: $text-subtitle; + border: solid 2px $color-interaction-secondary; + color: $color-text-subtitle; &:hover:enabled { - background-color: $interaction-secondary-alt-hover; - border: solid 2px $interaction-secondary-hover; + background-color: $color-interaction-secondary-alt-hover; + border: solid 2px $color-interaction-secondary-hover; } &_active, &:focus { - background-color: $interaction-secondary-alt-active; - border: solid 2px $interaction-secondary-active; + background-color: $color-interaction-secondary-alt-active; + border: solid 2px $color-interaction-secondary-active; } &:disabled, &[disabled] { background-color: transparent; - border: solid 2px $interaction-secondary-alt-disabled; + border: solid 2px $color-interaction-secondary-alt-disabled; } } @@ -179,23 +178,23 @@ @include rect_button_base(); background-color: transparent; border: 0; - color: $text-subtitle; + color: $color-text-subtitle; &:hover:enabled { - background-color: $interaction-secondary-alt-hover; - border: solid 2px $interaction-secondary-alt-hover; + background-color: $color-interaction-secondary-alt-hover; + border: solid 2px $color-interaction-secondary-alt-hover; } &_active, &:focus { - background-color: $interaction-secondary-alt-active; - border: solid 2px$interaction-secondary-alt-active; + background-color: $color-interaction-secondary-alt-active; + border: solid 2px$color-interaction-secondary-alt-active; } &:disabled, &[disabled] { background-color: transparent; - border: solid 2px $interaction-secondary-alt-disabled; + border: solid 2px $color-interaction-secondary-alt-disabled; } } diff --git a/client/components/shared/Button/Button.tsx b/client/components/shared/Button/Button.tsx index 5b46c1ae..cc0bc604 100644 --- a/client/components/shared/Button/Button.tsx +++ b/client/components/shared/Button/Button.tsx @@ -31,63 +31,15 @@ const Button = ({ iconPlacedRight = false, classProp = '', }: ButtonPropsT) => { - const [categoryClass, setCategoryClass] = useState(); - const [categoryActiveClass, setCategoryActiveClass] = useState(); - - useEffect(() => { - setButtonClass(category); - }, [category]); - - /** - * Get Button Category Class - * @param category : string - */ - const setButtonClass = (category: string) => { - const { - PRIMARY_SOLID, - PRIMARY_OUTLINE, - PRIMARY_CLEAR, - SECONDARY_SOLID, - SECONDARY_OUTLINE, - SECONDARY_CLEAR, - } = ButtonCategoriesE; - - switch (category) { - // PRIMARY - case PRIMARY_SOLID: - setCategoryClass(styles.button_primary_solid); - setCategoryActiveClass(styles.button_primary_solid_active); - break; - case PRIMARY_OUTLINE: - setCategoryClass(styles.button_primary_outline); - setCategoryActiveClass(styles.button_primary_outline_active); - break; - case PRIMARY_CLEAR: - setCategoryClass(styles.button_primary_clear); - setCategoryActiveClass(styles.button_primary_clear_active); - break; - - // SECONDARY - case SECONDARY_SOLID: - setCategoryClass(styles.button_secondary_solid); - setCategoryActiveClass(styles.button_secondary_solid_active); - break; - case SECONDARY_OUTLINE: - setCategoryClass(styles.button_secondary_outline); - setCategoryActiveClass(styles.button_secondary_outline_active); - break; - case SECONDARY_CLEAR: - setCategoryClass(styles.button_secondary_clear); - setCategoryActiveClass(styles.button_secondary_clear_active); - break; - } - }; - return (