mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-09-12 21:37:53 -04:00
154 lines
4.0 KiB
HTML
154 lines
4.0 KiB
HTML
<h2 class="login-title">Sign In</h2>
|
|
|
|
@if (error()) {
|
|
<div class="error-message">{{ error() }}</div>
|
|
}
|
|
|
|
@if (retryCountdown() > 0) {
|
|
<div class="retry-countdown">Try again in {{ retryCountdown() }}s</div>
|
|
}
|
|
|
|
<!-- Credentials view -->
|
|
@if (view() === 'credentials') {
|
|
<div class="login-view">
|
|
@if (!oidcExclusiveMode()) {
|
|
<form class="login-form" (ngSubmit)="submitLogin()">
|
|
<app-input
|
|
#usernameInput
|
|
label="Username"
|
|
placeholder="Enter your username"
|
|
type="text"
|
|
[value]="username()"
|
|
(valueChange)="username.set($event)"
|
|
/>
|
|
<app-input
|
|
label="Password"
|
|
placeholder="Enter your password"
|
|
type="password"
|
|
[value]="password()"
|
|
(valueChange)="password.set($event)"
|
|
/>
|
|
<app-button
|
|
variant="primary"
|
|
class="login-submit"
|
|
[disabled]="!username() || !password() || loading() || retryCountdown() > 0"
|
|
type="submit"
|
|
>
|
|
@if (loading()) {
|
|
<app-spinner size="sm" />
|
|
} @else {
|
|
Sign In
|
|
}
|
|
</app-button>
|
|
</form>
|
|
|
|
@if (plexLinked() || oidcEnabled()) {
|
|
<div class="divider">
|
|
<span>or</span>
|
|
</div>
|
|
}
|
|
|
|
@if (plexLinked()) {
|
|
<button
|
|
class="plex-login-btn"
|
|
[disabled]="plexLoading()"
|
|
(click)="startPlexLogin()"
|
|
>
|
|
@if (plexLoading()) {
|
|
<app-spinner size="sm" />
|
|
Waiting for Plex...
|
|
} @else {
|
|
<svg class="plex-login-btn__icon" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M5.074 1L12 12 5.074 23h5.854L18.926 12 11.928 1z"/>
|
|
</svg>
|
|
Sign in with Plex
|
|
}
|
|
</button>
|
|
}
|
|
}
|
|
|
|
@if (oidcEnabled()) {
|
|
<button
|
|
class="oidc-login-btn"
|
|
[disabled]="oidcLoading()"
|
|
(click)="startOidcLogin()"
|
|
>
|
|
@if (oidcLoading()) {
|
|
<app-spinner size="sm" />
|
|
Redirecting...
|
|
} @else {
|
|
<svg class="oidc-login-btn__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
</svg>
|
|
Sign in with {{ oidcProviderName() }}
|
|
}
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<!-- 2FA view -->
|
|
@if (view() === '2fa') {
|
|
<div class="login-view">
|
|
<form class="login-form" (ngSubmit)="submit2fa()">
|
|
<app-input
|
|
#totpInput
|
|
label="Authentication Code"
|
|
placeholder="Enter 6-digit code"
|
|
type="text"
|
|
[value]="totpCode()"
|
|
(valueChange)="totpCode.set($event)"
|
|
/>
|
|
<app-button
|
|
variant="primary"
|
|
class="login-submit"
|
|
[disabled]="totpCode().length !== 6 || loading()"
|
|
type="submit"
|
|
>
|
|
@if (loading()) {
|
|
<app-spinner size="sm" />
|
|
} @else {
|
|
Verify
|
|
}
|
|
</app-button>
|
|
</form>
|
|
|
|
<div class="login-links">
|
|
<button class="text-link" (click)="useRecoveryCode()">Use a recovery code</button>
|
|
<button class="text-link" (click)="backToCredentials()">Back to sign in</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Recovery code view -->
|
|
@if (view() === 'recovery') {
|
|
<div class="login-view">
|
|
<form class="login-form" (ngSubmit)="submitRecoveryCode()">
|
|
<app-input
|
|
#recoveryInput
|
|
label="Recovery Code"
|
|
placeholder="XXXX-XXXX"
|
|
type="text"
|
|
[value]="recoveryCode()"
|
|
(valueChange)="recoveryCode.set($event)"
|
|
/>
|
|
<app-button
|
|
variant="primary"
|
|
class="login-submit"
|
|
[disabled]="!recoveryCode() || loading()"
|
|
type="submit"
|
|
>
|
|
@if (loading()) {
|
|
<app-spinner size="sm" />
|
|
} @else {
|
|
Verify Recovery Code
|
|
}
|
|
</app-button>
|
|
</form>
|
|
|
|
<div class="login-links">
|
|
<button class="text-link" (click)="backTo2fa()">Back to authenticator code</button>
|
|
</div>
|
|
</div>
|
|
}
|