Refactor hostname to become baseurl

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-10-30 19:41:15 +01:00
parent 27a9858ec0
commit 896e6e0736
29 changed files with 657 additions and 153 deletions

View File

@@ -154,7 +154,7 @@ export function MainLayout() {
icon={IconBook}
to={`${prefix}/obligations`}
/>
<SidebarItem
<SidebarItem
label={__("Continual Improvements")}
icon={IconRotateCw}
to={`${prefix}/continual-improvements`}
@@ -192,15 +192,16 @@ export function MainLayout() {
function UserDropdown({ organizationId }: { organizationId: string }) {
const { __ } = useTranslate();
const { toast } = useToast();
const user = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, { organizationId }).viewer
.user;
const user = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, {
organizationId,
}).viewer.user;
const handleLogout: React.MouseEventHandler<HTMLAnchorElement> = async (
e
) => {
e.preventDefault();
fetch(buildEndpoint("/auth/logout"), {
fetch(buildEndpoint("/connect/logout"), {
method: "DELETE",
headers: {
"Content-Type": "application/json",
@@ -274,13 +275,19 @@ interface InvitationsResponse {
invitations: Invitation[];
}
function OrganizationSelectorWrapper({ organizationId }: { organizationId: string }) {
const data = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, { organizationId });
function OrganizationSelectorWrapper({
organizationId,
}: {
organizationId: string;
}) {
const data = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, {
organizationId,
});
return <OrganizationSelector currentOrganization={data.organization} />;
}
function OrganizationSelector({
currentOrganization
currentOrganization,
}: {
currentOrganization: MainLayoutQueryType["response"]["organization"];
}) {
@@ -297,32 +304,32 @@ function OrganizationSelector({
// Fetch organizations and invitations in parallel
const [orgsResponse, invitationsResponse] = await Promise.all([
fetch('/auth/organizations', { credentials: 'include' }),
fetch('/auth/invitations', { credentials: 'include' })
fetch("/connect/organizations", { credentials: "include" }),
fetch("/connect/invitations", { credentials: "include" }),
]);
if (!orgsResponse.ok) {
throw new Error('Failed to fetch organizations');
throw new Error("Failed to fetch organizations");
}
if (!invitationsResponse.ok) {
throw new Error('Failed to fetch invitations');
throw new Error("Failed to fetch invitations");
}
const orgsData: OrganizationsResponse = await orgsResponse.json();
const invitationsData: InvitationsResponse = await invitationsResponse.json();
const invitationsData: InvitationsResponse =
await invitationsResponse.json();
// Count pending invitations (those without acceptedAt)
const pendingCount = invitationsData.invitations.filter(
inv => !inv.acceptedAt
(inv) => !inv.acceptedAt
).length;
setOrganizations(orgsData.organizations);
setPendingInvitationsCount(pendingCount);
setError(null);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
console.error('Failed to fetch data:', err);
setError(err instanceof Error ? err.message : "Unknown error");
console.error("Failed to fetch data:", err);
} finally {
setIsLoading(false);
}
@@ -334,11 +341,7 @@ function OrganizationSelector({
if (error) {
return (
<div className="flex items-center gap-1">
<Button
className="-ml-3"
variant="tertiary"
disabled
>
<Button className="-ml-3" variant="tertiary" disabled>
{__("Error loading organizations")}
</Button>
</div>
@@ -355,7 +358,7 @@ function OrganizationSelector({
iconAfter={IconChevronGrabberVertical}
disabled={isLoading}
>
{isLoading ? __("Loading...") : (currentOrganization?.name || "")}
{isLoading ? __("Loading...") : currentOrganization?.name || ""}
</Button>
}
>
@@ -370,7 +373,8 @@ function OrganizationSelector({
</div>
) : (
organizations.map((organization) => {
const isAuthenticated = organization.authStatus === "authenticated";
const isAuthenticated =
organization.authStatus === "authenticated";
const isExpired = organization.authStatus === "expired";
const needsAuth = organization.authStatus === "unauthenticated";
@@ -378,16 +382,16 @@ function OrganizationSelector({
? `/organizations/${organization.id}`
: organization.loginUrl;
const isSAMLUrl = targetUrl.includes('/auth/saml/');
const isSAMLUrl = targetUrl.includes("/connect/saml/");
return (
<DropdownItem
asChild
key={organization.id}
>
<DropdownItem asChild key={organization.id}>
{isSAMLUrl ? (
<a href={targetUrl} className="flex items-center gap-2">
<Avatar name={organization.name} src={organization.logoUrl} />
<Avatar
name={organization.name}
src={organization.logoUrl}
/>
<span className="flex-1">{organization.name}</span>
{isAuthenticated && (
<IconCheckmark1 size={16} className="text-green-600" />
@@ -401,7 +405,10 @@ function OrganizationSelector({
</a>
) : (
<Link to={targetUrl} className="flex items-center gap-2">
<Avatar name={organization.name} src={organization.logoUrl} />
<Avatar
name={organization.name}
src={organization.logoUrl}
/>
<span className="flex-1">{organization.name}</span>
{isAuthenticated && (
<IconCheckmark1 size={16} className="text-green-600" />

View File

@@ -51,7 +51,7 @@ export default function OrganizationsPage() {
useEffect(() => {
const fetchOrganizations = async () => {
try {
const response = await fetch('/auth/organizations', {
const response = await fetch('/connect/organizations', {
credentials: 'include',
});
@@ -75,7 +75,7 @@ export default function OrganizationsPage() {
useEffect(() => {
const fetchInvitations = async () => {
try {
const response = await fetch('/auth/invitations', {
const response = await fetch('/connect/invitations', {
credentials: 'include',
});
@@ -98,7 +98,7 @@ export default function OrganizationsPage() {
const handleAcceptInvitation = async (invitationId: string, organizationId: string) => {
setIsAccepting(true);
try {
const response = await fetch('/auth/invitations/accept', {
const response = await fetch('/connect/invitations/accept', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -281,7 +281,7 @@ function OrganizationCard({ organization }: OrganizationCardProps) {
};
// Check if the URL is a backend SAML endpoint
const isSAMLUrl = targetUrl.includes('/auth/saml/');
const isSAMLUrl = targetUrl.includes('/connect/saml/');
return (
<Card padded className="w-full">

View File

@@ -111,7 +111,7 @@ export default function ConfirmEmailPage() {
<p className="text-green-600 dark:text-green-400">
{__("Your email has been confirmed successfully!")}
</p>
<Button onClick={() => navigate("/authentication/login")} className="w-full">
<Button onClick={() => navigate("/auth/login")} className="w-full">
{__("Proceed to Login")}
</Button>
</div>
@@ -141,7 +141,7 @@ export default function ConfirmEmailPage() {
{!isConfirmed && (
<p className="text-sm text-txt-tertiary">
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Back to Login")}

View File

@@ -23,7 +23,7 @@ export default function ForgotPasswordPage() {
const onSubmit = handleSubmit(async (data) => {
const response = await fetch(
buildEndpoint("/auth/forget-password"),
buildEndpoint("/connect/forget-password"),
{
method: "POST",
headers: {
@@ -81,7 +81,7 @@ export default function ForgotPasswordPage() {
<p className="text-sm text-txt-tertiary">
{__("Remember your password?")}{" "}
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Back to login")}
@@ -124,7 +124,7 @@ export default function ForgotPasswordPage() {
<p className="text-sm text-txt-tertiary">
{__("Remember your password?")}{" "}
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Back to login")}

View File

@@ -33,7 +33,7 @@ export default function LoginPage() {
setIsLoading(true);
try {
const res = await fetch(buildEndpoint("/auth/login"), {
const res = await fetch(buildEndpoint("/connect/login"), {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -68,7 +68,7 @@ export default function LoginPage() {
setIsChecking(true);
try {
const res = await fetch(buildEndpoint("/auth/check-sso"), {
const res = await fetch(buildEndpoint("/connect/check-sso"), {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -85,7 +85,7 @@ export default function LoginPage() {
if (data.ssoAvailable && data.samlConfigId) {
window.location.href = buildEndpoint(
`/auth/saml/login/${data.samlConfigId}`
`/connect/saml/login/${data.samlConfigId}`
);
} else {
throw new Error(__("SSO not available for this email domain"));
@@ -146,7 +146,7 @@ export default function LoginPage() {
<div className="text-center mt-6 text-sm text-txt-secondary">
{__("Don't have an account ?")}{" "}
<Link to="/authentication/register" className="underline hover:text-txt-primary">
<Link to="/auth/register" className="underline hover:text-txt-primary">
{__("Register")}
</Link>
</div>
@@ -154,7 +154,7 @@ export default function LoginPage() {
<div className="text-center text-sm text-txt-secondary">
{__("Forgot password?")}{" "}
<Link
to="/authentication/forgot-password"
to="/auth/forgot-password"
className="underline hover:text-txt-primary"
>
{__("Reset password")}
@@ -206,7 +206,7 @@ export default function LoginPage() {
<div className="text-center mt-6 text-sm text-txt-secondary">
{__("Don't have an account ?")}{" "}
<Link to="/authentication/register" className="underline hover:text-txt-primary">
<Link to="/auth/register" className="underline hover:text-txt-primary">
{__("Register")}
</Link>
</div>
@@ -214,7 +214,7 @@ export default function LoginPage() {
<div className="text-center text-sm text-txt-secondary">
{__("Forgot password?")}{" "}
<Link
to="/authentication/forgot-password"
to="/auth/forgot-password"
className="underline hover:text-txt-primary"
>
{__("Reset password")}
@@ -257,7 +257,7 @@ export default function LoginPage() {
<div className="text-center mt-6 text-sm text-txt-secondary">
{__("Don't have an account ?")}{" "}
<Link to="/authentication/register" className="underline hover:text-txt-primary">
<Link to="/auth/register" className="underline hover:text-txt-primary">
{__("Register")}
</Link>
</div>

View File

@@ -26,7 +26,7 @@ export default function RegisterPage() {
const onSubmit = handleSubmit(async (data) => {
const response = await fetch(
buildEndpoint("/auth/register"),
buildEndpoint("/connect/register"),
{
method: "POST",
headers: {
@@ -106,7 +106,7 @@ export default function RegisterPage() {
<p className="text-sm text-txt-tertiary">
{__("Already have an account?")}{" "}
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Log in here")}

View File

@@ -44,7 +44,7 @@ export default function ResetPasswordPage() {
}
const response = await fetch(
buildEndpoint("/auth/reset-password"),
buildEndpoint("/connect/reset-password"),
{
method: "POST",
headers: {
@@ -74,7 +74,7 @@ export default function ResetPasswordPage() {
description: __("Password reset successfully"),
variant: "success",
});
navigate("/authentication/login", { replace: true });
navigate("/auth/login", { replace: true });
});
usePageTitle(__("Reset password"));
@@ -118,7 +118,7 @@ export default function ResetPasswordPage() {
<p className="text-sm text-txt-tertiary">
{__("Remember your password?")}{" "}
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Log in here")}

View File

@@ -51,7 +51,7 @@ export default function SignupFromInvitationPage() {
}
const response = await fetch(
buildEndpoint("/auth/signup-from-invitation"),
buildEndpoint("/connect/signup-from-invitation"),
{
method: "POST",
headers: {
@@ -125,7 +125,7 @@ export default function SignupFromInvitationPage() {
<p className="text-sm text-txt-tertiary">
{__("Already have an account?")}{" "}
<Link
to="/authentication/login"
to="/auth/login"
className="underline text-txt-primary hover:text-txt-secondary"
>
{__("Log in here")}

View File

@@ -50,7 +50,7 @@ function ErrorBoundary({ error: propsError }: { error?: string }) {
const error = useRouteError() ?? propsError;
if (error instanceof UnAuthenticatedError) {
return <Navigate to="/authentication/login" />;
return <Navigate to="/auth/login" />;
}
return <PageError error={error?.toString()} />;
@@ -58,7 +58,7 @@ function ErrorBoundary({ error: propsError }: { error?: string }) {
const routes = [
{
path: "/authentication",
path: "/auth",
Component: AuthLayout,
children: [
{