diff --git a/frontend/elements/src/components/form/Button.tsx b/frontend/elements/src/components/form/Button.tsx index f09f96171..8b827ff80 100644 --- a/frontend/elements/src/components/form/Button.tsx +++ b/frontend/elements/src/components/form/Button.tsx @@ -8,6 +8,7 @@ import styles from "./styles.sass"; import LoadingSpinner from "../icons/LoadingSpinner"; import Icon, { IconName } from "../icons/Icon"; import { AppContext, UIAction } from "../../contexts/AppProvider"; +import LastUsed from "./LastUsed"; type Props = { uiAction?: UIAction; @@ -19,6 +20,7 @@ type Props = { isSuccess?: boolean; disabled?: boolean; autofocus?: boolean; + showLastUsed?: boolean; onClick?: (event: Event) => void; icon?: IconName; }; @@ -30,6 +32,7 @@ const Button = ({ secondary, dangerous, autofocus, + showLastUsed, onClick, icon, ...props @@ -93,7 +96,10 @@ const Button = ({ {icon ? ( ) : null} - {children} +
+ {children} + {showLastUsed ? : null} +
); diff --git a/frontend/elements/src/components/form/LastUsed.tsx b/frontend/elements/src/components/form/LastUsed.tsx new file mode 100644 index 000000000..f7eb31b75 --- /dev/null +++ b/frontend/elements/src/components/form/LastUsed.tsx @@ -0,0 +1,11 @@ +import cx from "classnames"; +import styles from "./styles.sass"; +import { useContext } from "preact/compat"; +import { TranslateContext } from "@denysvuika/preact-translate"; + +const LastUsed = () => { + const { t } = useContext(TranslateContext); + return {t("labels.lastUsed")}; +}; + +export default LastUsed; diff --git a/frontend/elements/src/components/form/styles.sass b/frontend/elements/src/components/form/styles.sass index a06af2580..c6d05411e 100644 --- a/frontend/elements/src/components/form/styles.sass +++ b/frontend/elements/src/components/form/styles.sass @@ -32,7 +32,7 @@ white-space: nowrap width: 100% min-width: variables.$button-min-width - height: variables.$item-height + min-height: variables.$item-height outline: none cursor: pointer transition: 0.1s ease-out @@ -68,7 +68,7 @@ color: variables.$color background: variables.$background-color border-color: variables.$color - justify-content: left + justify-content: flex-start &.secondary:hover color: variables.$color @@ -92,7 +92,18 @@ flex-grow: 0 width: auto +// Last Used Styles +.lastUsed + color: variables.$color-shade-1 + font-size: smaller + // Input Styles +.caption + flex-grow: 1 + flex-wrap: wrap + display: flex + justify-content: space-between + align-items: baseline .inputWrapper flex-grow: 1 diff --git a/frontend/elements/src/components/icons/styles.sass b/frontend/elements/src/components/icons/styles.sass index 87736406e..c7f8e3357 100644 --- a/frontend/elements/src/components/icons/styles.sass +++ b/frontend/elements/src/components/icons/styles.sass @@ -50,6 +50,7 @@ height: 100% margin: 0 5px justify-content: inherit + flex-wrap: inherit &.centerContent justify-content: center diff --git a/frontend/elements/src/i18n/bn.ts b/frontend/elements/src/i18n/bn.ts index 36bf51a51..3954a1a3a 100644 --- a/frontend/elements/src/i18n/bn.ts +++ b/frontend/elements/src/i18n/bn.ts @@ -149,6 +149,7 @@ export const bn: Translation = { authenticatorAppAdd: "সেট আপ করুন", configured: "কনফিগার করা হয়েছে", useAnotherMethod: "আরেকটি পদ্ধতি ব্যবহার করুন", + lastUsed: "সর্বশেষ ব্যবহৃত", }, errors: { somethingWentWrong: diff --git a/frontend/elements/src/i18n/de.ts b/frontend/elements/src/i18n/de.ts index dd12a77e0..ea8f32316 100644 --- a/frontend/elements/src/i18n/de.ts +++ b/frontend/elements/src/i18n/de.ts @@ -155,6 +155,7 @@ export const de: Translation = { authenticatorAppAdd: "Einrichten", configured: "konfiguriert", useAnotherMethod: "Eine andere Methode verwenden", + lastUsed: "Zuletzt verwendet", }, errors: { somethingWentWrong: diff --git a/frontend/elements/src/i18n/en.ts b/frontend/elements/src/i18n/en.ts index e2f5da77a..b81b862a4 100644 --- a/frontend/elements/src/i18n/en.ts +++ b/frontend/elements/src/i18n/en.ts @@ -150,6 +150,7 @@ export const en: Translation = { authenticatorAppAdd: "Set up", configured: "configured", useAnotherMethod: "Use another method", + lastUsed: "Last used", }, errors: { somethingWentWrong: diff --git a/frontend/elements/src/i18n/fr.ts b/frontend/elements/src/i18n/fr.ts index cab8e5fa2..f6bb0f990 100644 --- a/frontend/elements/src/i18n/fr.ts +++ b/frontend/elements/src/i18n/fr.ts @@ -155,6 +155,7 @@ export const fr: Translation = { authenticatorAppAdd: "Configurer", configured: "configuré", useAnotherMethod: "Utiliser une autre méthode", + lastUsed: "Dernière utilisation", }, errors: { somethingWentWrong: diff --git a/frontend/elements/src/i18n/it.ts b/frontend/elements/src/i18n/it.ts index 492fc5eb6..b4e88967c 100644 --- a/frontend/elements/src/i18n/it.ts +++ b/frontend/elements/src/i18n/it.ts @@ -151,6 +151,7 @@ export const it: Translation = { authenticatorAppAdd: "Imposta", configured: "configurato", useAnotherMethod: "Usa un altro metodo", + lastUsed: "Ultimo utilizzo", }, errors: { somethingWentWrong: "Si è verificato un errore tecnico. Riprova più tardi.", diff --git a/frontend/elements/src/i18n/pt-BR.ts b/frontend/elements/src/i18n/pt-BR.ts index 198bb037c..c21dac37c 100644 --- a/frontend/elements/src/i18n/pt-BR.ts +++ b/frontend/elements/src/i18n/pt-BR.ts @@ -154,6 +154,7 @@ export const ptBR: Translation = { authenticatorAppAdd: "Configurar", configured: "configurado", useAnotherMethod: "Usar outro método", + lastUsed: "Último uso", }, errors: { somethingWentWrong: diff --git a/frontend/elements/src/i18n/translations.ts b/frontend/elements/src/i18n/translations.ts index 8574f55a0..fd902a8e0 100644 --- a/frontend/elements/src/i18n/translations.ts +++ b/frontend/elements/src/i18n/translations.ts @@ -138,6 +138,7 @@ export interface Translation { currentSession: string; newSecurityKeyName: string; createSecurityKey: string; + lastUsed: string; }; errors: { somethingWentWrong: string; diff --git a/frontend/elements/src/i18n/zh.ts b/frontend/elements/src/i18n/zh.ts index f70c7d195..e6e17b300 100644 --- a/frontend/elements/src/i18n/zh.ts +++ b/frontend/elements/src/i18n/zh.ts @@ -146,6 +146,7 @@ export const zh: Translation = { authenticatorAppAdd: "设置", configured: "已配置", useAnotherMethod: "使用其他方法", + lastUsed: "最后使用", }, errors: { somethingWentWrong: "发生技术错误。请稍后再试。", diff --git a/frontend/elements/src/pages/LoginInitPage.tsx b/frontend/elements/src/pages/LoginInitPage.tsx index 0b4b1da93..bcc8ff1b7 100644 --- a/frontend/elements/src/pages/LoginInitPage.tsx +++ b/frontend/elements/src/pages/LoginInitPage.tsx @@ -40,6 +40,7 @@ const LoginInitPage = (props: Props) => { setUIState, stateHandler, hidePasskeyButtonOnLogin, + lastLogin, } = useContext(AppContext); const [identifierType, setIdentifierType] = useState(null); @@ -240,6 +241,7 @@ const LoginInitPage = (props: Props) => { } disabled={!isWebAuthnSupported} icon={"passkey"} + showLastUsed={lastLogin?.login_method == "passkey"} > {t("labels.signInPasskey")} @@ -258,6 +260,10 @@ const LoginInitPage = (props: Props) => { secondary // @ts-ignore icon={v.value} + showLastUsed={ + lastLogin?.login_method == "third_party" && + lastLogin?.third_party_provider == v.value + } > {t("labels.signInWith", { provider: v.name })} diff --git a/frontend/elements/src/pages/LoginMethodChooser.tsx b/frontend/elements/src/pages/LoginMethodChooser.tsx index 00f6ca283..c0436cf83 100644 --- a/frontend/elements/src/pages/LoginMethodChooser.tsx +++ b/frontend/elements/src/pages/LoginMethodChooser.tsx @@ -22,7 +22,8 @@ interface Props { const LoginMethodChooserPage = (props: Props) => { const { t } = useContext(TranslateContext); - const { hanko, setLoadingAction, stateHandler } = useContext(AppContext); + const { hanko, setLoadingAction, stateHandler, lastLogin } = + useContext(AppContext); const { flowState } = useFlowState(props.state); const onPasswordSelectSubmit = async (event: Event) => { @@ -63,7 +64,11 @@ const LoginMethodChooserPage = (props: Props) => { hidden={!flowState.actions.continue_to_passcode_confirmation?.(null)} onSubmit={onPasscodeSelectSubmit} > -