Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-04-17 18:03:26 +02:00
parent 11770b4058
commit 0e701ec6e9
5 changed files with 61 additions and 104 deletions

View File

@@ -12,14 +12,23 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import { formatError } from "@probo/helpers";
import { usePageTitle } from "@probo/hooks";
import { useTranslate } from "@probo/i18n";
import { Button, useToast } from "@probo/ui";
import { useCallback, useState } from "react";
import { type PreloadedQuery, useMutation, usePreloadedQuery } from "react-relay";
import { graphql } from "relay-runtime";
import { formatError } from "@probo/helpers";
import { usePageTitle } from "@probo/hooks";
import { useTranslate } from "@probo/i18n";
import {
Button,
IconArrowsClockwise,
IconEnvelope,
IconLockOpen,
IconUser,
IconUserCircle,
useToast,
} from "@probo/ui";
import type { ConsentPageMutation } from "#/__generated__/iam/ConsentPageMutation.graphql";
import type { ConsentPageQuery } from "#/__generated__/iam/ConsentPageQuery.graphql";
@@ -53,80 +62,12 @@ const scopeLabels: Record<string, string> = {
offline_access: "Stay signed in and access your data while you're away",
};
function ScopeIcon({ scope }: { scope: string }) {
switch (scope) {
case "openid":
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-[18px] h-[18px] shrink-0 text-txt-tertiary"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z"
/>
</svg>
);
case "email":
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-[18px] h-[18px] shrink-0 text-txt-tertiary"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"
/>
</svg>
);
case "profile":
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-[18px] h-[18px] shrink-0 text-txt-tertiary"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
/>
</svg>
);
case "offline_access":
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-[18px] h-[18px] shrink-0 text-txt-tertiary"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182M21.015 4.356v4.992"
/>
</svg>
);
default:
return null;
}
}
const scopeIcons: Record<string, React.ReactNode> = {
openid: <IconUser size={18} className="shrink-0 text-txt-tertiary" />,
email: <IconEnvelope size={18} className="shrink-0 text-txt-tertiary" />,
profile: <IconUserCircle size={18} className="shrink-0 text-txt-tertiary" />,
offline_access: <IconArrowsClockwise size={18} className="shrink-0 text-txt-tertiary" />,
};
export default function ConsentPage(props: {
queryRef: PreloadedQuery<ConsentPageQuery>;
@@ -236,20 +177,7 @@ export default function ConsentPage(props: {
<div className="space-y-2 text-center">
<div className="flex justify-center mb-4">
<div className="w-12 h-12 rounded-full flex items-center justify-center bg-level-1">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.5 10.5V6.75a4.5 4.5 0 1 1 9 0v3.75M3.75 21.75h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H3.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z"
/>
</svg>
<IconLockOpen size={24} />
</div>
</div>
<h1 className="text-2xl font-bold">
@@ -273,7 +201,7 @@ export default function ConsentPage(props: {
key={scope}
className="flex items-center gap-2.5 px-3 py-2.5 text-sm text-txt-secondary border border-border-mid rounded-lg"
>
<ScopeIcon scope={scope} />
{scopeIcons[scope]}
{__(label)}
</li>
);

View File

@@ -22,11 +22,10 @@ import type { ConsentPageQuery } from "#/__generated__/iam/ConsentPageQuery.grap
import ConsentPage, { consentPageQuery } from "./ConsentPage";
function ConsentPageQueryLoader() {
const [searchParams] = useSearchParams();
const consentId = searchParams.get("consent_id") ?? "";
const [queryRef, loadQuery]
= useQueryLoader<ConsentPageQuery>(consentPageQuery);
const [searchParams] = useSearchParams();
const consentId = searchParams.get("consent_id") ?? "";
useEffect(() => {
loadQuery({ consentId });
@@ -69,8 +68,11 @@ function ConsentErrorFallback() {
}
export default function ConsentPageLoader() {
const [searchParams] = useSearchParams();
const consentId = searchParams.get("consent_id") ?? "";
return (
<ConsentErrorBoundary fallback={<ConsentErrorFallback />}>
<ConsentErrorBoundary key={consentId} fallback={<ConsentErrorFallback />}>
<ConsentPageQueryLoader />
</ConsentErrorBoundary>
);

View File

@@ -44,6 +44,25 @@ type TestEnv struct {
cmd *exec.Cmd
done chan error
outputBuf *bytes.Buffer
outputWriter *switchableWriter
}
type switchableWriter struct {
mu sync.Mutex
w io.Writer
}
func (s *switchableWriter) Write(p []byte) (int, error) {
s.mu.Lock()
w := s.w
s.mu.Unlock()
return w.Write(p)
}
func (s *switchableWriter) switchTo(w io.Writer) {
s.mu.Lock()
s.w = w
s.mu.Unlock()
}
func Setup() {
@@ -93,8 +112,10 @@ func Setup() {
} else {
var buf bytes.Buffer
testEnv.outputBuf = &buf
cmd.Stdout = &buf
cmd.Stderr = &buf
sw := &switchableWriter{w: &buf}
testEnv.outputWriter = sw
cmd.Stdout = sw
cmd.Stderr = sw
}
testEnv.cmd = cmd
@@ -126,8 +147,7 @@ func Setup() {
}
if !verbose {
cmd.Stdout = io.Discard
cmd.Stderr = io.Discard
testEnv.outputWriter.switchTo(io.Discard)
}
})
}

View File

@@ -104,5 +104,12 @@ export { IconBrandFacebook } from "./IconBrandFacebook";
export { IconBrandLinkedin } from "./IconBrandLinkedin";
export { IconBrandX } from "./IconBrandX";
export { IconGlobe } from "./IconGlobe";
export {
ArrowsClockwise as IconArrowsClockwise,
Envelope as IconEnvelope,
LockOpen as IconLockOpen,
User as IconUser,
UserCircle as IconUserCircle,
} from "@phosphor-icons/react";
export { SocialIcon } from "./SocialIcon";
export type { SocialIconProps } from "./SocialIcon";

View File

@@ -1,7 +1,7 @@
extend type Mutation {
authorizeDevice(
input: AuthorizeDeviceInput!
): AuthorizeDevicePayload @session(required: PRESENT)
authorizeDevice(
input: AuthorizeDeviceInput!
): AuthorizeDevicePayload @session(required: PRESENT)
approveConsent(
input: ApproveConsentInput!