feat: add login button animation, add donation env var+button, ui tweaks, session checking in account links card
This commit is contained in:
parent
4c1a20407e
commit
152f96f0af
@ -2,9 +2,10 @@ import Link from "next/link"
|
|||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from "@/components/ui/card"
|
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from "@/components/ui/card"
|
||||||
import { auth, signIn } from "@/auth"
|
import { auth, signIn } from "@/auth"
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation"
|
||||||
import { SiAuthentik } from "react-icons/si"
|
import { SiAuthentik } from "react-icons/si"
|
||||||
import { UserPlus } from "lucide-react"
|
import { UserPlus } from "lucide-react"
|
||||||
|
import * as motion from "motion/react-client"
|
||||||
|
|
||||||
export default async function Login() {
|
export default async function Login() {
|
||||||
const session = await auth()
|
const session = await auth()
|
||||||
@ -27,22 +28,43 @@ export default async function Login() {
|
|||||||
await signIn("authentik", { redirectTo: "/account/dashboard" })
|
await signIn("authentik", { redirectTo: "/account/dashboard" })
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button type="submit" className="w-full">
|
<motion.div
|
||||||
<SiAuthentik />
|
initial={{ scale: 0.95 }}
|
||||||
Sign in with Authentik
|
animate={{ scale: 1 }}
|
||||||
</Button>
|
whileTap={{ scale: 0.95 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Button type="submit" className="w-full cursor-pointer">
|
||||||
|
<SiAuthentik />
|
||||||
|
Sign in with Authentik
|
||||||
|
</Button>
|
||||||
|
</motion.div>
|
||||||
{process.env.SIGNUP_ENABLED === "true" ? (
|
{process.env.SIGNUP_ENABLED === "true" ? (
|
||||||
<Link href="/account/signup">
|
<Link href="/account/signup">
|
||||||
<Button variant="outline" className="w-full">
|
<motion.div
|
||||||
<UserPlus />
|
initial={{ scale: 0.95 }}
|
||||||
Create an Account
|
animate={{ scale: 1 }}
|
||||||
</Button>
|
whileTap={{ scale: 0.95 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Button variant="outline" className="w-full cursor-pointer">
|
||||||
|
<UserPlus />
|
||||||
|
Create an Account
|
||||||
|
</Button>
|
||||||
|
</motion.div>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<Button variant="outline" className="w-full cursor-not-allowed" disabled>
|
<motion.div
|
||||||
<UserPlus />
|
initial={{ scale: 0.95 }}
|
||||||
Registration is Closed
|
animate={{ scale: 1 }}
|
||||||
</Button>
|
whileTap={{ scale: 0.95 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Button variant="outline" className="w-full cursor-not-allowed" disabled>
|
||||||
|
<UserPlus />
|
||||||
|
Registration is Closed
|
||||||
|
</Button>
|
||||||
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
import { ThemeProvider } from "next-themes"
|
import { ThemeProvider } from "next-themes"
|
||||||
import type { ReactNode } from "react"
|
import type { ReactNode } from "react"
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
export function Providers({ children }: { children: ReactNode }) {
|
export function Providers({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
<SessionProvider>
|
||||||
{children}
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||||
</ThemeProvider>
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</SessionProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ export function LinkGitea({ linked }: { linked: boolean }) {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
<p className="text-sm mb-4">
|
<p className="text-sm mb-4">
|
||||||
Unlinking your Gitea account will not delete your Gitea account. You can delete your Gitea account <Link href="https://try.gitea.com/user/sign_up" target="_blank" className="text-blue-500">here</Link>.
|
Unlinking your Gitea account will not delete your Gitea account. You can delete your Gitea account <Link href="https://try.gitea.com/user/sign_up" target="_blank" className="underline hover:text-muted-foreground">here</Link>.
|
||||||
</p>
|
</p>
|
||||||
{unlinkLoading ? (
|
{unlinkLoading ? (
|
||||||
<Button variant="destructive" disabled>
|
<Button variant="destructive" disabled>
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
import { useState, useEffect } from "react";
|
"use client"
|
||||||
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { useState, useEffect } from "react"
|
||||||
import { Loader2 } from "lucide-react";
|
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Loader2 } from "lucide-react"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
export const LinkedAccounts = () => {
|
export const LinkedAccounts = () => {
|
||||||
const [gitStatus, setGitStatus] = useState(false)
|
const [gitStatus, setGitStatus] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [isAdmin, setIsAdmin] = useState(false)
|
const [isAdmin, setIsAdmin] = useState(false)
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
const [authStatus, setAuthStatus] = useState(false)
|
||||||
|
|
||||||
|
const { data: session } = useSession()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session?.user?.email) {
|
||||||
|
setAuthStatus(true)
|
||||||
|
}
|
||||||
|
}, [session])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchGitStatus = async () => {
|
const fetchGitStatus = async () => {
|
||||||
@ -40,17 +52,32 @@ export const LinkedAccounts = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchGitStatus().then(r => r)
|
fetchGitStatus()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="col-span-full md:col-span-1">
|
<Card className="col-span-full md:col-span-1">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Linked Accounts</CardTitle>
|
<CardTitle>Linked Accounts</CardTitle>
|
||||||
<CardDescription>LibreCloud-connected services</CardDescription>
|
<CardDescription>LibreCloud-connected services you've linked to your account.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
|
{authStatus ? (
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="w-2 h-2 rounded-full bg-green-500 mr-2"></span>
|
||||||
|
<span>LibreCloud Auth</span>
|
||||||
|
</li>
|
||||||
|
) : (
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="w-2 h-2 rounded-full bg-red-500 mr-2"></span>
|
||||||
|
<span>LibreCloud Auth</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="w-2 h-2 rounded-full bg-green-500 mr-2"></span>
|
||||||
|
<span>LibreCloud Mail</span>
|
||||||
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||||
@ -74,10 +101,6 @@ export const LinkedAccounts = () => {
|
|||||||
<span>LibreCloud Git</span>
|
<span>LibreCloud Git</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
|
||||||
<span className="w-2 h-2 rounded-full bg-green-500 mr-2"></span>
|
|
||||||
<span>p0ntus mail</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
{error && <p className="text-red-500">{error}</p>}
|
{error && <p className="text-red-500">{error}</p>}
|
||||||
|
@ -2,7 +2,8 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import {
|
import {
|
||||||
Mail,
|
Mail,
|
||||||
Headset
|
Headset,
|
||||||
|
Heart
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
@ -17,7 +18,8 @@ export const QuickLinks = () => {
|
|||||||
href="/account/dashboard/support"
|
href="/account/dashboard/support"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className="w-full mb-2"
|
variant="secondary"
|
||||||
|
className="w-full mb-2 cursor-pointer"
|
||||||
>
|
>
|
||||||
<Headset />
|
<Headset />
|
||||||
Support
|
Support
|
||||||
@ -27,12 +29,24 @@ export const QuickLinks = () => {
|
|||||||
href="https://mail.librecloud.cc"
|
href="https://mail.librecloud.cc"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className="w-full mb-2"
|
variant="secondary"
|
||||||
|
className="w-full mb-2 cursor-pointer"
|
||||||
>
|
>
|
||||||
<Mail />
|
<Mail />
|
||||||
Webmail
|
Webmail
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={process.env.NEXT_PUBLIC_DONATE_URL || "https://donate.stripe.com/6oE8yxaPk6yXbpS145"}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="w-full mb-2 cursor-pointer"
|
||||||
|
>
|
||||||
|
<Heart />
|
||||||
|
Donate
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
@ -36,7 +36,7 @@ export const WelcomeCard = () => {
|
|||||||
<p className="text-sm mt-4">That’s all, have a great day!</p>
|
<p className="text-sm mt-4">That’s all, have a great day!</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter>
|
<CardFooter>
|
||||||
<Button className="w-full" onClick={handleMarkAsRead}>
|
<Button className="w-full cursor-pointer" onClick={handleMarkAsRead}>
|
||||||
<Check /> Mark as Read
|
<Check /> Mark as Read
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { Mail, Key, ExternalLink } from "lucide-react"
|
import { Mail, Key, ExternalLink } from "lucide-react"
|
||||||
import { SiGitea, SiAuthentik } from "react-icons/si";
|
import { SiGitea, SiAuthentik } from "react-icons/si";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardFooter, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
|
|
||||||
export const ServicesTab = () => (
|
export const ServicesTab = () => (
|
||||||
@ -13,16 +13,16 @@ export const ServicesTab = () => (
|
|||||||
<Mail className="mr-2 h-4 w-4" />
|
<Mail className="mr-2 h-4 w-4" />
|
||||||
Webmail
|
Webmail
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="pt-4">Send, read, and manage your email account from a web browser!</CardDescription>
|
<CardDescription className="pt-4">Send, read, and manage your email account from a web browser! Powered by Roundcube and LibreCloud Mail.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardFooter>
|
||||||
<Button>
|
<Button>
|
||||||
<ExternalLink className="h-4 w-4" />
|
<ExternalLink className="h-4 w-4" />
|
||||||
<Link href="https://mail.librecloud.cc/">
|
<Link href="https://mail.librecloud.cc/">
|
||||||
Open App
|
Open App
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
@ -31,16 +31,16 @@ export const ServicesTab = () => (
|
|||||||
<SiGitea className="mr-2 h-4 w-4" />
|
<SiGitea className="mr-2 h-4 w-4" />
|
||||||
Git
|
Git
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="pt-4">Host your repositories and run Actions on a fair usage policy.</CardDescription>
|
<CardDescription className="pt-4">Host unlimited repositories and run Actions on our Git server, powered by Gitea.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardFooter>
|
||||||
<Button>
|
<Button>
|
||||||
<ExternalLink className="h-4 w-4" />
|
<ExternalLink className="h-4 w-4" />
|
||||||
<Link href="https://git.pontusmail.org/">
|
<Link href="https://git.pontusmail.org/">
|
||||||
Open App
|
Open App
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
@ -49,16 +49,16 @@ export const ServicesTab = () => (
|
|||||||
<Key className="mr-2 h-4 w-4" />
|
<Key className="mr-2 h-4 w-4" />
|
||||||
Pass
|
Pass
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="pt-4">Securely store your passwords, notes, and 2FA codes with Vaultwarden.</CardDescription>
|
<CardDescription className="pt-4">Securely store your passwords, notes, and 2FA codes with Vaultwarden. Data is encrypted at rest.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardFooter>
|
||||||
<Button>
|
<Button>
|
||||||
<ExternalLink className="h-4 w-4" />
|
<ExternalLink className="h-4 w-4" />
|
||||||
<Link href="https://vaultwarden.p0ntus.com/">
|
<Link href="https://pass.librecloud.cc/">
|
||||||
Open App
|
Open App
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
@ -69,14 +69,14 @@ export const ServicesTab = () => (
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="pt-4">Manage your single-sign-on account for all LibreCloud services.</CardDescription>
|
<CardDescription className="pt-4">Manage your single-sign-on account for all LibreCloud services.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardFooter>
|
||||||
<Button>
|
<Button>
|
||||||
<ExternalLink className="h-4 w-4" />
|
<ExternalLink className="h-4 w-4" />
|
||||||
<Link href="https://auth.librecloud.cc/">
|
<Link href="https://auth.librecloud.cc/">
|
||||||
Open App
|
Open App
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -9,9 +9,10 @@ While this will change in the future, we still suggest that provide all the list
|
|||||||
These are the environment variables which handle how `librecloud/web` functions.
|
These are the environment variables which handle how `librecloud/web` functions.
|
||||||
With these variables, you can disable entire parts of the dashboard, such as registration.
|
With these variables, you can disable entire parts of the dashboard, such as registration.
|
||||||
|
|
||||||
| Environment Variable | Description | Expected Value |
|
| Environment Variable | Description | Expected Value |
|
||||||
|----------------------|-----------------------------------------------------------|----------------------------------------|
|
|------------------------|-----------------------------------------------------------|----------------------------------------|
|
||||||
| SIGNUP_ENABLED | Controls if the signup page and APIs are enabled/disabled | `true` (Enabled) or `false` (Disabled) |
|
| SIGNUP_ENABLED | Controls if the signup page and APIs are enabled/disabled | `true` (Enabled) or `false` (Disabled) |
|
||||||
|
| NEXT_PUBLIC_DONATE_URL | Changes the universal donation link for buttons/links | String - `https://...` |
|
||||||
|
|
||||||
## Authentik
|
## Authentik
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "1.0.0",
|
"cmdk": "1.0.0",
|
||||||
"cookies-next": "^5.1.0",
|
"cookies-next": "^5.1.0",
|
||||||
|
"framer-motion": "^12.6.3",
|
||||||
"geist": "^1.3.1",
|
"geist": "^1.3.1",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"lucide-react": "^0.474.0",
|
"lucide-react": "^0.474.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user