Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion resources/js/common/layouts/AuthBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@
import craftCmsLogoUrl from '@public/images/craftcms.svg';
import {t} from '@craftcms/cp';

const props = withDefaults(
defineProps<{
title?: string;
}>(),
{
title: t('Sign In'),
}
);

const {general, system} = useCraftData();
</script>

<template>
<Head :title="t('Sign In')"></Head>
<Head :title="props.title"></Head>
<main class="cp-login">
<div class="cp-login__wrapper grid gap-3 justify-items-center">
<h1 class="flex justify-center">
Expand Down
2 changes: 2 additions & 0 deletions resources/js/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// elevated session modal can be called from pretty much anywhere
await Promise.all([
import('./modules/auth/components/login/login-form.js'),
import('./modules/auth/components/set-password/set-password-form.js'),
import('./modules/auth/components/verify-email/verify-email-form.js'),
import('./modules/auth/components/totp/totp-form.js'),
import('./modules/auth/components/recovery-codes/recovery-code-form.js'),
]);
Expand Down
12 changes: 9 additions & 3 deletions resources/js/modules/auth/components/login/login-form.styles.ts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should probably rename this file to auth-form.styles.ts and move it out of the login folder

Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,23 @@ export default css`
place-items: center;
}

.login-form__fields {
.auth-form__fields {
display: flex;
gap: var(--c-spacing-md);
align-items: end;
}

.login-form__actions {
.auth-form__actions {
margin-block-start: var(--c-spacing-lg);
}

.login-form__error {
.auth-form__heading {
margin: 0;
font-size: var(--c-font-size);
font-weight: var(--c-font-weight-bold);
}

.auth-form__error {
margin-block-start: var(--c-spacing-md);
}

Expand Down
6 changes: 3 additions & 3 deletions resources/js/modules/auth/components/login/login-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export default class CraftLoginForm extends LitElement {
return html`
<craft-pane>
<form
class="login-form"
class="auth-form"
method="post"
accept-charset="UTF-8"
@submit="${this.#onSubmit}"
Expand Down Expand Up @@ -316,7 +316,7 @@ export default class CraftLoginForm extends LitElement {
: nothing}
</craft-field-group>

