Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue #3247] logged in header #3458

Merged
merged 16 commits into from
Jan 9, 2025
Merged
21 changes: 0 additions & 21 deletions frontend/src/app/[locale]/dev/feature-flags/FeatureFlagsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,18 @@
"use client";

import { useFeatureFlags } from "src/hooks/useFeatureFlags";
import { useUser } from "src/services/auth/useUser";

import React from "react";
import { Button, Table } from "@trussworks/react-uswds";

import Loading from "src/components/Loading";

/**
* View for managing feature flags
*/
export default function FeatureFlagsTable() {
const { setFeatureFlag, featureFlags } = useFeatureFlags();
const { user, isLoading, error } = useUser();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with a working header we no longer need these changes on the feature flag page as a proof of concept


if (isLoading) {
return <Loading />;
}

if (error) {
// there's no error page within this tree, should we make a top level error?
return (
<>
<h1>Error</h1>
{error.message}
</>
);
}

return (
<>
<h2>
{user?.token ? `Logged in with token: ${user.token}` : "Not logged in"}
</h2>
<Table>
<thead>
<tr>
Expand Down
7 changes: 0 additions & 7 deletions frontend/src/app/[locale]/dev/layout.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/src/app/[locale]/process/ProcessNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const ProcessNext = () => {
>
<IconListIcon>
<USWDSIcon
className="usa-icon text-base"
className="text-base"
name="check_circle_outline"
/>
</IconListIcon>
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/app/api/auth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const createSessionAndSetStatus = async (
};

/*
currently it looks like the API will send us a request with the params below, and we will be responsible
for directing the user accordingly. For now, we'll send them to generic success and error pages with cookie set on success
For now, we'll send them to generic success and error pages with cookie set on success

message: str ("success" or "error")
token: str | None
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/app/api/auth/logout/route.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { deleteSession, getSession } from "src/services/auth/session";
import { getSession } from "src/services/auth/session";
import { deleteSession } from "src/services/auth/sessionUtils";
import { postLogout } from "src/services/fetch/fetchers/userFetcher";

export async function POST() {
try {
// logout on API via /v1/users/token/logout
const session = await getSession();
if (!session || !session.token) {
throw new Error("No active session to logout");
}
// logout on API via /v1/users/token/logout
const response = await postLogout(session.token);
if (!response) {
throw new Error("No logout response from API");
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/app/api/auth/session/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { getSession } from "src/services/auth/session";

import { NextResponse } from "next/server";

export const revalidate = 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't want to cache anything here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this has an effect since a fetch isn't called in the session creation AFAICT. Next says it doesn't cache GET routes if cookies are used. force-dynamic might be the way to make sure that the GET request is re-rendered every time, but can't hurt to tell it to revalidate as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also wondering if this is better as a POST method.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I had this in there just for safety, but I just verified and the 'no-store' on the fetch call is doing all the work. We can safely pull this out. As for POST vs GET, I'm not sure I see a reason to make a change, but we can discuss


export async function GET() {
const currentSession = await getSession();
if (currentSession) {
return NextResponse.json({
token: currentSession.token,
});
return NextResponse.json(currentSession);
} else {
return NextResponse.json({ token: "" });
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type SocialLinkProps = {
const SocialLink = ({ href, name, icon }: SocialLinkProps) => (
<a className="usa-social-link" href={href} title={name} target="_blank">
<USWDSIcon
className="usa-icon usa-social-link__icon"
className="usa-social-link__icon"
height="40px"
name={icon}
aria-label={name}
Expand Down
39 changes: 3 additions & 36 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
Header as USWDSHeader,
} from "@trussworks/react-uswds";

import { USWDSIcon } from "src/components/USWDSIcon";
import { UserControl } from "./user/UserControl";

type PrimaryLink = {
text?: string;
Expand Down Expand Up @@ -120,36 +120,6 @@ const NavLinks = ({
);
};

const LoginLink = ({ navLoginLinkText }: { navLoginLinkText: string }) => {
const [authLoginUrl, setAuthLoginUrl] = useState<string | null>(null);

useEffect(() => {
async function fetchEnv() {
const res = await fetch("/api/env");
const data = (await res.json()) as { auth_login_url: string };
data.auth_login_url
? setAuthLoginUrl(data.auth_login_url)
: console.error("could not access auth_login_url");
}
fetchEnv().catch((error) => console.warn("error fetching api/env", error));
}, []);

return (
<a
{...(authLoginUrl ? { href: authLoginUrl } : "")}
key="login-link"
className="usa-nav__link text-primary font-sans-2xs display-flex text-normal"
>
<USWDSIcon
className="usa-icon margin-right-05 margin-left-neg-05"
name="login"
key="login-link-icon"
/>
{navLoginLinkText}
</a>
);
};

const Header = ({ logoPath, locale }: Props) => {
logoPath = "./img/grants-logo.svg";
const t = useTranslations("Header");
Expand All @@ -173,7 +143,6 @@ const Header = ({ logoPath, locale }: Props) => {

const { checkFeatureFlag } = useFeatureFlags();
const showLoginLink = checkFeatureFlag("authOn");

const language = locale && locale.match("/^es/") ? "spanish" : "english";

const handleMobileNavToggle = () => {
Expand Down Expand Up @@ -223,10 +192,8 @@ const Header = ({ logoPath, locale }: Props) => {
/>
</div>
{!!showLoginLink && (
<div className="usa-nav__primary margin-top-0 margin-bottom-1 desktop:margin-bottom-5px text-no-wrap desktop:order-last margin-left-auto">
<div className="usa-nav__primary-item border-0">
<LoginLink navLoginLinkText={t("nav_link_login")} />
</div>
<div className="usa-nav__primary margin-top-0 padding-bottom-05 text-no-wrap desktop:order-last margin-left-auto desktop:height-auto height-6">
<UserControl />
</div>
)}
<NavLinks
Expand Down
26 changes: 15 additions & 11 deletions frontend/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import UserProvider from "src/services/auth/UserProvider";

import { useTranslations } from "next-intl";
import { setRequestLocale } from "next-intl/server";

Expand All @@ -17,16 +19,18 @@ export default function Layout({ children, locale }: Props) {

return (
// Stick the footer to the bottom of the page
<div className="display-flex flex-column minh-viewport">
<a className="usa-skipnav z-top" href="#main-content">
{t("Layout.skip_to_main")}
</a>
<Header locale={locale} />
<main id="main-content" className="border-top-0">
{children}
</main>
<Footer />
<GrantsIdentifier />
</div>
<UserProvider>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could be more targeted here, but I don't see a need

<div className="display-flex flex-column minh-viewport">
<a className="usa-skipnav" href="#main-content">
{t("Layout.skip_to_main")}
</a>
<Header locale={locale} />
<main id="main-content" className="border-top-0">
{children}
</main>
<Footer />
<GrantsIdentifier />
</div>
</UserProvider>
);
}
6 changes: 4 additions & 2 deletions frontend/src/components/USWDSIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import clsx from "clsx";

import SpriteSVG from "public/img/uswds-sprite.svg";

interface IconProps {
name: string;
className: string;
className?: string;
height?: string;
}

Expand All @@ -12,7 +14,7 @@ const sprite_uri = SpriteSVG.src as string;
export function USWDSIcon(props: IconProps) {
return (
<svg
className={props.className}
className={clsx("usa-icon", props.className)}
Copy link
Collaborator Author

@doug-s-nava doug-s-nava Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since all usage of this component had this class added manually, figured we should add it to the shared implementation and make this component a bit more useful. Removal of "usa-icon" from other files is a result of this change

aria-hidden="true"
height={props.height}
role="img"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/content/IndexGoalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const IndexGoalContent = () => {
<span className="margin-right-5">{t("goal.cta")}</span>
<USWDSIcon
name="arrow_forward"
className="usa-icon usa-icon--size-4 text-middle margin-left-neg-4"
className="usa-icon--size-4 text-middle margin-left-neg-4"
aria-label="arrow-forward"
/>
</Button>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/content/ProcessAndResearchContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ProcessAndResearchContent = () => {
</span>
<USWDSIcon
name="arrow_forward"
className="usa-icon usa-icon--size-4 text-middle margin-left-neg-4"
className="usa-icon--size-4 text-middle margin-left-neg-4"
aria-label="arrow-forward"
/>
</Button>
Expand All @@ -47,7 +47,7 @@ const ProcessAndResearchContent = () => {
</span>
<USWDSIcon
name="arrow_forward"
className="usa-icon usa-icon--size-4 text-middle margin-left-neg-4"
className="usa-icon--size-4 text-middle margin-left-neg-4"
aria-label="arrow-forward"
/>
</Button>
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/components/opportunity/OpportunityCTA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ const OpportunityCTA = ({ id }: { id: number }) => {
>
<Button type="button" outline={true} className="margin-top-2">
<span>{t("button_content")}</span>
<USWDSIcon
name="launch"
className="usa-icon usa-icon--size-4 text-middle"
/>
<USWDSIcon name="launch" className="usa-icon--size-4 text-middle" />
</Button>
</a>
</>
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/components/opportunity/OpportunityDownload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ const OpportunityDownload = ({ nofoPath }: Props) => {
<div className="grid-row flex-justify">
<Button onClick={() => downloadNOFO(nofoPath)} type="button">
<span>{t("nofo_download")} </span>
<USWDSIcon
name={"file_download"}
className="usa-icon usa-icon--size-4"
/>
<USWDSIcon name={"file_download"} className="usa-icon--size-4" />
</Button>
<Link
className="flex-align-self-center"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const OpportunityStatusWidget = ({ opportunityData }: Props) => {
switch (status) {
case "archived":
return (
<div className="usa-tag bg-base-lighter text-ink border-radius-2 border-base-lightest width-100 radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

width-100 isn't a valid uswds class

<div className="usa-tag bg-base-lighter text-ink border-radius-2 border-base-lightest radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<p>
<strong>{t("archived")}</strong>
<span>{formatDate(archiveDate) || "--"}</span>
Expand All @@ -71,7 +71,7 @@ const OpportunityStatusWidget = ({ opportunityData }: Props) => {
);
case "closed":
return (
<div className="usa-tag bg-base-lighter text-ink border-radius-2 border-base-lightest width-100 radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<div className="usa-tag bg-base-lighter text-ink border-radius-2 border-base-lightest radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<p>
<strong>{t("closed")}</strong>
<span>{formatDate(closeDate) || "--"}</span>
Expand All @@ -81,7 +81,7 @@ const OpportunityStatusWidget = ({ opportunityData }: Props) => {
case "posted":
return (
<>
<div className="usa-tag bg-accent-warm-dark width-100 radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<div className="usa-tag bg-accent-warm-dark radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<p>
<strong>{t("closing")}</strong>
<span>{formatDate(closeDate) || "--"}</span>
Expand All @@ -96,7 +96,7 @@ const OpportunityStatusWidget = ({ opportunityData }: Props) => {
);
case "forecasted":
return (
<div className="usa-tag bg-base-dark border-radius-2 width-100 radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<div className="usa-tag bg-base-dark border-radius-2 radius-md margin-right-0 font-sans-sm text-center text-no-uppercase">
<p>
<strong>{t("forecasted")}</strong>
</p>
Expand Down
Loading