mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
refactor(ui): refactor app notification logic (#1241)
refactor app notification logic
This commit is contained in:
parent
2d663025ec
commit
6865efff27
9 changed files with 66 additions and 61 deletions
|
@ -1,7 +1,12 @@
|
|||
import { ConnectorMetadata } from '@logto/connector-types';
|
||||
import { SignInMode } from '@logto/schemas';
|
||||
import { adminConsoleApplicationId, adminConsoleSignInMethods } from '@logto/schemas/lib/seeds';
|
||||
import {
|
||||
adminConsoleApplicationId,
|
||||
adminConsoleSignInMethods,
|
||||
demoAppApplicationId,
|
||||
} from '@logto/schemas/lib/seeds';
|
||||
import etag from 'etag';
|
||||
import i18next from 'i18next';
|
||||
import { Provider, errors } from 'oidc-provider';
|
||||
|
||||
import { getConnectorInstances } from '@/connectors';
|
||||
|
@ -56,6 +61,17 @@ export default function signInSettingsRoutes<T extends AnonymousRouter>(
|
|||
return next();
|
||||
}
|
||||
|
||||
// Insert Notification Message to DemoApp
|
||||
if (interaction?.params.client_id === demoAppApplicationId) {
|
||||
ctx.body = {
|
||||
...signInExperience,
|
||||
socialConnectors,
|
||||
notification: i18next.t('demo_app.notification'),
|
||||
};
|
||||
|
||||
return next();
|
||||
}
|
||||
|
||||
ctx.body = { ...signInExperience, socialConnectors };
|
||||
|
||||
return next();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { LogtoProvider, useLogto, UserInfoResponse } from '@logto/react';
|
||||
import { signInNotificationStorageKey } from '@logto/schemas';
|
||||
import { demoAppApplicationId } from '@logto/schemas/lib/seeds';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -32,7 +31,6 @@ const Main = () => {
|
|||
setUser(userInfo);
|
||||
})();
|
||||
} else {
|
||||
sessionStorage.setItem(signInNotificationStorageKey, t('notification'));
|
||||
void signIn(window.location.href);
|
||||
}
|
||||
}, [fetchUserInfo, isAuthenticated, isInCallback, signIn, t]);
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export const signInNotificationStorageKey = 'logto:client:notification';
|
|
@ -1,4 +1,3 @@
|
|||
export * from './consts';
|
||||
export * from './foundations';
|
||||
export * from './db-entries';
|
||||
export * from './types';
|
||||
|
|
|
@ -1,23 +1,31 @@
|
|||
import { signInNotificationStorageKey } from '@logto/schemas';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import AppNotification from '.';
|
||||
import renderWithPageContext from '@/__mocks__/RenderWithPageContext';
|
||||
import SettingsProvider from '@/__mocks__/RenderWithPageContext/SettingsProvider';
|
||||
import { mockSignInExperienceSettings } from '@/__mocks__/logto';
|
||||
|
||||
describe('AppNotification', () => {
|
||||
it('render properly', () => {
|
||||
const message = 'This is a notification message';
|
||||
sessionStorage.setItem(signInNotificationStorageKey, message);
|
||||
const { queryByText, getByText } = render(<AppNotification />);
|
||||
import Notification from './index';
|
||||
|
||||
expect(queryByText(message)).not.toBeNull();
|
||||
describe('Notification', () => {
|
||||
it('render Notification', () => {
|
||||
const notification = 'text notification';
|
||||
|
||||
const closeLink = getByText('action.got_it');
|
||||
const { queryByText, getByText } = renderWithPageContext(
|
||||
<SettingsProvider
|
||||
settings={{
|
||||
...mockSignInExperienceSettings,
|
||||
notification,
|
||||
}}
|
||||
>
|
||||
<Notification />
|
||||
</SettingsProvider>
|
||||
);
|
||||
|
||||
expect(closeLink).not.toBeNull();
|
||||
expect(queryByText(notification)).not.toBeNull();
|
||||
|
||||
fireEvent.click(closeLink);
|
||||
|
||||
expect(queryByText(message)).toBeNull();
|
||||
const closeButton = getByText('action.got_it');
|
||||
fireEvent.click(closeButton);
|
||||
expect(queryByText(notification)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
import { Nullable } from '@silverhand/essentials';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
|
||||
import Notification from '@/components/Notification';
|
||||
import { getAppNotificationInfo, clearAppNotificationInfo } from '@/utils/session-storage';
|
||||
import { PageContext } from '@/hooks/use-page-context';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
const AppNotification = () => {
|
||||
const [notification, setNotification] = useState<Nullable<string>>(null);
|
||||
const { experienceSettings, setExperienceSettings } = useContext(PageContext);
|
||||
const notification = experienceSettings?.notification;
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
setNotification(null);
|
||||
clearAppNotificationInfo();
|
||||
}, []);
|
||||
// Clear notification
|
||||
setExperienceSettings((settings) => {
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const notification = getAppNotificationInfo();
|
||||
setNotification(notification);
|
||||
}, []);
|
||||
return {
|
||||
...settings,
|
||||
notification: undefined,
|
||||
};
|
||||
});
|
||||
}, [setExperienceSettings]);
|
||||
|
||||
if (!notification) {
|
||||
return null;
|
||||
|
|
|
@ -10,12 +10,12 @@ export type Context = {
|
|||
platform: Platform;
|
||||
termsAgreement: boolean;
|
||||
experienceSettings: SignInExperienceSettings | undefined;
|
||||
setTheme: (theme: Theme) => void;
|
||||
setToast: (message: string) => void;
|
||||
setLoading: (loading: boolean) => void;
|
||||
setPlatform: (platform: Platform) => void;
|
||||
setTermsAgreement: (termsAgreement: boolean) => void;
|
||||
setExperienceSettings: (settings: SignInExperienceSettings) => void;
|
||||
setTheme: React.Dispatch<React.SetStateAction<Theme>>;
|
||||
setToast: React.Dispatch<React.SetStateAction<string>>;
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setPlatform: React.Dispatch<React.SetStateAction<Platform>>;
|
||||
setTermsAgreement: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setExperienceSettings: React.Dispatch<React.SetStateAction<SignInExperienceSettings | undefined>>;
|
||||
};
|
||||
|
||||
const noop = () => {
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
import {
|
||||
Branding,
|
||||
LanguageInfo,
|
||||
TermsOfUse,
|
||||
SignInExperience,
|
||||
ConnectorMetadata,
|
||||
SignInMode,
|
||||
Color,
|
||||
} from '@logto/schemas';
|
||||
import { SignInExperience, ConnectorMetadata } from '@logto/schemas';
|
||||
|
||||
export type UserFlow = 'sign-in' | 'register';
|
||||
export type SignInMethod = 'username' | 'email' | 'sms' | 'social';
|
||||
|
@ -28,15 +20,13 @@ export interface ConnectorData extends ConnectorMetadata {
|
|||
|
||||
export type SignInExperienceSettingsResponse = SignInExperience & {
|
||||
socialConnectors: ConnectorData[];
|
||||
notification?: string;
|
||||
};
|
||||
|
||||
export type SignInExperienceSettings = {
|
||||
color: Color;
|
||||
branding: Branding;
|
||||
languageInfo: LanguageInfo;
|
||||
termsOfUse: TermsOfUse;
|
||||
export type SignInExperienceSettings = Omit<
|
||||
SignInExperienceSettingsResponse,
|
||||
'id' | 'signInMethods' | 'socialSignInConnectorTargets'
|
||||
> & {
|
||||
primarySignInMethod: SignInMethod;
|
||||
secondarySignInMethods: SignInMethod[];
|
||||
socialConnectors: ConnectorData[];
|
||||
signInMode: SignInMode;
|
||||
};
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import { signInNotificationStorageKey } from '@logto/schemas';
|
||||
|
||||
export const getAppNotificationInfo = () => {
|
||||
return sessionStorage.getItem(signInNotificationStorageKey);
|
||||
};
|
||||
|
||||
export const clearAppNotificationInfo = () => {
|
||||
sessionStorage.removeItem(signInNotificationStorageKey);
|
||||
};
|
Loading…
Add table
Reference in a new issue