mirror of
https://github.com/lukin/keywind.git
synced 2025-01-09 09:26:24 +00:00
refactor!: update components
This commit is contained in:
parent
17dedde7e2
commit
b90506a476
69 changed files with 771 additions and 714 deletions
20
README.md
20
README.md
|
@ -51,10 +51,11 @@ parent=keywind
|
|||
|
||||
### Theme
|
||||
|
||||
When you do need to customize a palette, you can configure your colors under the `colors` key in the `theme` section of `tailwind.config.js` file:
|
||||
When you do need to customize a palette, you can configure your colors under the `colors` key in the `theme` section of Tailwind config file:
|
||||
|
||||
`tailwind.config.js`
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
|
@ -70,18 +71,15 @@ Read more about Tailwind CSS configuration in the [documentation](https://tailwi
|
|||
|
||||
### Components
|
||||
|
||||
You can inherit Keywind components in your own theme. For example, to resize the primary button you should create a styled `theme/mytheme/components/button/primary.ftl` file:
|
||||
You can update Keywind components in your own child theme. For example, create a copy of the `body` component and change the background:
|
||||
|
||||
`theme/mytheme/login/components/atoms/body.ftl`
|
||||
|
||||
```
|
||||
<#macro kw component="button" rest...>
|
||||
<${component}
|
||||
class="bg-primary-600 flex justify-center px-6 py-3 relative rounded-lg text-md text-white w-full focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2 hover:bg-primary-700"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#macro kw>
|
||||
<body class="bg-primary-100">
|
||||
<#nested>
|
||||
</${component}>
|
||||
</body>
|
||||
</#macro>
|
||||
```
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/20/solid/arrow-top-right-on-square.svg -->
|
||||
<#macro kw>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M4.25 5.5C3.83579 5.5 3.5 5.83579 3.5 6.25V14.75C3.5 15.1642 3.83579 15.5 4.25 15.5H12.75C13.1642 15.5 13.5 15.1642 13.5 14.75V10.75C13.5 10.3358 13.8358 10 14.25 10C14.6642 10 15 10.3358 15 10.75V14.75C15 15.9926 13.9926 17 12.75 17H4.25C3.00736 17 2 15.9926 2 14.75V6.25C2 5.00736 3.00736 4 4.25 4H9.25C9.66421 4 10 4.33579 10 4.75C10 5.16421 9.66421 5.5 9.25 5.5H4.25Z" fill-rule="evenodd" />
|
||||
<path clip-rule="evenodd" d="M6.19385 12.7532C6.47175 13.0603 6.94603 13.0841 7.25319 12.8062L16.5 4.43999V7.25C16.5 7.66421 16.8358 8 17.25 8C17.6642 8 18 7.66421 18 7.25V2.75C18 2.33579 17.6642 2 17.25 2H12.75C12.3358 2 12 2.33579 12 2.75C12 3.16421 12.3358 3.5 12.75 3.5H15.3032L6.24682 11.6938C5.93966 11.9717 5.91595 12.446 6.19385 12.7532Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</#macro>
|
6
theme/keywind/login/assets/icons/chevron-down.ftl
Normal file
6
theme/keywind/login/assets/icons/chevron-down.ftl
Normal file
|
@ -0,0 +1,6 @@
|
|||
<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/20/solid/chevron-down.svg -->
|
||||
<#macro kw>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</#macro>
|
|
@ -1,16 +1,16 @@
|
|||
<#import "./provider/bitbucket.ftl" as bitbucketIcon>
|
||||
<#import "./provider/facebook.ftl" as facebookIcon>
|
||||
<#import "./provider/github.ftl" as githubIcon>
|
||||
<#import "./provider/gitlab.ftl" as gitlabIcon>
|
||||
<#import "./provider/google.ftl" as googleIcon>
|
||||
<#import "./provider/instagram.ftl" as instagramIcon>
|
||||
<#import "./provider/linkedin.ftl" as linkedinIcon>
|
||||
<#import "./provider/microsoft.ftl" as microsoftIcon>
|
||||
<#import "./provider/oidc.ftl" as oidcIcon>
|
||||
<#import "./provider/openshift.ftl" as openshiftIcon>
|
||||
<#import "./provider/paypal.ftl" as paypalIcon>
|
||||
<#import "./provider/stackoverflow.ftl" as stackoverflowIcon>
|
||||
<#import "./provider/twitter.ftl" as twitterIcon>
|
||||
<#import "./bitbucket.ftl" as bitbucketIcon>
|
||||
<#import "./facebook.ftl" as facebookIcon>
|
||||
<#import "./github.ftl" as githubIcon>
|
||||
<#import "./gitlab.ftl" as gitlabIcon>
|
||||
<#import "./google.ftl" as googleIcon>
|
||||
<#import "./instagram.ftl" as instagramIcon>
|
||||
<#import "./linkedin.ftl" as linkedinIcon>
|
||||
<#import "./microsoft.ftl" as microsoftIcon>
|
||||
<#import "./oidc.ftl" as oidcIcon>
|
||||
<#import "./openshift.ftl" as openshiftIcon>
|
||||
<#import "./paypal.ftl" as paypalIcon>
|
||||
<#import "./stackoverflow.ftl" as stackoverflowIcon>
|
||||
<#import "./twitter.ftl" as twitterIcon>
|
||||
|
||||
<#macro bitbucket>
|
||||
<@bitbucketIcon.kw />
|
22
theme/keywind/login/components/atoms/alert.ftl
Normal file
22
theme/keywind/login/components/atoms/alert.ftl
Normal file
|
@ -0,0 +1,22 @@
|
|||
<#macro kw color="">
|
||||
<#switch color>
|
||||
<#case "error">
|
||||
<#assign colorClass="bg-red-100 text-red-600">
|
||||
<#break>
|
||||
<#case "info">
|
||||
<#assign colorClass="bg-blue-100 text-blue-600">
|
||||
<#break>
|
||||
<#case "success">
|
||||
<#assign colorClass="bg-green-100 text-green-600">
|
||||
<#break>
|
||||
<#case "warning">
|
||||
<#assign colorClass="bg-orange-100 text-orange-600">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign colorClass="bg-blue-100 text-blue-600">
|
||||
</#switch>
|
||||
|
||||
<div class="${colorClass} p-4 rounded-lg text-sm" role="alert">
|
||||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
5
theme/keywind/login/components/atoms/body.ftl
Normal file
5
theme/keywind/login/components/atoms/body.ftl
Normal file
|
@ -0,0 +1,5 @@
|
|||
<#macro kw>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<#nested>
|
||||
</body>
|
||||
</#macro>
|
5
theme/keywind/login/components/atoms/button-group.ftl
Normal file
5
theme/keywind/login/components/atoms/button-group.ftl
Normal file
|
@ -0,0 +1,5 @@
|
|||
<#macro kw>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
33
theme/keywind/login/components/atoms/button.ftl
Normal file
33
theme/keywind/login/components/atoms/button.ftl
Normal file
|
@ -0,0 +1,33 @@
|
|||
<#macro kw color="" component="button" size="" rest...>
|
||||
<#switch color>
|
||||
<#case "primary">
|
||||
<#assign colorClass="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700">
|
||||
<#break>
|
||||
<#case "secondary">
|
||||
<#assign colorClass="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign colorClass="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700">
|
||||
</#switch>
|
||||
|
||||
<#switch size>
|
||||
<#case "medium">
|
||||
<#assign sizeClass="px-4 py-2 text-sm">
|
||||
<#break>
|
||||
<#case "small">
|
||||
<#assign sizeClass="px-2 py-1 text-xs">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign sizeClass="px-4 py-2 text-sm">
|
||||
</#switch>
|
||||
|
||||
<${component}
|
||||
class="${colorClass} ${sizeClass} flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
19
theme/keywind/login/components/atoms/card.ftl
Normal file
19
theme/keywind/login/components/atoms/card.ftl
Normal file
|
@ -0,0 +1,19 @@
|
|||
<#macro kw content="" footer="" header="">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<#if header?has_content>
|
||||
<div class="space-y-4">
|
||||
${header}
|
||||
</div>
|
||||
</#if>
|
||||
<#if content?has_content>
|
||||
<div class="space-y-4">
|
||||
${content}
|
||||
</div>
|
||||
</#if>
|
||||
<#if footer?has_content>
|
||||
<div class="space-y-4">
|
||||
${footer}
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,17 +1,19 @@
|
|||
<#macro kw name checked=false rest...>
|
||||
<#macro kw checked=false label="" name="" rest...>
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
<#if checked>checked</#if>
|
||||
|
||||
class="border-secondary-200 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50"
|
||||
id="${name}"
|
||||
name="${name}"
|
||||
type="checkbox"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<label class="block ml-2 text-secondary-900 text-sm" for="${name}">
|
||||
<#nested>
|
||||
<label class="ml-2 text-secondary-600 text-sm" for="${name}">
|
||||
${label}
|
||||
</label>
|
||||
</div>
|
||||
</#macro>
|
5
theme/keywind/login/components/atoms/container.ftl
Normal file
5
theme/keywind/login/components/atoms/container.ftl
Normal file
|
@ -0,0 +1,5 @@
|
|||
<#macro kw>
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
11
theme/keywind/login/components/atoms/form.ftl
Normal file
11
theme/keywind/login/components/atoms/form.ftl
Normal file
|
@ -0,0 +1,11 @@
|
|||
<#macro kw rest...>
|
||||
<form
|
||||
class="m-0 space-y-4"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</form>
|
||||
</#macro>
|
5
theme/keywind/login/components/atoms/heading.ftl
Normal file
5
theme/keywind/login/components/atoms/heading.ftl
Normal file
|
@ -0,0 +1,5 @@
|
|||
<#macro kw>
|
||||
<h1 class="text-center text-xl">
|
||||
<#nested>
|
||||
</h1>
|
||||
</#macro>
|
37
theme/keywind/login/components/atoms/input.ftl
Normal file
37
theme/keywind/login/components/atoms/input.ftl
Normal file
|
@ -0,0 +1,37 @@
|
|||
<#macro
|
||||
kw
|
||||
autofocus=false
|
||||
disabled=false
|
||||
invalid=false
|
||||
label=""
|
||||
message=""
|
||||
name=""
|
||||
required=true
|
||||
rest...
|
||||
>
|
||||
<div>
|
||||
<label class="sr-only" for="${name}">
|
||||
${label}
|
||||
</label>
|
||||
<input
|
||||
<#if autofocus>autofocus</#if>
|
||||
<#if disabled>disabled</#if>
|
||||
<#if required>required</#if>
|
||||
|
||||
aria-invalid="${invalid?c}"
|
||||
class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm"
|
||||
id="${name}"
|
||||
name="${name}"
|
||||
placeholder="${label}"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#if invalid?? && message??>
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
${message?no_esc}
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</#macro>
|
30
theme/keywind/login/components/atoms/link.ftl
Normal file
30
theme/keywind/login/components/atoms/link.ftl
Normal file
|
@ -0,0 +1,30 @@
|
|||
<#macro kw color="" component="a" size="" rest...>
|
||||
<#switch color>
|
||||
<#case "primary">
|
||||
<#assign colorClass="text-primary-600 hover:text-primary-500">
|
||||
<#break>
|
||||
<#case "secondary">
|
||||
<#assign colorClass="text-secondary-600 hover:text-secondary-900">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign colorClass="text-primary-600 hover:text-primary-500">
|
||||
</#switch>
|
||||
|
||||
<#switch size>
|
||||
<#case "small">
|
||||
<#assign sizeClass="text-sm">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign sizeClass="">
|
||||
</#switch>
|
||||
|
||||
<${component}
|
||||
class="<#compress>${colorClass} ${sizeClass} inline-flex</#compress>"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
|
@ -1,5 +1,5 @@
|
|||
<#macro kw>
|
||||
<div class="font-bold text-center text-2xl">
|
||||
${kcSanitize(msg("loginTitleHtml", (realm.displayNameHtml!"")))?no_esc}
|
||||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,20 +1,18 @@
|
|||
<#macro kw id tabIndex checked=false rest...>
|
||||
<#macro kw checked=false id="" label="" rest...>
|
||||
<div>
|
||||
<input
|
||||
<#if checked>checked</#if>
|
||||
|
||||
class="border-secondary-200 focus:ring-primary-600"
|
||||
id="${id}"
|
||||
type="radio"
|
||||
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<label
|
||||
class="font-medium ml-2 text-sm"
|
||||
for="${id}"
|
||||
tabindex="${tabIndex}"
|
||||
>
|
||||
<#nested>
|
||||
<label class="ml-2 text-secondary-600 text-sm" for="${id}">
|
||||
${label}
|
||||
</label>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,10 +0,0 @@
|
|||
<#macro kw component="button" rest...>
|
||||
<${component}
|
||||
class="bg-primary-600 flex justify-center px-4 py-2 relative rounded-lg text-sm text-white w-full focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2 hover:bg-primary-700"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
|
@ -1,10 +0,0 @@
|
|||
<#macro kw component="button" rest...>
|
||||
<${component}
|
||||
class="bg-secondary-100 flex justify-center px-4 py-2 relative rounded-lg text-sm text-secondary-600 w-full focus:outline-none focus:ring-2 focus:ring-secondary-600 focus:ring-offset-2 hover:bg-secondary-200 hover:text-secondary-900"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
|
@ -1,6 +0,0 @@
|
|||
<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/outline/chevron-down.svg -->
|
||||
<#macro kw>
|
||||
<svg fill="none" height="1em" stroke="currentColor" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</#macro>
|
|
@ -1,6 +0,0 @@
|
|||
<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/outline/external-link.svg -->
|
||||
<#macro kw>
|
||||
<svg fill="none" height="1em" stroke="currentColor" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
</#macro>
|
|
@ -1,23 +0,0 @@
|
|||
<#macro kw invalid name autofocus=false disabled=false message=true required=true rest...>
|
||||
<label class="sr-only" for="${name}">
|
||||
<#nested>
|
||||
</label>
|
||||
<input
|
||||
<#if autofocus>autofocus</#if>
|
||||
<#if disabled>disabled</#if>
|
||||
<#if required>required</#if>
|
||||
aria-invalid="${messagesPerField.existsError(invalid)?c}"
|
||||
class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm"
|
||||
id="${name}"
|
||||
name="${name}"
|
||||
placeholder="<#compress><#nested></#compress>"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#if message && messagesPerField.existsError(invalid)>
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
${kcSanitize(messagesPerField.getFirstError(invalid))?no_esc}
|
||||
</div>
|
||||
</#if>
|
||||
</#macro>
|
|
@ -1,22 +0,0 @@
|
|||
<#macro kw>
|
||||
<#switch message.type>
|
||||
<#case "error">
|
||||
<#assign color="bg-red-100 text-red-600">
|
||||
<#break>
|
||||
<#case "info">
|
||||
<#assign color="bg-blue-100 text-blue-600">
|
||||
<#break>
|
||||
<#case "success">
|
||||
<#assign color="bg-green-100 text-green-600">
|
||||
<#break>
|
||||
<#case "warning">
|
||||
<#assign color="bg-orange-100 text-orange-600">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign color="bg-blue-100 text-blue-600">
|
||||
</#switch>
|
||||
|
||||
<div class="${color} p-4 rounded-lg text-sm" role="alert">
|
||||
<span>${kcSanitize(message.summary)?no_esc}</span>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,10 +0,0 @@
|
|||
<#import "../button/primary.ftl" as buttonPrimary>
|
||||
|
||||
<#macro kw>
|
||||
<form action="${url.loginAction}" class="flex justify-center" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"/>
|
||||
<@buttonPrimary.kw type="submit">
|
||||
${msg("doTryAnotherWay")}
|
||||
</@buttonPrimary.kw>
|
||||
</form>
|
||||
</#macro>
|
|
@ -1,5 +0,0 @@
|
|||
<#macro kw>
|
||||
<footer class="space-y-4">
|
||||
<#nested>
|
||||
</footer>
|
||||
</#macro>
|
|
@ -1,5 +0,0 @@
|
|||
<#macro kw>
|
||||
<header class="space-y-4">
|
||||
<#nested>
|
||||
</header>
|
||||
</#macro>
|
|
@ -1,5 +0,0 @@
|
|||
<#macro kw>
|
||||
<main class="space-y-4">
|
||||
<#nested>
|
||||
</main>
|
||||
</#macro>
|
|
@ -1,5 +0,0 @@
|
|||
<#macro kw>
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,7 +0,0 @@
|
|||
<#macro kw>
|
||||
<div class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<#nested>
|
||||
</div>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,29 +0,0 @@
|
|||
<#import "../icon/chevron-down.ftl" as iconChevronDown>
|
||||
<#import "../link/secondary.ftl" as linkSecondary>
|
||||
|
||||
<#macro kw>
|
||||
<div class="relative" x-data="{open: false}">
|
||||
<@linkSecondary.kw component="button" type="button" @click="open = true">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">${locale.current}</span>
|
||||
<@iconChevronDown.kw />
|
||||
</div>
|
||||
</@linkSecondary.kw>
|
||||
<div
|
||||
class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg"
|
||||
x-cloak
|
||||
x-show="open"
|
||||
@click.away="open = false"
|
||||
>
|
||||
<#list locale.supported as locales>
|
||||
<#if locale.current != locales.label>
|
||||
<div class="px-4 py-2">
|
||||
<@linkSecondary.kw href=locales.url>
|
||||
<span class="text-sm">${locales.label}</span>
|
||||
</@linkSecondary.kw>
|
||||
</div>
|
||||
</#if>
|
||||
</#list>
|
||||
</div>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,3 +0,0 @@
|
|||
<#macro kw>
|
||||
<div class="text-secondary-600 text-sm">* ${msg("requiredFields")}</div>
|
||||
</#macro>
|
|
@ -1,3 +0,0 @@
|
|||
<#macro kw>
|
||||
<h1 class="text-center text-xl"><#nested "header"></h1>
|
||||
</#macro>
|
|
@ -1,15 +0,0 @@
|
|||
<#import "../icon/external-link.ftl" as iconExternalLink>
|
||||
<#import "../link/primary.ftl" as linkPrimary>
|
||||
|
||||
<#macro kw>
|
||||
<#nested "show-username">
|
||||
<div class="flex items-center justify-center mb-4 space-x-2">
|
||||
<b>${auth.attemptedUsername}</b>
|
||||
<@linkPrimary.kw
|
||||
href="${url.loginRestartFlowUrl}"
|
||||
title="${msg('restartLoginTooltip')}"
|
||||
>
|
||||
<@iconExternalLink.kw />
|
||||
</@linkPrimary.kw>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,10 +0,0 @@
|
|||
<#macro kw component="a" rest...>
|
||||
<${component}
|
||||
class="inline-flex text-primary-600 hover:text-primary-500"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
|
@ -1,10 +0,0 @@
|
|||
<#macro kw component="a" rest...>
|
||||
<${component}
|
||||
class="inline-flex text-secondary-600 hover:text-secondary-900"
|
||||
<#list rest as attrName, attrValue>
|
||||
${attrName}="${attrValue}"
|
||||
</#list>
|
||||
>
|
||||
<#nested>
|
||||
</${component}>
|
||||
</#macro>
|
|
@ -0,0 +1,72 @@
|
|||
<#import "/assets/providers/providers.ftl" as providerIcons>
|
||||
|
||||
<#macro kw providers=[]>
|
||||
<div class="pt-4 separate text-secondary-600 text-sm">
|
||||
${msg("identity-provider-login-label")}
|
||||
</div>
|
||||
<div class="gap-4 grid grid-cols-3">
|
||||
<#list providers as provider>
|
||||
<#switch provider.alias>
|
||||
<#case "bitbucket">
|
||||
<#assign colorClass="hover:bg-provider-bitbucket/10">
|
||||
<#break>
|
||||
<#case "facebook">
|
||||
<#assign colorClass="hover:bg-provider-facebook/10">
|
||||
<#break>
|
||||
<#case "github">
|
||||
<#assign colorClass="hover:bg-provider-github/10">
|
||||
<#break>
|
||||
<#case "gitlab">
|
||||
<#assign colorClass="hover:bg-provider-gitlab/10">
|
||||
<#break>
|
||||
<#case "google">
|
||||
<#assign colorClass="hover:bg-provider-google/10">
|
||||
<#break>
|
||||
<#case "instagram">
|
||||
<#assign colorClass="hover:bg-provider-instagram/10">
|
||||
<#break>
|
||||
<#case "linkedin">
|
||||
<#assign colorClass="hover:bg-provider-linkedin/10">
|
||||
<#break>
|
||||
<#case "microsoft">
|
||||
<#assign colorClass="hover:bg-provider-microsoft/10">
|
||||
<#break>
|
||||
<#case "oidc">
|
||||
<#assign colorClass="hover:bg-provider-oidc/10">
|
||||
<#break>
|
||||
<#case "openshift-v3">
|
||||
<#assign colorClass="hover:bg-provider-openshift/10">
|
||||
<#break>
|
||||
<#case "openshift-v4">
|
||||
<#assign colorClass="hover:bg-provider-openshift/10">
|
||||
<#break>
|
||||
<#case "paypal">
|
||||
<#assign colorClass="hover:bg-provider-paypal/10">
|
||||
<#break>
|
||||
<#case "stackoverflow">
|
||||
<#assign colorClass="hover:bg-provider-stackoverflow/10">
|
||||
<#break>
|
||||
<#case "twitter">
|
||||
<#assign colorClass="hover:bg-provider-twitter/10">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign colorClass="hover:bg-secondary-100">
|
||||
</#switch>
|
||||
|
||||
<a
|
||||
class="${colorClass} border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent"
|
||||
data-provider="${provider.alias}"
|
||||
href="${provider.loginUrl}"
|
||||
type="button"
|
||||
>
|
||||
<#if providerIcons[provider.alias]??>
|
||||
<div class="h-6 w-6">
|
||||
<@providerIcons[provider.alias] />
|
||||
</div>
|
||||
<#else>
|
||||
${provider.displayName!}
|
||||
</#if>
|
||||
</a>
|
||||
</#list>
|
||||
</div>
|
||||
</#macro>
|
29
theme/keywind/login/components/molecules/locale-provider.ftl
Normal file
29
theme/keywind/login/components/molecules/locale-provider.ftl
Normal file
|
@ -0,0 +1,29 @@
|
|||
<#import "/assets/icons/chevron-down.ftl" as icon>
|
||||
<#import "/components/atoms/link.ftl" as link>
|
||||
|
||||
<#macro kw currentLocale="" locales=[]>
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<@link.kw @click="open = true" color="secondary" component="button" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">${currentLocale}</span>
|
||||
<@icon.kw />
|
||||
</div>
|
||||
</@link.kw>
|
||||
<div
|
||||
@click.away="open = false"
|
||||
class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg"
|
||||
x-cloak
|
||||
x-show="open"
|
||||
>
|
||||
<#list locales as locale>
|
||||
<#if currentLocale != locale.label>
|
||||
<div class="px-4 py-2">
|
||||
<@link.kw color="secondary" href=locale.url size="small">
|
||||
${locale.label}
|
||||
</@link.kw>
|
||||
</div>
|
||||
</#if>
|
||||
</#list>
|
||||
</div>
|
||||
</div>
|
||||
</#macro>
|
15
theme/keywind/login/components/molecules/username.ftl
Normal file
15
theme/keywind/login/components/molecules/username.ftl
Normal file
|
@ -0,0 +1,15 @@
|
|||
<#import "/assets/icons/arrow-top-right-on-square.ftl" as icon>
|
||||
<#import "/components/atoms/link.ftl" as link>
|
||||
|
||||
<#macro kw linkHref="" linkTitle="" name="">
|
||||
<div class="flex items-center justify-center mb-4 space-x-2">
|
||||
<b>${name}</b>
|
||||
<@link.kw
|
||||
color="primary"
|
||||
href=linkHref
|
||||
title=linkTitle
|
||||
>
|
||||
<@icon.kw />
|
||||
</@link.kw>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,70 +0,0 @@
|
|||
<#import "./icon/provider.ftl" as iconProvider>
|
||||
|
||||
<#macro kw>
|
||||
<div class="pt-4 separate text-secondary-600 text-sm">${msg("identity-provider-login-label")}</div>
|
||||
<div class="gap-4 grid grid-cols-3">
|
||||
<#list social.providers as provider>
|
||||
<#switch provider.alias>
|
||||
<#case "bitbucket">
|
||||
<#assign color="hover:bg-provider-bitbucket/10">
|
||||
<#break>
|
||||
<#case "facebook">
|
||||
<#assign color="hover:bg-provider-facebook/10">
|
||||
<#break>
|
||||
<#case "github">
|
||||
<#assign color="hover:bg-provider-github/10">
|
||||
<#break>
|
||||
<#case "gitlab">
|
||||
<#assign color="hover:bg-provider-gitlab/10">
|
||||
<#break>
|
||||
<#case "google">
|
||||
<#assign color="hover:bg-provider-google/10">
|
||||
<#break>
|
||||
<#case "instagram">
|
||||
<#assign color="hover:bg-provider-instagram/10">
|
||||
<#break>
|
||||
<#case "linkedin">
|
||||
<#assign color="hover:bg-provider-linkedin/10">
|
||||
<#break>
|
||||
<#case "microsoft">
|
||||
<#assign color="hover:bg-provider-microsoft/10">
|
||||
<#break>
|
||||
<#case "oidc">
|
||||
<#assign color="hover:bg-provider-oidc/10">
|
||||
<#break>
|
||||
<#case "openshift-v3">
|
||||
<#assign color="hover:bg-provider-openshift/10">
|
||||
<#break>
|
||||
<#case "openshift-v4">
|
||||
<#assign color="hover:bg-provider-openshift/10">
|
||||
<#break>
|
||||
<#case "paypal">
|
||||
<#assign color="hover:bg-provider-paypal/10">
|
||||
<#break>
|
||||
<#case "stackoverflow">
|
||||
<#assign color="hover:bg-provider-stackoverflow/10">
|
||||
<#break>
|
||||
<#case "twitter">
|
||||
<#assign color="hover:bg-provider-twitter/10">
|
||||
<#break>
|
||||
<#default>
|
||||
<#assign color="hover:bg-secondary-100">
|
||||
</#switch>
|
||||
|
||||
<a
|
||||
class="border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent ${color}"
|
||||
data-provider="${provider.alias}"
|
||||
href="${provider.loginUrl}"
|
||||
type="button"
|
||||
>
|
||||
<#if iconProvider[provider.alias]??>
|
||||
<div class="h-6 w-6">
|
||||
<@iconProvider[provider.alias] />
|
||||
</div>
|
||||
<#else>
|
||||
${provider.displayName!}
|
||||
</#if>
|
||||
</a>
|
||||
</#list>
|
||||
</div>
|
||||
</#macro>
|
|
@ -1,4 +1,4 @@
|
|||
<#macro kw>
|
||||
<#macro kw script="">
|
||||
<title>${msg("loginTitle", (realm.displayName!""))}</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
|
@ -23,9 +23,13 @@
|
|||
</#list>
|
||||
</#if>
|
||||
|
||||
<#if script?has_content>
|
||||
<script defer src="${url.resourcesPath}/${script}" type="module"></script>
|
||||
</#if>
|
||||
|
||||
<#if properties.scripts?has_content>
|
||||
<#list properties.scripts?split(" ") as script>
|
||||
<script defer src="${url.resourcesPath}/${script}" type="text/javascript"></script>
|
||||
<script defer src="${url.resourcesPath}/${script}" type="module"></script>
|
||||
</#list>
|
||||
</#if>
|
||||
</#macro>
|
|
@ -1,10 +1,14 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/button/secondary.ftl" as buttonSecondary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/label/totp.ftl" as labelTotp>
|
||||
<#import "components/label/userdevice.ftl" as labelUserDevice>
|
||||
<#import "components/link/primary.ftl" as linkPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
<#import "components/atoms/link.ftl" as link>
|
||||
<#import "features/labels/totp.ftl" as totpLabel>
|
||||
<#import "features/labels/totp-device.ftl" as totpDeviceLabel>
|
||||
|
||||
<#assign totpLabel><@totpLabel.kw /></#assign>
|
||||
<#assign totpDeviceLabel><@totpDeviceLabel.kw /></#assign>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayMessage=!messagesPerField.existsError("totp", "userLabel")
|
||||
|
@ -24,15 +28,15 @@
|
|||
</#list>
|
||||
</ul>
|
||||
</li>
|
||||
<#if mode?? && mode = "manual">
|
||||
<li class="space-y-2">
|
||||
<#if mode?? && mode="manual">
|
||||
<li>
|
||||
<p>${msg("loginTotpManualStep2")}</p>
|
||||
<p class="font-bold text-xl">${totp.totpSecretEncoded}</p>
|
||||
</li>
|
||||
<li>
|
||||
<@linkPrimary.kw href=totp.qrUrl>
|
||||
<@link.kw color="primary" href=totp.qrUrl>
|
||||
${msg("loginTotpScanBarcode")}
|
||||
</@linkPrimary.kw>
|
||||
</@link.kw>
|
||||
</li>
|
||||
<li class="space-y-2">
|
||||
<p>${msg("loginTotpManualStep3")}</p>
|
||||
|
@ -40,9 +44,9 @@
|
|||
<li>${msg("loginTotpType")}: ${msg("loginTotp." + totp.policy.type)}</li>
|
||||
<li>${msg("loginTotpAlgorithm")}: ${totp.policy.getAlgorithmKey()}</li>
|
||||
<li>${msg("loginTotpDigits")}: ${totp.policy.digits}</li>
|
||||
<#if totp.policy.type = "totp">
|
||||
<#if totp.policy.type="totp">
|
||||
<li>${msg("loginTotpInterval")}: ${totp.policy.period}</li>
|
||||
<#elseif totp.policy.type = "hotp">
|
||||
<#elseif totp.policy.type="hotp">
|
||||
<li>${msg("loginTotpCounter")}: ${totp.policy.initialCounter}</li>
|
||||
</#if>
|
||||
</ul>
|
||||
|
@ -55,58 +59,52 @@
|
|||
class="mx-auto"
|
||||
src="data:image/png;base64, ${totp.totpSecretQrCode}"
|
||||
>
|
||||
<@linkPrimary.kw href=totp.manualUrl>
|
||||
<@link.kw color="primary" href=totp.manualUrl>
|
||||
${msg("loginTotpUnableToScan")}
|
||||
</@linkPrimary.kw>
|
||||
</@link.kw>
|
||||
</li>
|
||||
</#if>
|
||||
<li>${msg("loginTotpStep3")}</li>
|
||||
<li>${msg("loginTotpStep3DeviceName")}</li>
|
||||
</ol>
|
||||
<form action="${url.loginAction}" class="m-0 space-y-4" method="post">
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="off"
|
||||
autofocus=true
|
||||
invalid=["totp"]
|
||||
name="totp"
|
||||
required=false
|
||||
type="text"
|
||||
>
|
||||
<@labelTotp.kw />
|
||||
</@inputPrimary.kw>
|
||||
<input name="totpSecret" type="hidden" value="${totp.totpSecret}">
|
||||
<#if mode??>
|
||||
<input name="mode" type="hidden" value="${mode}">
|
||||
</#if>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="off"
|
||||
invalid=["userLabel"]
|
||||
name="userLabel"
|
||||
required=false
|
||||
type="text"
|
||||
>
|
||||
<@labelUserDevice.kw />
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<#if isAppInitiatedAction??>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<@buttonPrimary.kw type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@buttonPrimary.kw>
|
||||
<@buttonSecondary.kw name="cancel-aia" type="submit">
|
||||
${msg("doCancel")}
|
||||
</@buttonSecondary.kw>
|
||||
</div>
|
||||
<#else>
|
||||
<div class="pt-4">
|
||||
<@buttonPrimary.kw type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<input name="totpSecret" type="hidden" value="${totp.totpSecret}">
|
||||
<#if mode??>
|
||||
<input name="mode" type="hidden" value="${mode}">
|
||||
</#if>
|
||||
</form>
|
||||
<@input.kw
|
||||
autocomplete="off"
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("totp")
|
||||
label=totpLabel
|
||||
message=kcSanitize(messagesPerField.get("totp"))
|
||||
name="totp"
|
||||
required=false
|
||||
type="text"
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="off"
|
||||
invalid=messagesPerField.existsError("userLabel")
|
||||
label=totpDeviceLabel
|
||||
message=kcSanitize(messagesPerField.get("userLabel"))
|
||||
name="userLabel"
|
||||
required=false
|
||||
type="text"
|
||||
/>
|
||||
<@buttonGroup.kw>
|
||||
<#if isAppInitiatedAction??>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
<@button.kw color="secondary" name="cancel-aia" type="submit" value="true">
|
||||
${msg("doCancel")}
|
||||
</@button.kw>
|
||||
<#else>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
</#if>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
|
||||
<@layout.registrationLayout; section>
|
||||
<#if section="header">
|
||||
${msg("confirmLinkIdpTitle")}
|
||||
<#elseif section="form">
|
||||
<form action="${url.loginAction}" class="m-0 space-y-4" method="post">
|
||||
<div>
|
||||
<@buttonPrimary.kw name="submitAction" type="submit" value="updateProfile">
|
||||
${msg("confirmLinkIdpReviewProfile")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@buttonPrimary.kw name="submitAction" type="submit" value="linkAccount">
|
||||
${msg("confirmLinkIdpContinue", idpDisplayName)}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<@button.kw color="primary" name="submitAction" type="submit" value="updateProfile">
|
||||
${msg("confirmLinkIdpReviewProfile")}
|
||||
</@button.kw>
|
||||
<@button.kw color="primary" name="submitAction" type="submit" value="linkAccount">
|
||||
${msg("confirmLinkIdpContinue", idpDisplayName)}
|
||||
</@button.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/button/secondary.ftl" as buttonSecondary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
|
||||
<@layout.registrationLayout; section>
|
||||
<#if section="header">
|
||||
|
@ -46,16 +47,16 @@
|
|||
</#if>
|
||||
</h3>
|
||||
</#if>
|
||||
<form action="${url.oauthAction}" class="m-0 space-y-4" method="POST">
|
||||
<@form.kw action=url.oauthAction method="post">
|
||||
<input name="code" type="hidden" value="${oauth.code}">
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<@buttonPrimary.kw name="accept" type="submit">
|
||||
<@buttonGroup.kw>
|
||||
<@button.kw color="primary" name="accept" type="submit">
|
||||
${msg("doYes")}
|
||||
</@buttonPrimary.kw>
|
||||
<@buttonSecondary.kw name="cancel" type="submit">
|
||||
</@button.kw>
|
||||
<@button.kw color="secondary" name="cancel" type="submit">
|
||||
${msg("doNo")}
|
||||
</@buttonSecondary.kw>
|
||||
</div>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/label/totp.ftl" as labelTotp>
|
||||
<#import "components/link/secondary.ftl" as linkSecondary>
|
||||
<#import "components/radio/primary.ftl" as radioPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
<#import "components/atoms/radio.ftl" as radio>
|
||||
<#import "features/labels/totp.ftl" as totpLabel>
|
||||
|
||||
<#assign totpLabel><@totpLabel.kw /></#assign>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayMessage=!messagesPerField.existsError("totp")
|
||||
|
@ -13,45 +16,35 @@
|
|||
<#if section="header">
|
||||
${msg("doLogIn")}
|
||||
<#elseif section="form">
|
||||
<form
|
||||
action="${url.loginAction}"
|
||||
class="m-0 space-y-4"
|
||||
method="post"
|
||||
>
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<#if otpLogin.userOtpCredentials?size gt 1>
|
||||
<div class="flex items-center space-x-4">
|
||||
<#list otpLogin.userOtpCredentials as otpCredential>
|
||||
<@radioPrimary.kw
|
||||
<@radio.kw
|
||||
checked=(otpCredential.id == otpLogin.selectedCredentialId)
|
||||
id="kw-otp-credential-${otpCredential?index}"
|
||||
label=otpCredential.userLabel
|
||||
name="selectedCredentialId"
|
||||
tabIndex="${otpCredential?index}"
|
||||
value="${otpCredential.id}"
|
||||
>
|
||||
${otpCredential.userLabel}
|
||||
</@radioPrimary.kw>
|
||||
tabindex=otpCredential?index
|
||||
value=otpCredential.id
|
||||
/>
|
||||
</#list>
|
||||
</div>
|
||||
</#if>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="off"
|
||||
autofocus=true
|
||||
invalid=["totp"]
|
||||
name="otp"
|
||||
type="text"
|
||||
>
|
||||
<@labelTotp.kw />
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<@buttonPrimary.kw
|
||||
name="submitAction"
|
||||
type="submit"
|
||||
>
|
||||
<@input.kw
|
||||
autocomplete="off"
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("totp")
|
||||
label=totpLabel
|
||||
message=kcSanitize(messagesPerField.get("totp"))
|
||||
name="otp"
|
||||
type="text"
|
||||
/>
|
||||
<@buttonGroup.kw>
|
||||
<@button.kw color="primary" name="submitAction" type="submit">
|
||||
${msg("doLogIn")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/label/username.ftl" as labelUsername>
|
||||
<#import "components/link/secondary.ftl" as linkSecondary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
<#import "components/atoms/link.ftl" as link>
|
||||
<#import "features/labels/username.ftl" as usernameLabel>
|
||||
|
||||
<#assign usernameLabel><@usernameLabel.kw /></#assign>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayInfo=true
|
||||
|
@ -13,30 +17,28 @@
|
|||
<#if section="header">
|
||||
${msg("emailForgotTitle")}
|
||||
<#elseif section="form">
|
||||
<form action="${url.loginAction}" class="m-0 space-y-4" method="post">
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete=realm.loginWithEmailAllowed?string("email", "username")
|
||||
autofocus=true
|
||||
invalid=["username"]
|
||||
name="username"
|
||||
type="text"
|
||||
value=(auth?has_content && auth.showUsername())?then(auth.attemptedUsername, '')
|
||||
>
|
||||
<@labelUsername.kw />
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@buttonPrimary.kw type="submit">
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<@input.kw
|
||||
autocomplete=realm.loginWithEmailAllowed?string("email", "username")
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("username")
|
||||
label=usernameLabel
|
||||
message=kcSanitize(messagesPerField.get("username"))
|
||||
name="username"
|
||||
type="text"
|
||||
value=(auth?has_content && auth.showUsername())?then(auth.attemptedUsername, '')
|
||||
/>
|
||||
<@buttonGroup.kw>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
<#elseif section="info">
|
||||
${msg("emailInstruction")}
|
||||
<#elseif section="nav">
|
||||
<@linkSecondary.kw href=url.loginUrl>
|
||||
<span class="text-sm">${kcSanitize(msg("backToLogin"))?no_esc}</span>
|
||||
</@linkSecondary.kw>
|
||||
<@link.kw color="secondary" href=url.loginUrl size="small">
|
||||
${kcSanitize(msg("backToLogin"))?no_esc}
|
||||
</@link.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/checkbox.ftl" as checkbox>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayMessage=!messagesPerField.existsError("password", "password-confirm")
|
||||
|
@ -10,7 +13,7 @@
|
|||
<#if section="header">
|
||||
${msg("updatePasswordTitle")}
|
||||
<#elseif section="form">
|
||||
<form action="${url.loginAction}" class="m-0 space-y-4" method="post">
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<input
|
||||
autocomplete="username"
|
||||
name="username"
|
||||
|
@ -18,36 +21,44 @@
|
|||
value="${username}"
|
||||
>
|
||||
<input autocomplete="current-password" name="password" type="hidden">
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="new-password"
|
||||
autofocus=true
|
||||
invalid=["password", "password-confirm"]
|
||||
message=false
|
||||
name="password-new"
|
||||
type="password"
|
||||
>
|
||||
${msg("passwordNew")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="new-password"
|
||||
invalid=["password-confirm"]
|
||||
name="password-confirm"
|
||||
type="password"
|
||||
>
|
||||
${msg("passwordConfirm")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
|
||||
<#-- TODO isAppInitiatedAction -->
|
||||
|
||||
<div>
|
||||
<@buttonPrimary.kw type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
<@input.kw
|
||||
autocomplete="new-password"
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("password", "password-confirm")
|
||||
label=msg("passwordNew")
|
||||
name="password-new"
|
||||
type="password"
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="new-password"
|
||||
invalid=messagesPerField.existsError("password-confirm")
|
||||
label=msg("passwordConfirm")
|
||||
message=kcSanitize(messagesPerField.get("password-confirm"))
|
||||
name="password-confirm"
|
||||
type="password"
|
||||
/>
|
||||
<#if isAppInitiatedAction??>
|
||||
<@checkbox.kw
|
||||
checked=true
|
||||
label=msg("logoutOtherSessions")
|
||||
name="logout-sessions"
|
||||
value="on"
|
||||
/>
|
||||
</#if>
|
||||
<@buttonGroup.kw>
|
||||
<#if isAppInitiatedAction??>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
<@button.kw color="secondary" name="cancel-aia" type="submit" value="true">
|
||||
${msg("doCancel")}
|
||||
</@button.kw>
|
||||
<#else>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
</#if>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayMessage=!messagesPerField.existsError("email", "firstName", "lastName", "username")
|
||||
|
@ -10,62 +12,60 @@
|
|||
<#if section="header">
|
||||
${msg("loginProfileTitle")}
|
||||
<#elseif section="form">
|
||||
<form action="${url.loginAction}" class="m-0 space-y-4" method="post">
|
||||
<@form.kw action=url.loginAction method="post">
|
||||
<#if user.editUsernameAllowed>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="username"
|
||||
autofocus=true
|
||||
invalid=["username"]
|
||||
name="username"
|
||||
type="text"
|
||||
value=(user.username)!''
|
||||
>
|
||||
${msg("username")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<@input.kw
|
||||
autocomplete="username"
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("username")
|
||||
label=msg("username")
|
||||
message=kcSanitize(messagesPerField.get("username"))
|
||||
name="username"
|
||||
type="text"
|
||||
value=(user.username)!''
|
||||
/>
|
||||
</#if>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="email"
|
||||
invalid=["email"]
|
||||
name="email"
|
||||
type="email"
|
||||
value=(user.email)!''
|
||||
>
|
||||
${msg("email")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="given-name"
|
||||
invalid=["firstName"]
|
||||
name="firstName"
|
||||
type="text"
|
||||
value=(user.firstName)!''
|
||||
>
|
||||
${msg("firstName")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="family-name"
|
||||
invalid=["lastName"]
|
||||
name="lastName"
|
||||
type="text"
|
||||
value=(user.lastName)!''
|
||||
>
|
||||
${msg("lastName")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
|
||||
<#-- TODO isAppInitiatedAction -->
|
||||
|
||||
<div>
|
||||
<@buttonPrimary.kw type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
<@input.kw
|
||||
autocomplete="email"
|
||||
invalid=messagesPerField.existsError("email")
|
||||
label=msg("email")
|
||||
message=kcSanitize(messagesPerField.get("email"))
|
||||
name="email"
|
||||
type="email"
|
||||
value=(user.email)!''
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="given-name"
|
||||
invalid=messagesPerField.existsError("firstName")
|
||||
label=msg("firstName")
|
||||
message=kcSanitize(messagesPerField.get("firstName"))
|
||||
name="firstName"
|
||||
type="text"
|
||||
value=(user.firstName)!''
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="family-name"
|
||||
invalid=messagesPerField.existsError("lastName")
|
||||
label=msg("lastName")
|
||||
message=kcSanitize(messagesPerField.get("lastName"))
|
||||
name="lastName"
|
||||
type="text"
|
||||
value=(user.lastName)!''
|
||||
/>
|
||||
<@buttonGroup.kw>
|
||||
<#if isAppInitiatedAction??>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
<@button.kw color="secondary" name="cancel-aia" type="submit" value="true">
|
||||
${msg("doCancel")}
|
||||
</@button.kw>
|
||||
<#else>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doSubmit")}
|
||||
</@button.kw>
|
||||
</#if>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/provider.ftl" as provider>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/checkbox/primary.ftl" as checkboxPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/label/username.ftl" as labelUsername>
|
||||
<#import "components/link/primary.ftl" as linkPrimary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/checkbox.ftl" as checkbox>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
<#import "components/atoms/link.ftl" as link>
|
||||
<#import "components/molecules/identity-provider.ftl" as identityProvider>
|
||||
<#import "features/labels/username.ftl" as usernameLabel>
|
||||
|
||||
<#assign usernameLabel><@usernameLabel.kw /></#assign>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??
|
||||
|
@ -16,9 +20,8 @@
|
|||
${msg("loginAccountTitle")}
|
||||
<#elseif section="form">
|
||||
<#if realm.password>
|
||||
<form
|
||||
action="${url.loginAction}"
|
||||
class="m-0 space-y-4"
|
||||
<@form.kw
|
||||
action=url.loginAction
|
||||
method="post"
|
||||
onsubmit="login.disabled = true; return true;"
|
||||
>
|
||||
|
@ -27,58 +30,56 @@
|
|||
type="hidden"
|
||||
value="<#if auth.selectedCredential?has_content>${auth.selectedCredential}</#if>"
|
||||
>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete=realm.loginWithEmailAllowed?string("email", "username")
|
||||
autofocus=true
|
||||
disabled=usernameEditDisabled??
|
||||
invalid=["username", "password"]
|
||||
name="username"
|
||||
type="text"
|
||||
value=(login.username)!''
|
||||
>
|
||||
<@labelUsername.kw />
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
invalid=["username", "password"]
|
||||
message=false
|
||||
name="password"
|
||||
type="password"
|
||||
>
|
||||
${msg("password")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<#if realm.rememberMe && !usernameEditDisabled??>
|
||||
<@checkboxPrimary.kw checked=login.rememberMe?? name="rememberMe">
|
||||
${msg("rememberMe")}
|
||||
</@checkboxPrimary.kw>
|
||||
</#if>
|
||||
<#if realm.resetPasswordAllowed>
|
||||
<@linkPrimary.kw href=url.loginResetCredentialsUrl>
|
||||
<span class="text-sm">${msg("doForgotPassword")}</span>
|
||||
</@linkPrimary.kw>
|
||||
</#if>
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<@buttonPrimary.kw name="login" type="submit">
|
||||
<@input.kw
|
||||
autocomplete=realm.loginWithEmailAllowed?string("email", "username")
|
||||
autofocus=true
|
||||
disabled=usernameEditDisabled??
|
||||
invalid=messagesPerField.existsError("username", "password")
|
||||
label=usernameLabel
|
||||
message=kcSanitize(messagesPerField.getFirstError("username", "password"))
|
||||
name="username"
|
||||
type="text"
|
||||
value=(login.username)!''
|
||||
/>
|
||||
<@input.kw
|
||||
invalid=messagesPerField.existsError("username", "password")
|
||||
label=msg("password")
|
||||
name="password"
|
||||
type="password"
|
||||
/>
|
||||
<#if realm.rememberMe && !usernameEditDisabled?? || realm.resetPasswordAllowed>
|
||||
<div class="flex items-center justify-between">
|
||||
<#if realm.rememberMe && !usernameEditDisabled??>
|
||||
<@checkbox.kw
|
||||
checked=login.rememberMe??
|
||||
label=msg("rememberMe")
|
||||
name="rememberMe"
|
||||
/>
|
||||
</#if>
|
||||
<#if realm.resetPasswordAllowed>
|
||||
<@link.kw color="primary" href=url.loginResetCredentialsUrl size="small">
|
||||
${msg("doForgotPassword")}
|
||||
</@link.kw>
|
||||
</#if>
|
||||
</div>
|
||||
</#if>
|
||||
<@buttonGroup.kw>
|
||||
<@button.kw color="primary" name="login" type="submit">
|
||||
${msg("doLogIn")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
</#if>
|
||||
<#if realm.password && social.providers??>
|
||||
<@provider.kw />
|
||||
<@identityProvider.kw providers=social.providers />
|
||||
</#if>
|
||||
<#elseif section="info">
|
||||
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
|
||||
<div class="text-center">
|
||||
${msg("noAccount")}
|
||||
<@linkPrimary.kw href=url.registrationUrl>
|
||||
<@link.kw color="primary" href=url.registrationUrl>
|
||||
${msg("doRegister")}
|
||||
</@linkPrimary.kw>
|
||||
</@link.kw>
|
||||
</div>
|
||||
</#if>
|
||||
</#if>
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/link/secondary.ftl" as linkSecondary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/link.ftl" as link>
|
||||
|
||||
<@layout.registrationLayout; section>
|
||||
<#if section = "header">
|
||||
<#if section="header">
|
||||
${msg("logoutConfirmTitle")}
|
||||
<#elseif section = "form">
|
||||
<#elseif section="form">
|
||||
<p>${msg("logoutConfirmHeader")}</p>
|
||||
<form action="${url.logoutConfirmAction}" class="m-0 space-y-4" method="post">
|
||||
<@form.kw action=url.logoutConfirmAction method="post">
|
||||
<input name="session_code" type="hidden" value="${logoutConfirm.code}">
|
||||
<@buttonPrimary.kw name="confirmLogout" type="submit" value="${msg('doLogout')}">
|
||||
<@button.kw color="primary" name="confirmLogout" type="submit" value=msg('doLogout')>
|
||||
${msg("doLogout")}
|
||||
</@buttonPrimary.kw>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@form.kw>
|
||||
<#if !logoutConfirm.skipLink>
|
||||
<#if (client.baseUrl)?has_content>
|
||||
<@linkSecondary.kw href=client.baseUrl>
|
||||
<span class="text-sm">${kcSanitize(msg("backToApplication"))?no_esc}</span>
|
||||
</@linkSecondary.kw>
|
||||
<@link.kw color="secondary" href=client.baseUrl size="small">
|
||||
${kcSanitize(msg("backToApplication"))?no_esc}
|
||||
</@link.kw>
|
||||
</#if>
|
||||
</#if>
|
||||
</#if>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<#import "template.ftl" as layout>
|
||||
<#import "components/button/primary.ftl" as buttonPrimary>
|
||||
<#import "components/input/primary.ftl" as inputPrimary>
|
||||
<#import "components/link/secondary.ftl" as linkSecondary>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/button-group.ftl" as buttonGroup>
|
||||
<#import "components/atoms/form.ftl" as form>
|
||||
<#import "components/atoms/input.ftl" as input>
|
||||
<#import "components/atoms/link.ftl" as link>
|
||||
|
||||
<@layout.registrationLayout
|
||||
displayMessage=!messagesPerField.existsError("firstName", "lastName", "email", "username", "password", "password-confirm")
|
||||
|
@ -11,90 +13,76 @@
|
|||
<#if section="header">
|
||||
${msg("registerTitle")}
|
||||
<#elseif section="form">
|
||||
<form action="${url.registrationAction}" class="m-0 space-y-4" method="post">
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="given-name"
|
||||
autofocus=true
|
||||
invalid=["firstName"]
|
||||
name="firstName"
|
||||
type="text"
|
||||
value=(register.formData.firstName)!''
|
||||
>
|
||||
${msg("firstName")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="family-name"
|
||||
invalid=["lastName"]
|
||||
name="lastName"
|
||||
type="text"
|
||||
value=(register.formData.lastName)!''
|
||||
>
|
||||
${msg("lastName")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="email"
|
||||
invalid=["email"]
|
||||
name="email"
|
||||
type="email"
|
||||
value=(register.formData.email)!''
|
||||
>
|
||||
${msg("email")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<@form.kw action=url.registrationAction method="post">
|
||||
<@input.kw
|
||||
autocomplete="given-name"
|
||||
autofocus=true
|
||||
invalid=messagesPerField.existsError("firstName")
|
||||
label=msg("firstName")
|
||||
message=kcSanitize(messagesPerField.get("firstName"))
|
||||
name="firstName"
|
||||
type="text"
|
||||
value=(register.formData.firstName)!''
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="family-name"
|
||||
invalid=messagesPerField.existsError("lastName")
|
||||
label=msg("lastName")
|
||||
message=kcSanitize(messagesPerField.get("lastName"))
|
||||
name="lastName"
|
||||
type="text"
|
||||
value=(register.formData.lastName)!''
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="email"
|
||||
invalid=messagesPerField.existsError("email")
|
||||
label=msg("email")
|
||||
message=kcSanitize(messagesPerField.get("email"))
|
||||
name="email"
|
||||
type="email"
|
||||
value=(register.formData.email)!''
|
||||
/>
|
||||
<#if !realm.registrationEmailAsUsername>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="username"
|
||||
invalid=["username"]
|
||||
name="username"
|
||||
type="text"
|
||||
value=(register.formData.username)!''
|
||||
>
|
||||
${msg("username")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<@input.kw
|
||||
autocomplete="username"
|
||||
invalid=messagesPerField.existsError("username")
|
||||
label=msg("username")
|
||||
message=kcSanitize(messagesPerField.get("username"))
|
||||
name="username"
|
||||
type="text"
|
||||
value=(register.formData.username)!''
|
||||
/>
|
||||
</#if>
|
||||
<#if passwordRequired??>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="new-password"
|
||||
invalid=["password", "password-confirm"]
|
||||
name="password"
|
||||
type="password"
|
||||
>
|
||||
${msg("password")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<div>
|
||||
<@inputPrimary.kw
|
||||
autocomplete="new-password"
|
||||
invalid=["password-confirm"]
|
||||
name="password-confirm"
|
||||
type="password"
|
||||
>
|
||||
${msg("passwordConfirm")}
|
||||
</@inputPrimary.kw>
|
||||
</div>
|
||||
<@input.kw
|
||||
autocomplete="new-password"
|
||||
invalid=messagesPerField.existsError("password", "password-confirm")
|
||||
label=msg("password")
|
||||
message=kcSanitize(messagesPerField.getFirstError("password", "password-confirm"))
|
||||
name="password"
|
||||
type="password"
|
||||
/>
|
||||
<@input.kw
|
||||
autocomplete="new-password"
|
||||
invalid=messagesPerField.existsError("password-confirm")
|
||||
label=msg("passwordConfirm")
|
||||
message=kcSanitize(messagesPerField.get("password-confirm"))
|
||||
name="password-confirm"
|
||||
type="password"
|
||||
/>
|
||||
</#if>
|
||||
<#if recaptchaRequired??>
|
||||
<div>
|
||||
<div class="g-recaptcha" data-sitekey="${recaptchaSiteKey}" data-size="compact"></div>
|
||||
</div>
|
||||
<div class="g-recaptcha" data-sitekey="${recaptchaSiteKey}" data-size="compact"></div>
|
||||
</#if>
|
||||
<div>
|
||||
<@buttonPrimary.kw type="submit">
|
||||
<@buttonGroup.kw>
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doRegister")}
|
||||
</@buttonPrimary.kw>
|
||||
</div>
|
||||
</form>
|
||||
</@button.kw>
|
||||
</@buttonGroup.kw>
|
||||
</@form.kw>
|
||||
<#elseif section="nav">
|
||||
<@linkSecondary.kw href=url.loginUrl>
|
||||
<span class="text-sm">${kcSanitize(msg("backToLogin"))?no_esc}</span>
|
||||
</@linkSecondary.kw>
|
||||
<@link.kw color="secondary" href=url.loginUrl size="small">
|
||||
${kcSanitize(msg("backToLogin"))?no_esc}
|
||||
</@link.kw>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
|
|
2
theme/keywind/login/resources/dist/index.css
vendored
2
theme/keywind/login/resources/dist/index.css
vendored
File diff suppressed because one or more lines are too long
|
@ -1,67 +1,83 @@
|
|||
<#import "components/document.ftl" as document>
|
||||
<#import "components/layout/alerts.ftl" as alerts>
|
||||
<#import "components/layout/another-way.ftl" as anotherWay>
|
||||
<#import "components/layout/card.ftl" as card>
|
||||
<#import "components/layout/card-footer.ftl" as cardFooter>
|
||||
<#import "components/layout/card-header.ftl" as cardHeader>
|
||||
<#import "components/layout/card-main.ftl" as cardMain>
|
||||
<#import "components/layout/container.ftl" as container>
|
||||
<#import "components/layout/locales.ftl" as locales>
|
||||
<#import "components/layout/nav.ftl" as nav>
|
||||
<#import "components/layout/required-fields.ftl" as requiredFields>
|
||||
<#import "components/layout/title.ftl" as title>
|
||||
<#import "components/layout/subtitle.ftl" as subtitle>
|
||||
<#import "components/layout/username.ftl" as username>
|
||||
<#import "document.ftl" as document>
|
||||
<#import "components/atoms/alert.ftl" as alert>
|
||||
<#import "components/atoms/body.ftl" as body>
|
||||
<#import "components/atoms/button.ftl" as button>
|
||||
<#import "components/atoms/card.ftl" as card>
|
||||
<#import "components/atoms/container.ftl" as container>
|
||||
<#import "components/atoms/heading.ftl" as heading>
|
||||
<#import "components/atoms/logo.ftl" as logo>
|
||||
<#import "components/atoms/nav.ftl" as nav>
|
||||
<#import "components/molecules/locale-provider.ftl" as localeProvider>
|
||||
<#import "components/molecules/username.ftl" as username>
|
||||
|
||||
<#macro
|
||||
registrationLayout
|
||||
displayInfo=false
|
||||
displayMessage=true
|
||||
displayRequiredFields=false
|
||||
script=""
|
||||
showAnotherWayIfPresent=true
|
||||
>
|
||||
<#assign cardHeader>
|
||||
<@logo.kw>
|
||||
${kcSanitize(msg("loginTitleHtml", (realm.displayNameHtml!"")))?no_esc}
|
||||
</@logo.kw>
|
||||
<#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
|
||||
<@heading.kw>
|
||||
<#nested "header">
|
||||
</@heading.kw>
|
||||
<#else>
|
||||
<#nested "show-username">
|
||||
<@username.kw
|
||||
linkHref=url.loginRestartFlowUrl
|
||||
linkTitle=msg("restartLoginTooltip")
|
||||
name=auth.attemptedUsername
|
||||
/>
|
||||
</#if>
|
||||
</#assign>
|
||||
|
||||
<#assign cardContent>
|
||||
<#if displayMessage && message?has_content && (message.type != "warning" || !isAppInitiatedAction??)>
|
||||
<@alert.kw color=message.type>
|
||||
${kcSanitize(message.summary)?no_esc}
|
||||
</@alert.kw>
|
||||
</#if>
|
||||
<#nested "form">
|
||||
<#if displayRequiredFields>
|
||||
<p class="text-secondary-600 text-sm">
|
||||
* ${msg("requiredFields")}
|
||||
</p>
|
||||
</#if>
|
||||
<#if auth?has_content && auth.showTryAnotherWayLink() && showAnotherWayIfPresent>
|
||||
<form action="${url.loginAction}" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on" />
|
||||
<@button.kw color="primary" type="submit">
|
||||
${msg("doTryAnotherWay")}
|
||||
</@button.kw>
|
||||
</form>
|
||||
</#if>
|
||||
</#assign>
|
||||
|
||||
<#assign cardFooter>
|
||||
<#if displayInfo>
|
||||
<#nested "info">
|
||||
</#if>
|
||||
</#assign>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<@document.kw />
|
||||
<@document.kw script=script />
|
||||
</head>
|
||||
<body>
|
||||
<@body.kw>
|
||||
<@container.kw>
|
||||
<@card.kw>
|
||||
<@cardHeader.kw>
|
||||
<@title.kw />
|
||||
<#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
|
||||
<@subtitle.kw>
|
||||
<#nested "header">
|
||||
</@subtitle.kw>
|
||||
<#else>
|
||||
<@username.kw />
|
||||
</#if>
|
||||
</@cardHeader.kw>
|
||||
<@cardMain.kw>
|
||||
<#if displayMessage && message?has_content && (message.type != "warning" || !isAppInitiatedAction??)>
|
||||
<@alerts.kw />
|
||||
</#if>
|
||||
<#nested "form">
|
||||
<#if displayRequiredFields>
|
||||
<@requiredFields.kw />
|
||||
</#if>
|
||||
<#if auth?has_content && auth.showTryAnotherWayLink() && showAnotherWayIfPresent>
|
||||
<@anotherWay.kw />
|
||||
</#if>
|
||||
</@cardMain.kw>
|
||||
<#if displayInfo>
|
||||
<@cardFooter.kw>
|
||||
<#nested "info">
|
||||
</@cardFooter.kw>
|
||||
</#if>
|
||||
</@card.kw>
|
||||
<@card.kw content=cardContent footer=cardFooter header=cardHeader />
|
||||
<@nav.kw>
|
||||
<#nested "nav">
|
||||
<#if realm.internationalizationEnabled && locale.supported?size gt 1>
|
||||
<@locales.kw />
|
||||
<@localeProvider.kw currentLocale=locale.current locales=locale.supported />
|
||||
</#if>
|
||||
</@nav.kw>
|
||||
</@container.kw>
|
||||
</body>
|
||||
</@body.kw>
|
||||
</html>
|
||||
</#macro>
|
||||
|
|
Loading…
Reference in a new issue