<div class="login-form__actions">
<div class="auth-form__actions">
<craft-button
type="submit"
variant="accent"
Expand All @@ -329,7 +329,7 @@ export default class CraftLoginForm extends LitElement {
</form>

${this._error
? html`<craft-callout class="login-form__error" variant="danger"
? html`<craft-callout class="auth-form__error" variant="danger"
>${this._error}</craft-callout
>`
: nothing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default class CraftLoginResetPassword extends LitElement {
return html`
<craft-pane>
<form
class="login-form login-form--reset"
class="auth-form auth-form--reset"
method="post"
accept-charset="UTF-8"
@submit="${this.#onSubmit}"
Expand All @@ -95,7 +95,7 @@ export default class CraftLoginResetPassword extends LitElement {
</craft-input>
</craft-field-group>

<div class="login-form__actions">
<div class="auth-form__actions">
<craft-button
type="submit"
variant="accent"
Expand All @@ -106,7 +106,7 @@ export default class CraftLoginResetPassword extends LitElement {
</div>

${this._error
? html`<craft-callout variant="danger" class="login-form__error"
? html`<craft-callout variant="danger" class="auth-form__error"
>${this._error}</craft-callout
>`
: nothing}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {html, LitElement, nothing} from 'lit';
import {property, state} from 'lit/decorators.js';
import {t} from '@craftcms/cp';
import componentStyles from '../login/login-form.styles.js';

/**
* @summary Full-page set-password form.
* @since 6.0
*/
export default class CraftSetPasswordForm extends LitElement {
static override styles = [componentStyles];

@property() action = '';
@property() uid = '';
@property() code = '';
@property({attribute: 'initial-error'}) initialError = '';
@property({type: Boolean, attribute: 'new-user'}) newUser = false;

@state() private _busy = false;

#passwordLabel() {
return this.newUser ? t('Choose a password') : t('Choose a new password');
}

#onSubmit() {
this._busy = true;
}

override render() {
return html`
<craft-pane>
<form
class="auth-form"
method="post"
action="${this.action}"
accept-charset="UTF-8"
@submit="${this.#onSubmit}"
>
<input type="hidden" name="uid" value="${this.uid}" />
<input type="hidden" name="code" value="${this.code}" />

<craft-field-group>
<craft-input-password
label="${this.#passwordLabel()}"
id="newPassword"
name="newPassword"
autocomplete="new-password"
required
autofocus
></craft-input-password>
</craft-field-group>

<div class="auth-form__actions">
<craft-button
type="submit"
variant="accent"
?loading="${this._busy}"
style="width: 100%"
>
${t('Set Password')}
</craft-button>
</div>
</form>

${this.initialError
? html`<craft-callout class="auth-form__error" variant="danger"
>${this.initialError}</craft-callout
>`
: nothing}
</craft-pane>
`;
}
}

if (!customElements.get('craft-set-password-form')) {
customElements.define('craft-set-password-form', CraftSetPasswordForm);
}

declare global {
interface HTMLElementTagNameMap {
'craft-set-password-form': CraftSetPasswordForm;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {html, LitElement, nothing} from 'lit';
import {property, state} from 'lit/decorators.js';
import {t} from '@craftcms/cp';
import componentStyles from '../login/login-form.styles.js';

/**
* @summary Full-page verify-email form.
* @since 6.0
*/
export default class CraftVerifyEmailForm extends LitElement {
static override styles = [componentStyles];

@property() action = '';
@property() uid = '';
@property() code = '';
@property({attribute: 'initial-error'}) initialError = '';

@state() private _busy = false;

#onSubmit() {
this._busy = true;
}

override render() {
return html`
<craft-pane>
<form
class="auth-form"
method="post"
action="${this.action}"
accept-charset="UTF-8"
@submit="${this.#onSubmit}"
>
<input type="hidden" name="uid" value="${this.uid}" />
<input type="hidden" name="code" value="${this.code}" />

<h2 class="auth-form__heading">${t('Verify your email address')}</h2>

<div class="auth-form__actions">
<craft-button
type="submit"
variant="accent"
?loading="${this._busy}"
style="width: 100%"
>
${t('Verify')}
</craft-button>
</div>
</form>

${this.initialError
? html`<craft-callout class="auth-form__error" variant="danger"
>${this.initialError}</craft-callout
>`
: nothing}
</craft-pane>
`;
}
}

if (!customElements.get('craft-verify-email-form')) {
customElements.define('craft-verify-email-form', CraftVerifyEmailForm);
}

declare global {
interface HTMLElementTagNameMap {
'craft-verify-email-form': CraftVerifyEmailForm;
}
}
38 changes: 38 additions & 0 deletions resources/js/pages/auth/SetPassword.vue
Comment thread
riasvdv marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup lang="ts">
import {computed} from 'vue';
import {t} from '@craftcms/cp';
import {usePage} from '@inertiajs/vue3';
import AuthBase from '@/common/layouts/AuthBase.vue';
import {store} from '@actions/Auth/SetPasswordController';
import '@/modules/auth/components/set-password/set-password-form.js';

const props = defineProps<{
uid: string;
code: string;
newUser: boolean;
}>();

const page = usePage<{
errors?: Record<string, string>;
}>();

const title = computed(() =>
props.newUser ? t('Set Your Password') : t('Set Your New Password')
);

const action = computed(
() => store(undefined, {query: {uid: props.uid, code: props.code}}).url
);
</script>

<template>
<AuthBase :title="title">
<craft-set-password-form
:action="action"
:uid="uid"
:code="code"
:initial-error="page.props.errors?.newPassword"
:new-user="newUser ? '' : null"
></craft-set-password-form>
</AuthBase>
</template>
36 changes: 36 additions & 0 deletions resources/js/pages/auth/VerifyEmail.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup lang="ts">
import {t} from '@craftcms/cp';
import {computed} from 'vue';
import {usePage} from '@inertiajs/vue3';
import AuthBase from '@/common/layouts/AuthBase.vue';
import {store} from '@actions/Auth/VerifyEmailController';
import '@/modules/auth/components/verify-email/verify-email-form.js';

const props = defineProps<{
uid: string;
code: string;
}>();

const page = usePage<{
errors?: Record<string, string>;
}>();

const action = computed(
() => store(undefined, {query: {uid: props.uid, code: props.code}}).url
);

const initialError = computed(
() => page.props.errors?.code ?? page.props.errors?.uid
);
</script>

<template>
<AuthBase :title="t('Verify your email address')">
<craft-verify-email-form
:action="action"
:uid="uid"
:code="code"
:initial-error="initialError"
></craft-verify-email-form>
</AuthBase>
</template>
33 changes: 7 additions & 26 deletions resources/templates/set-password.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{% extends "_layouts/message" %}
{% import "_includes/forms" as forms %}

{% if newUser %}
{% set title = "Set Your Password"|t('app') %}
Expand All @@ -8,30 +7,12 @@
{% endif %}

{% block message %}
<form method="post" accept-charset="UTF-8">
{{ hiddenInput('code', code) }}
{{ hiddenInput('uid', id) }}
{{ csrfInput() }}
{% set passwordErrors = errors.get('newPassword') %}

<div>
{{ forms.passwordField({
id: 'newPassword',
label: (newUser ? "Choose a password"|t('app') : "Choose a new password"|t('app')),
name: 'newPassword',
autocomplete: 'new-password',
autofocus: true,
errors: errors.get('newPassword')
}) }}
</div>

<div class="buttons">
<button class="btn submit" type="submit">{{ 'Set Password'|t('app') }}</button>
</div>
</form>
<craft-set-password-form {{ attr({
uid: uid,
code: code,
'initial-error': passwordErrors ? passwordErrors|first : null,
'new-user': newUser,
}) }}></craft-set-password-form>
{% endblock %}

{% js %}
(() => {
new Craft.PasswordInput($('#newPassword'));
})();
{% endjs %}
Loading
Loading