show loading indicators while fetching current user in popup

This commit is contained in:
Alan Hamlett
2024-10-08 21:03:00 +02:00
parent 949c1ebddb
commit 5a75c71328
3 changed files with 45 additions and 18 deletions

View File

@@ -27,6 +27,27 @@ describe('MainList', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div> <div>
<div
class="placeholder-glow"
>
<span
class="placeholder col-12"
/>
</div>
<div
class="placeholder-glow"
>
<span
class="placeholder col-12"
/>
</div>
<div
class="placeholder-glow"
>
<span
class="placeholder col-12"
/>
</div>
<div <div
class="list-group" class="list-group"
> >
@@ -39,17 +60,6 @@ describe('MainList', () => {
/> />
Options Options
</a> </a>
<a
class="list-group-item text-body-secondary"
href="https://wakatime.com/login"
rel="noreferrer"
target="_blank"
>
<i
class="fa fa-fw fa-sign-in me-2"
/>
Login
</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import React from 'react';
import { configLogout, setLoggingEnabled } from '../reducers/configReducer'; import { configLogout, setLoggingEnabled } from '../reducers/configReducer';
import { userLogout } from '../reducers/currentUser'; import { userLogout } from '../reducers/currentUser';
import { ReduxSelector } from '../types/store'; import { ReduxSelector } from '../types/store';
@@ -23,6 +24,9 @@ export default function MainList({
const user: User | undefined = useSelector( const user: User | undefined = useSelector(
(selector: ReduxSelector) => selector.currentUser.user, (selector: ReduxSelector) => selector.currentUser.user,
); );
const isLoading: boolean = useSelector(
(selector: ReduxSelector) => selector.currentUser.pending ?? true,
);
const logoutUser = async (): Promise<void> => { const logoutUser = async (): Promise<void> => {
await browser.storage.sync.set({ apiKey: '' }); await browser.storage.sync.set({ apiKey: '' });
@@ -43,6 +47,12 @@ export default function MainList({
await changeExtensionState('trackingDisabled'); await changeExtensionState('trackingDisabled');
}; };
const loading = isLoading ? (
<div className="placeholder-glow">
<span className="placeholder col-12"></span>
</div>
) : null;
return ( return (
<div> <div>
{user ? ( {user ? (
@@ -56,7 +66,9 @@ export default function MainList({
</blockquote> </blockquote>
</div> </div>
</div> </div>
) : null} ) : (
loading
)}
{loggingEnabled && user ? ( {loggingEnabled && user ? (
<div className="row"> <div className="row">
<div className="col-xs-12"> <div className="col-xs-12">
@@ -71,7 +83,9 @@ export default function MainList({
</p> </p>
</div> </div>
</div> </div>
) : null} ) : (
loading
)}
{!loggingEnabled && user ? ( {!loggingEnabled && user ? (
<div className="row"> <div className="row">
<div className="col-xs-12"> <div className="col-xs-12">
@@ -86,21 +100,22 @@ export default function MainList({
</p> </p>
</div> </div>
</div> </div>
) : null} ) : (
loading
)}
<div className="list-group"> <div className="list-group">
<a href="#" className="list-group-item text-body-secondary" onClick={openOptionsPage}> <a href="#" className="list-group-item text-body-secondary" onClick={openOptionsPage}>
<i className="fa fa-fw fa-cogs me-2" /> <i className="fa fa-fw fa-cogs me-2" />
Options Options
</a> </a>
{user ? ( {isLoading ? null : user ? (
<div> <div>
<a href="#" className="list-group-item text-body-secondary" onClick={logoutUser}> <a href="#" className="list-group-item text-body-secondary" onClick={logoutUser}>
<i className="fa fa-fw fa-sign-out me-2" /> <i className="fa fa-fw fa-sign-out me-2" />
Logout Logout
</a> </a>
</div> </div>
) : null} ) : (
{user ? null : (
<a <a
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"

View File

@@ -36,10 +36,12 @@ const currentUser = createSlice({
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(fetchCurrentUser.fulfilled, (state, { payload }) => { builder.addCase(fetchCurrentUser.fulfilled, (state, { payload }) => {
state.user = payload; state.user = payload;
state.pending = false;
}); });
builder.addCase(fetchCurrentUser.rejected, (state, { error }) => { builder.addCase(fetchCurrentUser.rejected, (state, { error }) => {
state.user = undefined; state.user = undefined;
state.error = error; state.error = error;
state.pending = false;
}); });
}, },
initialState, initialState,