mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-08-04 22:40:11 +00:00
feat: add pendingAuthRequestsRefreshing state to improve loading feedback in auth request components
This commit is contained in:
+2
-3
@@ -1115,8 +1115,6 @@ export default function App() {
|
||||
queryFn: () => listPendingAuthRequests(authedFetch, profile?.email || session?.email || ''),
|
||||
enabled: !IS_DEMO_MODE && phase === 'app' && !!session?.accessToken && !!session?.symEncKey && !!session?.symMacKey && !!(profile?.email || session?.email),
|
||||
staleTime: 5_000,
|
||||
refetchInterval: 15_000,
|
||||
refetchIntervalInBackground: true,
|
||||
});
|
||||
const pendingAuthRequests = (pendingAuthRequestsQuery.data || []).filter(isPendingAuthRequest);
|
||||
const latestPendingAuthRequest = pendingAuthRequests[0] || null;
|
||||
@@ -2015,7 +2013,8 @@ export default function App() {
|
||||
onEnableAccountPasskeyDirectUnlock: accountSecurityActions.enableAccountPasskeyDirectUnlock,
|
||||
onDeleteAccountPasskey: accountSecurityActions.deleteAccountPasskey,
|
||||
pendingAuthRequests,
|
||||
pendingAuthRequestsLoading: pendingAuthRequestsQuery.isFetching,
|
||||
pendingAuthRequestsLoading: pendingAuthRequestsQuery.isLoading,
|
||||
pendingAuthRequestsRefreshing: pendingAuthRequestsQuery.isFetching && !pendingAuthRequestsQuery.isLoading,
|
||||
onRefreshPendingAuthRequests: async () => {
|
||||
await pendingAuthRequestsQuery.refetch();
|
||||
},
|
||||
|
||||
@@ -119,6 +119,7 @@ export interface AppMainRoutesProps {
|
||||
onDeleteAccountPasskey: (id: string, masterPassword: string) => Promise<void>;
|
||||
pendingAuthRequests: AuthRequest[];
|
||||
pendingAuthRequestsLoading: boolean;
|
||||
pendingAuthRequestsRefreshing: boolean;
|
||||
onRefreshPendingAuthRequests: () => Promise<void>;
|
||||
onApproveAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
onDenyAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
@@ -354,6 +355,7 @@ export default function AppMainRoutes(props: AppMainRoutesProps) {
|
||||
error={props.authorizedDevicesError}
|
||||
pendingAuthRequests={props.pendingAuthRequests}
|
||||
pendingAuthRequestsLoading={props.pendingAuthRequestsLoading}
|
||||
pendingAuthRequestsRefreshing={props.pendingAuthRequestsRefreshing}
|
||||
onRefresh={() => void props.onRefreshAuthorizedDevices()}
|
||||
onRefreshPendingAuthRequests={props.onRefreshPendingAuthRequests}
|
||||
onApproveAuthRequest={props.onApproveAuthRequest}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { t } from '@/lib/i18n';
|
||||
interface PendingAuthRequestsPanelProps {
|
||||
pendingAuthRequests: AuthRequest[];
|
||||
pendingAuthRequestsLoading: boolean;
|
||||
pendingAuthRequestsRefreshing?: boolean;
|
||||
onRefreshPendingAuthRequests: () => Promise<void>;
|
||||
onApproveAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
onDenyAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
@@ -22,6 +23,7 @@ function formatDateTime(value: string | null | undefined): string {
|
||||
|
||||
export default function PendingAuthRequestsPanel(props: PendingAuthRequestsPanelProps) {
|
||||
const [authRequestSubmittingId, setAuthRequestSubmittingId] = useState<string | null>(null);
|
||||
const refreshing = props.pendingAuthRequestsLoading || !!props.pendingAuthRequestsRefreshing;
|
||||
|
||||
async function approveAuthRequest(authRequest: AuthRequest): Promise<void> {
|
||||
if (authRequestSubmittingId) return;
|
||||
@@ -50,10 +52,10 @@ export default function PendingAuthRequestsPanel(props: PendingAuthRequestsPanel
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary small"
|
||||
disabled={props.pendingAuthRequestsLoading}
|
||||
disabled={refreshing}
|
||||
onClick={() => void props.onRefreshPendingAuthRequests()}
|
||||
>
|
||||
<RefreshCw size={14} className="btn-icon" />
|
||||
<RefreshCw size={14} className={`btn-icon${refreshing ? ' btn-icon-spin' : ''}`} />
|
||||
{t('txt_refresh')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,7 @@ interface SecurityDevicesPageProps {
|
||||
error: string;
|
||||
pendingAuthRequests: AuthRequest[];
|
||||
pendingAuthRequestsLoading: boolean;
|
||||
pendingAuthRequestsRefreshing: boolean;
|
||||
onRefresh: () => void;
|
||||
onRefreshPendingAuthRequests: () => Promise<void>;
|
||||
onApproveAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
@@ -106,6 +107,7 @@ export default function SecurityDevicesPage(props: SecurityDevicesPageProps) {
|
||||
loadingVariant="compact"
|
||||
pendingAuthRequests={props.pendingAuthRequests}
|
||||
pendingAuthRequestsLoading={props.pendingAuthRequestsLoading}
|
||||
pendingAuthRequestsRefreshing={props.pendingAuthRequestsRefreshing}
|
||||
onRefreshPendingAuthRequests={props.onRefreshPendingAuthRequests}
|
||||
onApproveAuthRequest={props.onApproveAuthRequest}
|
||||
onDenyAuthRequest={props.onDenyAuthRequest}
|
||||
|
||||
@@ -172,6 +172,10 @@ input[type='file'].input::file-selector-button:hover {
|
||||
@apply shrink-0;
|
||||
}
|
||||
|
||||
.btn-icon-spin {
|
||||
animation: spin 0.9s linear infinite;
|
||||
}
|
||||
|
||||
.btn.full {
|
||||
@apply my-2.5 h-12 w-full;
|
||||
font-size: var(--font-md);
|
||||
|
||||
Reference in New Issue
Block a user