@@ -8,6 +8,14 @@ export default {
|
|||||||
|
|
||||||
export const Navigation = { args: { routed: false } };
|
export const Navigation = { args: { routed: false } };
|
||||||
|
|
||||||
|
export const LogoutControl = {
|
||||||
|
args: { routed: false },
|
||||||
|
play: async ({ canvasElement }) => {
|
||||||
|
const canvas = within(canvasElement);
|
||||||
|
await expect(canvas.getByRole('button', { name: 'Sign out' })).toHaveAttribute('aria-busy', 'false');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const KeyboardSkipLink = {
|
export const KeyboardSkipLink = {
|
||||||
args: { routed: false },
|
args: { routed: false },
|
||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement }) => {
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterView } from 'vue-router';
|
import { RouterView } from 'vue-router';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { useAuth } from '@/composables/useAuth.js';
|
import { useAuth } from '@/composables/useAuth.js';
|
||||||
|
|
||||||
defineProps({ routed: { type: Boolean, default: true } });
|
defineProps({ routed: { type: Boolean, default: true } });
|
||||||
const { principal, signOut } = useAuth();
|
const { principal, signOut } = useAuth();
|
||||||
|
const isLoggingOut = ref(false);
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
await signOut();
|
isLoggingOut.value = true;
|
||||||
window.location.href = '/login';
|
try {
|
||||||
|
await signOut();
|
||||||
|
window.location.href = '/login';
|
||||||
|
} finally {
|
||||||
|
isLoggingOut.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -29,7 +36,7 @@ async function logout() {
|
|||||||
</nav>
|
</nav>
|
||||||
<div class="admin-sidebar__footer">
|
<div class="admin-sidebar__footer">
|
||||||
<span>{{ principal?.email }}</span>
|
<span>{{ principal?.email }}</span>
|
||||||
<button class="button button--secondary" type="button" @click="logout">Sign out</button>
|
<button class="button button--secondary" type="button" :disabled="isLoggingOut" :aria-busy="isLoggingOut" @click="logout">{{ isLoggingOut ? 'Signing out…' : 'Sign out' }}</button>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
<section id="admin-content" class="admin-shell__content" tabindex="-1"><RouterView v-if="routed" /></section>
|
<section id="admin-content" class="admin-shell__content" tabindex="-1"><RouterView v-if="routed" /></section>
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ Remaining roadmap areas are approved external provider credentials/adapters, bro
|
|||||||
- Saved-view rows now expose an accessible view name, and the image-limit setting includes range guidance tied to its input.
|
- Saved-view rows now expose an accessible view name, and the image-limit setting includes range guidance tied to its input.
|
||||||
- Login errors now move focus to the announced error message so failed authentication is immediately available to keyboard and assistive-technology users.
|
- Login errors now move focus to the announced error message so failed authentication is immediately available to keyboard and assistive-technology users.
|
||||||
- Login error focus behavior now has Storybook interaction coverage using a deterministic failed-authentication response.
|
- Login error focus behavior now has Storybook interaction coverage using a deterministic failed-authentication response.
|
||||||
|
- Admin logout now exposes a busy state and disables repeat activation while the session is being revoked.
|
||||||
|
|
||||||
## Local Commands
|
## Local Commands
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user