Implement the template
This commit is contained in:
parent
f92488b80d
commit
292881532a
@ -45,7 +45,7 @@ export function generateFtlFilesCodeFactory(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(element).attr(attrName, "${url.resourcesPath}" + href);
|
$(element).attr(attrName, "${url.resourcesPath}/build" + href);
|
||||||
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,9 @@ import {
|
|||||||
replaceImportFromStaticInJsCode
|
replaceImportFromStaticInJsCode
|
||||||
} from "./replaceImportFromStatic";
|
} from "./replaceImportFromStatic";
|
||||||
import { generateFtlFilesCodeFactory } from "./generateFtl";
|
import { generateFtlFilesCodeFactory } from "./generateFtl";
|
||||||
|
import { keycloakBuiltinThemesAndThirdPartyExamplesThemsUrl } from "../download-sample-keycloak-themes";
|
||||||
|
import { downloadAndUnzip } from "../tools/downloadAndUnzip";
|
||||||
|
import * as child_process from "child_process";
|
||||||
|
|
||||||
export const ftlValuesGlobalName = "keycloakPagesContext";
|
export const ftlValuesGlobalName = "keycloakPagesContext";
|
||||||
|
|
||||||
@ -25,7 +28,7 @@ export function generateKeycloakThemeResources(
|
|||||||
let allCssGlobalsToDefine: Record<string, string> = {};
|
let allCssGlobalsToDefine: Record<string, string> = {};
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
"destDirPath": pathJoin(themeDirPath, "resources"),
|
"destDirPath": pathJoin(themeDirPath, "resources", "build"),
|
||||||
"srcDirPath": reactAppBuildDirPath,
|
"srcDirPath": reactAppBuildDirPath,
|
||||||
"transformSourceCodeString": ({ filePath, sourceCode }) => {
|
"transformSourceCodeString": ({ filePath, sourceCode }) => {
|
||||||
|
|
||||||
@ -79,9 +82,31 @@ export function generateKeycloakThemeResources(
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
const destDirPath = pathJoin(themeDirPath, "..", "tmp_xxKdLpdIdLd");
|
||||||
|
|
||||||
|
downloadAndUnzip({
|
||||||
|
"url": keycloakBuiltinThemesAndThirdPartyExamplesThemsUrl,
|
||||||
|
destDirPath
|
||||||
|
});
|
||||||
|
|
||||||
|
child_process.execSync(
|
||||||
|
[
|
||||||
|
"mv",
|
||||||
|
pathJoin("keycloak", "common"),
|
||||||
|
pathJoin("..", "common")
|
||||||
|
].join(" "),
|
||||||
|
{ "cwd": destDirPath }
|
||||||
|
);
|
||||||
|
|
||||||
|
child_process.execSync(`rm -r ${destDirPath}`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
pathJoin(themeDirPath, "theme.properties"),
|
pathJoin(themeDirPath, "theme.properties"),
|
||||||
Buffer.from("parent=base\n", "utf8")
|
Buffer.from(`import=common/${themeName}\n`, "utf8")
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export function replaceImportFromStaticInJsCode(
|
|||||||
|
|
||||||
const fixedJsCode = jsCode!.replace(
|
const fixedJsCode = jsCode!.replace(
|
||||||
/"static\//g,
|
/"static\//g,
|
||||||
`window.${ftlValuesGlobalName}.url.resourcesPath.replace(/^\\//,"") + "/" + "static/`
|
`window.${ftlValuesGlobalName}.url.resourcesPath.replace(/^\\//,"") + "/build/static/`
|
||||||
);
|
);
|
||||||
|
|
||||||
return { fixedJsCode };
|
return { fixedJsCode };
|
||||||
@ -75,7 +75,7 @@ export function generateCssCodeToDefineGlobals(
|
|||||||
`--${cssVariableName}:`,
|
`--${cssVariableName}:`,
|
||||||
[
|
[
|
||||||
"url(",
|
"url(",
|
||||||
"${url.resourcesPath}" +
|
"${url.resourcesPath}/build" +
|
||||||
cssGlobalsToDefine[cssVariableName].match(/^url\(([^)]+)\)$/)![1],
|
cssGlobalsToDefine[cssVariableName].match(/^url\(([^)]+)\)$/)![1],
|
||||||
")"
|
")"
|
||||||
].join("")
|
].join("")
|
||||||
|
288
src/lib/Template.tsx
Normal file
288
src/lib/Template.tsx
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useKeycloakThemeTranslation } from "./i18n/useKeycloakTranslation";
|
||||||
|
import { keycloakPagesContext } from "./keycloakFtlValues";
|
||||||
|
import { assert } from "evt/tools/typeSafety/assert";
|
||||||
|
import { cx } from "tss-react";
|
||||||
|
import { useKeycloakLanguage, AvailableLanguages } from "./i18n/useKeycloakLanguage";
|
||||||
|
import { getLanguageLabel } from "./i18n/getLanguageLabel";
|
||||||
|
import { useCallbackFactory } from "powerhooks";
|
||||||
|
import { appendLinkInHead } from "./tools/appendLinkInHead";
|
||||||
|
import { appendScriptInHead } from "./tools/appendScriptInHead";
|
||||||
|
import { join as pathJoin } from "path";
|
||||||
|
import { useConstCallback } from "powerhooks";
|
||||||
|
|
||||||
|
type KcClasses<T extends string> = { [key in T]?: string[] | string };
|
||||||
|
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
displayInfo?: boolean;
|
||||||
|
displayMessage: boolean;
|
||||||
|
displayRequiredFields: boolean;
|
||||||
|
displayWide: boolean;
|
||||||
|
showAnotherWayIfPresent: boolean;
|
||||||
|
properties?: {
|
||||||
|
stylesCommon?: string[];
|
||||||
|
styles?: string[];
|
||||||
|
scripts?: string[];
|
||||||
|
} & KcClasses<
|
||||||
|
"kcLoginClass" |
|
||||||
|
"kcHeaderClass" |
|
||||||
|
"kcHeaderWrapperClass" |
|
||||||
|
"kcFormCardClass" |
|
||||||
|
"kcFormCardAccountClass" |
|
||||||
|
"kcFormHeaderClass" |
|
||||||
|
"kcLocaleWrapperClass" |
|
||||||
|
"kcContentWrapperClass" |
|
||||||
|
"kcLabelWrapperClass" |
|
||||||
|
"kcContentWrapperClass" |
|
||||||
|
"kcLabelWrapperClass" |
|
||||||
|
"kcFormGroupClass" |
|
||||||
|
"kcResetFlowIcon" |
|
||||||
|
"kcResetFlowIcon" |
|
||||||
|
"kcFeedbackSuccessIcon" |
|
||||||
|
"kcFeedbackWarningIcon" |
|
||||||
|
"kcFeedbackErrorIcon" |
|
||||||
|
"kcFeedbackInfoIcon" |
|
||||||
|
"kcContentWrapperClass" |
|
||||||
|
"kcFormSocialAccountContentClass" |
|
||||||
|
"kcFormSocialAccountClass" |
|
||||||
|
"kcSignUpClass" |
|
||||||
|
"kcInfoAreaWrapperClass"
|
||||||
|
>;
|
||||||
|
headerNode: ReactNode;
|
||||||
|
showUsernameNode: ReactNode;
|
||||||
|
formNode: ReactNode;
|
||||||
|
displayInfoNode: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Template(props: Props) {
|
||||||
|
|
||||||
|
const {
|
||||||
|
displayInfo = false,
|
||||||
|
displayMessage = true,
|
||||||
|
displayRequiredFields = false,
|
||||||
|
displayWide = false,
|
||||||
|
showAnotherWayIfPresent = true,
|
||||||
|
properties = {},
|
||||||
|
headerNode,
|
||||||
|
showUsernameNode,
|
||||||
|
formNode,
|
||||||
|
displayInfoNode
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const { t } = useKeycloakThemeTranslation();
|
||||||
|
|
||||||
|
const { keycloakLanguage, setKeycloakLanguage } = useKeycloakLanguage();
|
||||||
|
|
||||||
|
const onChangeLanguageClickFactory = useCallbackFactory(
|
||||||
|
([languageTag]: [AvailableLanguages]) =>
|
||||||
|
setKeycloakLanguage(languageTag)
|
||||||
|
);
|
||||||
|
|
||||||
|
const onTryAnotherWayClick = useConstCallback(() => {
|
||||||
|
|
||||||
|
document.forms["kc-select-try-another-way-form" as never].submit();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const [{ realm, locale, auth, url, message, isAppInitiatedAction }] = useState(() => {
|
||||||
|
|
||||||
|
assert(keycloakPagesContext !== undefined);
|
||||||
|
|
||||||
|
return keycloakPagesContext;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
properties.stylesCommon?.forEach(
|
||||||
|
relativePath =>
|
||||||
|
appendLinkInHead(
|
||||||
|
{ "href": pathJoin(url.resourcesCommonPath, relativePath) }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
properties.styles?.forEach(
|
||||||
|
relativePath =>
|
||||||
|
appendLinkInHead(
|
||||||
|
{ "href": pathJoin(url.resourcesPath, relativePath) }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
properties.scripts?.forEach(
|
||||||
|
relativePath =>
|
||||||
|
appendScriptInHead(
|
||||||
|
{ "src": pathJoin(url.resourcesPath, relativePath) }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cx(properties.kcLoginClass)}>
|
||||||
|
|
||||||
|
<div id="kc-header" className={cx(properties.kcHeaderClass)}>
|
||||||
|
<div id="kc-header-wrapper" className={cx(properties.kcHeaderWrapperClass)}>
|
||||||
|
{t("loginTitleHtml", realm.displayNameHtml)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={cx("kcFormCardClass", displayWide && properties.kcFormCardAccountClass)}>
|
||||||
|
<header className={cx(properties.kcFormHeaderClass)}>
|
||||||
|
{
|
||||||
|
(
|
||||||
|
realm.internationalizationEnabled &&
|
||||||
|
(assert(locale !== undefined), true) &&
|
||||||
|
locale.supported.length > 1
|
||||||
|
) &&
|
||||||
|
<div id="kc-locale">
|
||||||
|
<div id="kc-locale-wrapper" className={cx(properties.kcLocaleWrapperClass)}>
|
||||||
|
<div className="kc-dropdown" id="kc-locale-dropdown">
|
||||||
|
<a href="#" id="kc-current-locale-link">
|
||||||
|
{getLanguageLabel(keycloakLanguage)}
|
||||||
|
</a>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
locale.supported.map(
|
||||||
|
({ languageTag }) =>
|
||||||
|
<li className="kc-dropdown-item">
|
||||||
|
<a href="#" onClick={onChangeLanguageClickFactory(languageTag)}>
|
||||||
|
{getLanguageLabel(languageTag)}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
(
|
||||||
|
auth !== undefined &&
|
||||||
|
auth.showUsername &&
|
||||||
|
!auth.showResetCredentials
|
||||||
|
) ?
|
||||||
|
(
|
||||||
|
displayRequiredFields ?
|
||||||
|
(
|
||||||
|
|
||||||
|
<div className={cx(properties.kcContentWrapperClass)}>
|
||||||
|
<div className={cx(properties.kcLabelWrapperClass, "subtitle")}>
|
||||||
|
<span className="subtitle">
|
||||||
|
<span className="required">*</span>
|
||||||
|
{t("requiredFields")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-10">
|
||||||
|
<h1 id="kc-page-title">{headerNode}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
:
|
||||||
|
(
|
||||||
|
|
||||||
|
<h1 id="kc-page-title">{headerNode}</h1>
|
||||||
|
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
displayRequiredFields ? (
|
||||||
|
<div className={cx(properties.kcContentWrapperClass)}>
|
||||||
|
<div className={cx(properties.kcLabelWrapperClass, "subtitle")}>
|
||||||
|
<span className="subtitle"><span className="required">*</span> {t("requiredFields")}</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-10">
|
||||||
|
{showUsernameNode}
|
||||||
|
<div className={cx(properties.kcFormGroupClass)}>
|
||||||
|
<div id="kc-username">
|
||||||
|
<label id="kc-attempted-username">{auth?.attemptedUsername}</label>
|
||||||
|
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
||||||
|
<div className="kc-login-tooltip">
|
||||||
|
<i className={cx(properties.kcResetFlowIcon)}></i>
|
||||||
|
<span className="kc-tooltip-text">{t("restartLoginTooltip")}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{showUsernameNode}
|
||||||
|
<div className={cx(properties.kcFormGroupClass)}>
|
||||||
|
<div id="kc-username">
|
||||||
|
<label id="kc-attempted-username">{auth?.attemptedUsername}</label>
|
||||||
|
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
||||||
|
<div className="kc-login-tooltip">
|
||||||
|
<i className={cx(properties.kcResetFlowIcon)}></i>
|
||||||
|
<span className="kc-tooltip-text">{t("restartLoginTooltip")}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</header>
|
||||||
|
<div id="kc-content">
|
||||||
|
<div id="kc-content-wrapper">
|
||||||
|
{/* App-initiated actions should not see warning messages about the need to complete the action during login. */}
|
||||||
|
{
|
||||||
|
(
|
||||||
|
displayMessage &&
|
||||||
|
message !== undefined &&
|
||||||
|
(
|
||||||
|
message.type !== "warning" ||
|
||||||
|
!isAppInitiatedAction
|
||||||
|
)
|
||||||
|
) &&
|
||||||
|
<div className={cx("alert", `alert-${message.type}`)}>
|
||||||
|
{message.type === "success" && <span className={cx(properties.kcFeedbackSuccessIcon)}></span>}
|
||||||
|
{message.type === "warning" && <span className={cx(properties.kcFeedbackWarningIcon)}></span>}
|
||||||
|
{message.type === "error" && <span className={cx(properties.kcFeedbackErrorIcon)}></span>}
|
||||||
|
{message.type === "info" && <span className={cx(properties.kcFeedbackInfoIcon)}></span>}
|
||||||
|
<span className="kc-feedback-text">{message.summary}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{formNode}
|
||||||
|
{
|
||||||
|
(
|
||||||
|
auth !== undefined &&
|
||||||
|
auth.showTryAnotherWayLink &&
|
||||||
|
showAnotherWayIfPresent
|
||||||
|
) &&
|
||||||
|
|
||||||
|
<form id="kc-select-try-another-way-form" action={url.loginAction} method="post" className={cx(displayWide && properties.kcContentWrapperClass)} >
|
||||||
|
<div className={cx(displayWide && [properties.kcFormSocialAccountContentClass, properties.kcFormSocialAccountClass])} >
|
||||||
|
<div className={cx(properties.kcFormGroupClass)}>
|
||||||
|
<input type="hidden" name="tryAnotherWay" value="on" />
|
||||||
|
<a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>{t("doTryAnotherWay")}</a>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
displayInfo &&
|
||||||
|
|
||||||
|
<div id="kc-info" className={cx(properties.kcSignUpClass)}>
|
||||||
|
<div id="kc-info-wrapper" className={cx(properties.kcInfoAreaWrapperClass)}>
|
||||||
|
{displayInfoNode}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div >
|
||||||
|
</div >
|
||||||
|
</div >
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
@ -1,211 +0,0 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useKeycloakThemeTranslation } from "./i18n/useKeycloakTranslation";
|
|
||||||
import { keycloakPagesContext } from "./keycloakFtlValues";
|
|
||||||
import { assert } from "evt/tools/typeSafety/assert";
|
|
||||||
import { cx } from "tss-react";
|
|
||||||
import { useKeycloakLanguage, AvailableLanguages } from "./i18n/useKeycloakLanguage";
|
|
||||||
import { getLanguageLabel } from "./i18n/getLanguageLabel";
|
|
||||||
import { useCallbackFactory } from "powerhooks";
|
|
||||||
|
|
||||||
export type Props = {
|
|
||||||
displayInfo?: boolean;
|
|
||||||
displayMessage: boolean;
|
|
||||||
displayRequiredFields: boolean;
|
|
||||||
displayWide: boolean;
|
|
||||||
showAnotherWayIfPresent: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Template(props: Props) {
|
|
||||||
|
|
||||||
const {
|
|
||||||
displayInfo = false,
|
|
||||||
displayMessage = true,
|
|
||||||
displayRequiredFields = false,
|
|
||||||
displayWide = false,
|
|
||||||
showAnotherWayIfPresent = true
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const { t } = useKeycloakThemeTranslation();
|
|
||||||
|
|
||||||
const { keycloakLanguage, setKeycloakLanguage } = useKeycloakLanguage();
|
|
||||||
|
|
||||||
const onChangeLanguageClickFactory = useCallbackFactory(
|
|
||||||
([languageTag]: [AvailableLanguages]) =>
|
|
||||||
setKeycloakLanguage(languageTag)
|
|
||||||
);
|
|
||||||
|
|
||||||
const [{ realm, locale, auth }] = useState(() => {
|
|
||||||
|
|
||||||
assert(keycloakPagesContext !== undefined);
|
|
||||||
|
|
||||||
return keycloakPagesContext;
|
|
||||||
|
|
||||||
});
|
|
||||||
//<div className="kcBodyClass"></div>
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
<div className="kcLoginClass">
|
|
||||||
<div id="kc-header" className="kcHeaderClass">
|
|
||||||
<div id="kc-header-wrapper" className="kcHeaderWrapperClass">
|
|
||||||
{t("loginTitleHtml", realm.displayNameHtml)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={cx("kcFormCardClass", displayWide && "kcFormCardAccountClass")}>
|
|
||||||
<header className="kcFormHeaderClass">
|
|
||||||
|
|
||||||
{
|
|
||||||
(
|
|
||||||
realm.internationalizationEnabled &&
|
|
||||||
(assert(locale !== undefined), true) &&
|
|
||||||
locale.supported.length > 1
|
|
||||||
) && (
|
|
||||||
<div id="kc-locale">
|
|
||||||
<div id="kc-locale-wrapper" className="kcLocaleWrapperClass">
|
|
||||||
<div className="kc-dropdown" id="kc-locale-dropdown">
|
|
||||||
<a href="#" id="kc-current-locale-link">
|
|
||||||
{getLanguageLabel(keycloakLanguage)}
|
|
||||||
</a>
|
|
||||||
<ul>
|
|
||||||
{
|
|
||||||
locale.supported.map(
|
|
||||||
({ languageTag }) =>
|
|
||||||
<li className="kc-dropdown-item">
|
|
||||||
<a href="#" onClick={onChangeLanguageClickFactory(languageTag)}>
|
|
||||||
{getLanguageLabel(languageTag)}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
(
|
|
||||||
auth !== undefined &&
|
|
||||||
auth.showUsername &&
|
|
||||||
!auth.showResetCredentials
|
|
||||||
) ?
|
|
||||||
(
|
|
||||||
displayRequiredFields ?
|
|
||||||
(
|
|
||||||
|
|
||||||
<div className="kcContentWrapperClass">
|
|
||||||
<div className="kcLabelWrapperClass subtitle">
|
|
||||||
<span className="subtitle">
|
|
||||||
<span className="required">*</span>
|
|
||||||
{t("requiredFields")}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-10">
|
|
||||||
<h1 id="kc-page-title"><#nested "header"></h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
)
|
|
||||||
:
|
|
||||||
(
|
|
||||||
|
|
||||||
<h1 id="kc-page-title"><#nested "header"></h1>
|
|
||||||
|
|
||||||
)
|
|
||||||
)
|
|
||||||
:
|
|
||||||
(
|
|
||||||
displayRequiredFields ? (
|
|
||||||
<div className="kcContentWrapperClass">
|
|
||||||
<div class="${properties.kcLabelWrapperClass!} subtitle">
|
|
||||||
<span class="subtitle"><span class="required">*</span> ${msg("requiredFields")}</span>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-10">
|
|
||||||
<#nested "show-username">
|
|
||||||
<div class="${properties.kcFormGroupClass!}">
|
|
||||||
<div id="kc-username">
|
|
||||||
<label id="kc-attempted-username">${auth.attemptedUsername}</label>
|
|
||||||
<a id="reset-login" href="${url.loginRestartFlowUrl}">
|
|
||||||
<div class="kc-login-tooltip">
|
|
||||||
<i class="${properties.kcResetFlowIcon!}"></i>
|
|
||||||
<span class="kc-tooltip-text">${msg("restartLoginTooltip")}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
|
|
||||||
<#nested "show-username">
|
|
||||||
<div class="${properties.kcFormGroupClass!}">
|
|
||||||
<div id="kc-username">
|
|
||||||
<label id="kc-attempted-username">${auth.attemptedUsername}</label>
|
|
||||||
<a id="reset-login" href="${url.loginRestartFlowUrl}">
|
|
||||||
<div class="kc-login-tooltip">
|
|
||||||
<i class="${properties.kcResetFlowIcon!}"></i>
|
|
||||||
<span class="kc-tooltip-text">${msg("restartLoginTooltip")}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</header>
|
|
||||||
<div id="kc-content">
|
|
||||||
<div id="kc-content-wrapper">
|
|
||||||
|
|
||||||
<#-- App-initiated actions should not see warning messages about the need to complete the action -->
|
|
||||||
<#-- during login. -->
|
|
||||||
<#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)>
|
|
||||||
<div class="alert alert-${message.type}">
|
|
||||||
<#if message.<span class="${properties.kcFeedbackSuccessIcon!}"></span></#if>
|
|
||||||
<#if message.<span class="${properties.kcFeedbackWarningIcon!}"></span></#if>
|
|
||||||
<#if message.<span class="${properties.kcFeedbackErrorIcon!}"></span></#if>
|
|
||||||
<#if message.<span class="${properties.kcFeedbackInfoIcon!}"></span></#if>
|
|
||||||
<span class="kc-feedback-text">${kcSanitize(message.summary) ? no_esc}</span>
|
|
||||||
</div >
|
|
||||||
</#if >
|
|
||||||
|
|
||||||
<#nested "form" >
|
|
||||||
|
|
||||||
<#if auth?has_content && auth.showTryAnotherWayLink() && showAnotherWayIfPresent >
|
|
||||||
<form id="kc-select-try-another-way-form" action="${url.loginAction}" method="post" <#if displayWide>class="${properties.kcContentWrapperClass!}"</#if> >
|
|
||||||
<div <#if displayWide>class="${properties.kcFormSocialAccountContentClass!} ${properties.kcFormSocialAccountClass!}"</#if> >
|
|
||||||
<div class="${properties.kcFormGroupClass!}">
|
|
||||||
<input type="hidden" name="tryAnotherWay" value="on" />
|
|
||||||
<a href="#" id="try-another-way" onclick="document.forms['kc-select-try-another-way-form'].submit();return false;">${msg("doTryAnotherWay")}</a>
|
|
||||||
</div>
|
|
||||||
</div >
|
|
||||||
</form >
|
|
||||||
</#if >
|
|
||||||
|
|
||||||
<#if displayInfo>
|
|
||||||
<div id="kc-info" class="${properties.kcSignUpClass!}">
|
|
||||||
<div id="kc-info-wrapper" class="${properties.kcInfoAreaWrapperClass!}">
|
|
||||||
<#nested "info">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</#if>
|
|
||||||
</div >
|
|
||||||
</div >
|
|
||||||
|
|
||||||
</div >
|
|
||||||
</div >
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
24
src/lib/tools/appendLinkInHead.ts
Normal file
24
src/lib/tools/appendLinkInHead.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
export function appendLinkInHead(
|
||||||
|
props: {
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
const { href } = props;
|
||||||
|
|
||||||
|
var link = document.createElement("link");
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
link,
|
||||||
|
{
|
||||||
|
href,
|
||||||
|
"type": "text/css",
|
||||||
|
"rel": "stylesheet",
|
||||||
|
"media": "screen,print"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
document.getElementsByTagName("head")[0].appendChild(link);
|
||||||
|
|
||||||
|
}
|
22
src/lib/tools/appendScriptInHead.ts
Normal file
22
src/lib/tools/appendScriptInHead.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
export function appendScriptInHead(
|
||||||
|
props: {
|
||||||
|
src: string;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
const { src } = props;
|
||||||
|
|
||||||
|
var script = document.createElement("script");
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
script,
|
||||||
|
{
|
||||||
|
src,
|
||||||
|
"type": "text/javascript",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
document.getElementsByTagName("head")[0].appendChild(script);
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user