mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
refactor(experience): remove demo app notification (#4851)
This commit is contained in:
parent
f58f93f3f1
commit
c5809e4722
37 changed files with 8 additions and 216 deletions
|
@ -6,10 +6,9 @@ import { conditionalArray } from '@silverhand/essentials';
|
|||
|
||||
import { isDevFeaturesEnabled } from '@/consts/env';
|
||||
|
||||
export const hiddenLocalePhraseGroups: readonly LocalePhraseGroupKey[] = [
|
||||
'demo_app',
|
||||
...conditionalArray(!isDevFeaturesEnabled && 'mfa'),
|
||||
];
|
||||
export const hiddenLocalePhraseGroups: readonly LocalePhraseGroupKey[] = conditionalArray(
|
||||
!isDevFeaturesEnabled && 'mfa'
|
||||
);
|
||||
|
||||
export const hiddenLocalePhrases: readonly LocalePhraseKey[] = [
|
||||
...conditionalArray(
|
||||
|
|
|
@ -183,8 +183,7 @@ export default function initOidc(
|
|||
);
|
||||
|
||||
const appendParameters = (path: string) => {
|
||||
// `notification` is for showing a text banner on the homepage
|
||||
return isDemoApp ? path + `?notification=demo_app.notification&no_cache` : path;
|
||||
return isDemoApp ? path + `?no_cache` : path;
|
||||
};
|
||||
|
||||
switch (prompt.name) {
|
||||
|
|
|
@ -9,8 +9,6 @@ import PageMeta from '@/components/PageMeta';
|
|||
import { layoutClassNames } from '@/utils/consts';
|
||||
import { getBrandingLogoUrl } from '@/utils/logo';
|
||||
|
||||
import AppNotification from '../../containers/AppNotification';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
|
@ -44,7 +42,6 @@ const LandingPageLayout = ({ children, className, title }: Props) => {
|
|||
{children}
|
||||
</div>
|
||||
{platform === 'web' && <div className={styles.placeholderBottom} />}
|
||||
<AppNotification />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.appNotification {
|
||||
position: absolute;
|
||||
max-width: 520px;
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.appNotification {
|
||||
top: _.unit(6);
|
||||
left: _.unit(5);
|
||||
right: _.unit(5);
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.appNotification {
|
||||
left: 50%;
|
||||
transform: translate(-50%);
|
||||
width: max-content;
|
||||
max-width: calc(100% - 40px);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
import type { Nullable } from '@silverhand/essentials';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import { AppNotification as Notification } from '@/components/Notification';
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
import { searchKeys } from '@/utils/search-parameters';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
const AppNotification = () => {
|
||||
const { isMobile } = usePlatform();
|
||||
const [notification, setNotification] = useState<Nullable<string>>(null);
|
||||
const [topOffset, setTopOffset] = useState<number>();
|
||||
const eleRef = useRef<HTMLDivElement>(null);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const adjustNotificationPosition = useCallback(() => {
|
||||
const mainEleOffsetTop = document.querySelector('main')?.offsetTop;
|
||||
const elementHeight = eleRef.current?.offsetHeight;
|
||||
|
||||
if (mainEleOffsetTop !== undefined && elementHeight) {
|
||||
const topSpace = mainEleOffsetTop - elementHeight - 24;
|
||||
setTopOffset(Math.max(32, topSpace));
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setNotification(sessionStorage.getItem(searchKeys.notification));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!notification || isMobile) {
|
||||
return;
|
||||
}
|
||||
|
||||
adjustNotificationPosition();
|
||||
|
||||
window.addEventListener('resize', adjustNotificationPosition);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', adjustNotificationPosition);
|
||||
};
|
||||
}, [adjustNotificationPosition, isMobile, notification]);
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
setNotification(null);
|
||||
}, []);
|
||||
|
||||
if (!notification) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createPortal(
|
||||
<Notification
|
||||
ref={eleRef}
|
||||
className={styles.appNotification}
|
||||
message={<Trans t={t}>{notification}</Trans>}
|
||||
style={isMobile ? undefined : { top: topOffset }}
|
||||
onClose={onClose}
|
||||
/>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
export default AppNotification;
|
|
@ -1,5 +1,4 @@
|
|||
export const searchKeys = Object.freeze({
|
||||
notification: 'notification',
|
||||
noCache: 'no_cache',
|
||||
});
|
||||
|
||||
|
@ -12,12 +11,6 @@ export const handleSearchParametersData = () => {
|
|||
|
||||
const parameters = new URLSearchParams(search);
|
||||
|
||||
const notification = parameters.get(searchKeys.notification);
|
||||
|
||||
if (notification) {
|
||||
sessionStorage.setItem(searchKeys.notification, notification);
|
||||
}
|
||||
|
||||
if (parameters.get(searchKeys.noCache) !== null) {
|
||||
sessionStorage.setItem(searchKeys.noCache, 'true');
|
||||
}
|
||||
|
|
|
@ -41,18 +41,18 @@ describe('.well-known api', () => {
|
|||
|
||||
// Also test for Redis cache invalidation
|
||||
it('should be able to return updated phrases', async () => {
|
||||
const notification = 'Big brother is watching you.';
|
||||
const and = '&';
|
||||
const original = await api
|
||||
.get('.well-known/phrases?lng=en')
|
||||
.json<{ translation: Translation }>();
|
||||
|
||||
expect(original.translation.demo_app).not.toHaveProperty('notification', notification);
|
||||
expect(original.translation.list).not.toHaveProperty('and', and);
|
||||
|
||||
await authedAdminApi.put('custom-phrases/en', { json: { demo_app: { notification } } });
|
||||
await authedAdminApi.put('custom-phrases/en', { json: { list: { and } } });
|
||||
const updated = await api
|
||||
.get('.well-known/phrases?lng=en')
|
||||
.json<{ translation: Translation }>();
|
||||
expect(updated.translation.demo_app).toHaveProperty('notification', notification);
|
||||
expect(updated.translation.list).toHaveProperty('and', and);
|
||||
});
|
||||
|
||||
describe('sso connectors in sign-in experience', () => {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Tipp: Erstelle zuerst ein Konto, um die Anmeldeerfahrung zu testen.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const de = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Tip: Create an account first to test the sign-in experience.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,5 +1,4 @@
|
|||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -14,7 +13,6 @@ const en = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Consejo: Crea una cuenta primero para probar la experiencia de inicio de sesión.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const es = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: "Astuce : Créez d'abord un compte pour tester l'expérience de connexion.",
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const fr = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: "Suggerimento: crea prima un account per testare l'esperienza di accesso.",
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const it = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'ヒント:最初にアカウントを作成してサインイン体験をテストしてください。',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const ja = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: '알림:로그인 경험을 테스트하기 위해 먼저 계정을 만드는 것이 좋아요.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const ko = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Wskazówka: Najpierw stwórz konto, aby przetestować proces logowania.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const pl_pl = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Dica: Crie uma conta primeiro para testar a experiência de login.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const pt_br = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Dica: Crie uma conta primeiro para testar a experiência de login.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const pt_pt = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'Совет: Создайте аккаунт сначала, чтобы протестировать процесс входа.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const ru = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: 'İpucu: Oturum açma deneyimini test etmek için önce bir hesap oluşturun.',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const tr_tr = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: '提示:先注册一个账号,再测试登录体验。',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const zh_cn = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: '提示:先注冊一個賬號,再測試登入體驗。',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const zh_hk = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const demo_app = {
|
||||
notification: '提示:先註冊一個帳號,再測試登錄體驗。',
|
||||
};
|
||||
|
||||
export default Object.freeze(demo_app);
|
|
@ -1,7 +1,6 @@
|
|||
import type { LocalePhrase } from '../../types.js';
|
||||
|
||||
import action from './action.js';
|
||||
import demo_app from './demo-app.js';
|
||||
import description from './description.js';
|
||||
import error from './error/index.js';
|
||||
import input from './input.js';
|
||||
|
@ -16,7 +15,6 @@ const zh_tw = {
|
|||
action,
|
||||
description,
|
||||
error,
|
||||
demo_app,
|
||||
list,
|
||||
mfa,
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue