first commit
This commit is contained in:
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/node_modules
|
||||||
|
/carbon
|
||||||
|
.sonarlint
|
||||||
|
.idea
|
||||||
|
.docker-compose
|
||||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM node:10 as node
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build:prod
|
||||||
|
|
||||||
|
FROM busybox
|
||||||
|
COPY --from=node /usr/src/app/carbon /carbon
|
||||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Carbon theme for the keycloak
|
||||||
|
|
||||||
|
[Carbon Design](https://carbondesignsystem.com/) for the [keycloak](https://www.keycloak.org)
|
||||||
|
|
||||||
|
Special thanks for reference [GOV.UK](https://github.com/UKHomeOffice/keycloak-theme-govuk).
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
### Login Page
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Login
|
||||||
|
- [x] Login
|
||||||
|
- [x] Register
|
||||||
|
- [x] Reset password
|
||||||
|
- [ ] TOTP
|
||||||
|
- [ ] OAuth Grant
|
||||||
|
- [ ] Config TOTP
|
||||||
|
- [ ] Account
|
||||||
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
version: '3.6'
|
||||||
|
services:
|
||||||
|
keycloak:
|
||||||
|
image: jboss/keycloak:latest
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- ./carbon/:/opt/jboss/keycloak/themes/carbon/
|
||||||
|
environment:
|
||||||
|
KEYCLOAK_PASSWORD: "admin"
|
||||||
|
KEYCLOAK_USER: "admin"
|
||||||
|
PROXY_ADDRESS_FORWARDING: "true"
|
||||||
7561
package-lock.json
generated
Normal file
7561
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
57
package.json
Normal file
57
package.json
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"name": "keycloak-carbon-theme",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "WIP: Stay tune",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "webpack --config webpack.config.dev.js",
|
||||||
|
"build:prod": "webpack --env prod --config webpack.config.js",
|
||||||
|
"watch": "webpack --watch --config webpack.config.dev.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/httpsOmkar/keycloak-carbon-theme.git"
|
||||||
|
},
|
||||||
|
"author": "Omkar Yadav <httpsOmkar@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/httpsOmkar/keycloak-carbon-theme/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/httpsOmkar/keycloak-carbon-theme#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.5.4",
|
||||||
|
"@babel/preset-env": "^7.5.4",
|
||||||
|
"@types/angular": "^1.6.55",
|
||||||
|
"@types/blueimp-md5": "^2.7.0",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||||
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
|
"copy-webpack-plugin": "^5.0.3",
|
||||||
|
"css-loader": "^3.0.0",
|
||||||
|
"dotenv-webpack": "^1.7.0",
|
||||||
|
"node-sass": "^4.12.0",
|
||||||
|
"sass-loader": "^7.1.0",
|
||||||
|
"style-loader": "^0.23.1",
|
||||||
|
"terser-webpack-plugin": "^1.3.0",
|
||||||
|
"ts-loader": "^6.0.4",
|
||||||
|
"typescript": "^3.5.3",
|
||||||
|
"uglifyjs-webpack-plugin": "^2.1.3",
|
||||||
|
"webpack": "^4.35.3",
|
||||||
|
"webpack-cli": "^3.3.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"angular": "^1.7.8",
|
||||||
|
"angular-cookies": "^1.7.8",
|
||||||
|
"angular-resource": "^1.7.8",
|
||||||
|
"angular-route": "^1.7.8",
|
||||||
|
"angular-sanitize": "^1.7.8",
|
||||||
|
"angular-translate": "^2.18.1",
|
||||||
|
"angular-translate-loader-url": "^2.18.1",
|
||||||
|
"angular-ui-select2": "0.0.5",
|
||||||
|
"autofill-event": "0.0.1",
|
||||||
|
"blueimp-md5": "^2.11.0",
|
||||||
|
"carbon-components": "^10.3.2",
|
||||||
|
"jquery": "^3.4.1",
|
||||||
|
"select2": "^4.0.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
screenshots/login_page.png
Normal file
BIN
screenshots/login_page.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
167
src/account/account.ftl
Normal file
167
src/account/account.ftl
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.mainLayout active='account' bodyClass='user'; section>
|
||||||
|
|
||||||
|
<h1 class="GreetingsMessage NoMargin">
|
||||||
|
${msg("editAccountHtmlTitle")}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<form action="${url.accountUrl}" class="AccountForm" method="post">
|
||||||
|
|
||||||
|
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
|
||||||
|
|
||||||
|
<#if !realm.registrationEmailAsUsername>
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="username" class="bx--label">${msg("username")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('username','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('username')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="username" type="text"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('username', 'bx--text-input--invalid') }"
|
||||||
|
placeholder="${ msg('username') }" <#if !realm.editUsernameAllowed>disabled="disabled"</#if>
|
||||||
|
name="username"
|
||||||
|
value="${(account.username!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('username')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('username') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="email" class="bx--label">${msg("email")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('email','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('email')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16" height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="email" type="text"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('username', 'bx--text-input--invalid') }"
|
||||||
|
autofocus
|
||||||
|
name="email"
|
||||||
|
placeholder="${ msg('email') }"
|
||||||
|
value="${(account.email!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('email')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('email') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- <#if !realm.registrationEmailAsUsername>-->
|
||||||
|
<#-- <div class="form-group ${messagesPerField.printIfExists('username','has-error')}">-->
|
||||||
|
<#-- <div class="col-sm-2 col-md-2">-->
|
||||||
|
<#-- <label for="username" class="control-label"></label> <#if realm.editUsernameAllowed><span-->
|
||||||
|
<#-- class="required">*</span></#if>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#-- <div class="col-sm-10 col-md-10">-->
|
||||||
|
<#-- <input type="text" class="form-control" id="username" name="username" "/>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="firstName" class="bx--label">${msg("firstName")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('firstName','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('firstName')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16" height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="firstName" type="text"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('username', 'bx--text-input--invalid') }"
|
||||||
|
autofocus
|
||||||
|
name="firstName"
|
||||||
|
placeholder="${ msg('firstName') }"
|
||||||
|
value="${(account.firstName!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('firstName')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('firstName') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="lastName" class="bx--label">${msg("lastName")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('lastName','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('lastName')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16" height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="lastName" type="text"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('username', 'bx--text-input--invalid') }"
|
||||||
|
autofocus
|
||||||
|
name="lastName"
|
||||||
|
placeholder="${ msg('lastName') }"
|
||||||
|
value="${(account.lastName!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('lastName')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('lastName') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- <div class="form-group ${messagesPerField.printIfExists('firstName','has-error')}">-->
|
||||||
|
<#-- <div class="col-sm-2 col-md-2">-->
|
||||||
|
<#-- <label for="firstName" class="control-label">${msg("firstName")}</label> <span class="required">*</span>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#-- <div class="col-sm-10 col-md-10">-->
|
||||||
|
<#-- <input type="text" class="form-control" id="firstName" name="firstName"-->
|
||||||
|
<#-- value="${(account.firstName!'')}"/>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#-- <div class="form-group ${messagesPerField.printIfExists('lastName','has-error')}">-->
|
||||||
|
<#-- <div class="col-sm-2 col-md-2">-->
|
||||||
|
<#-- <label for="lastName" class="control-label">${msg("lastName")}</label> <span class="required">*</span>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#-- <div class="col-sm-10 col-md-10">-->
|
||||||
|
<#-- <input type="text" class="form-control" id="lastName" name="lastName" value="${(account.lastName!'')}"/>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<div class="DisplayFlex">
|
||||||
|
<#if url.referrerURI??>
|
||||||
|
<div>
|
||||||
|
<a role="button" class="bx--btn bx--btn--primary" type="button" href="${url.referrerURI}">
|
||||||
|
${kcSanitize(msg("backToApplication")?no_esc)}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit"
|
||||||
|
class="bx--btn bx--btn--primary"
|
||||||
|
name="submitAction" value="Save">${msg("doSave")}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit"
|
||||||
|
class="bx--btn bx--btn--tertiary"
|
||||||
|
name="submitAction" value="Cancel">${msg("doCancel")}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</@layout.mainLayout>
|
||||||
110
src/account/applications.ftl
Normal file
110
src/account/applications.ftl
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.mainLayout active='applications' bodyClass='applications'; section>
|
||||||
|
<div class="DashboardProfilePictureWrapper">
|
||||||
|
<div class="DashboardProfilePicture">
|
||||||
|
<figure class="ProfileContent">
|
||||||
|
<img alt="Profile"
|
||||||
|
style="display: none"
|
||||||
|
id="profileImage"
|
||||||
|
width="96"
|
||||||
|
height="96">
|
||||||
|
</figure>
|
||||||
|
<div class="ChangeGravatar" onclick="handleChangeAvatar()">
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 class="GreetingsMessage" style="display: none" id="greetingsMessage">
|
||||||
|
Good <span id="afterTime"></span>, <b class="Username">${ account.firstName! }</b>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<form action="${url.applicationsUrl}" method="post">
|
||||||
|
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
|
||||||
|
<input type="hidden" id="referrer" name="referrer" value="${stateChecker}">
|
||||||
|
|
||||||
|
<div class="CardList">
|
||||||
|
<#list applications.applications as application>
|
||||||
|
<#if application.effectiveUrl?has_content>
|
||||||
|
<a class="bx--tile bx--tile--clickable Card" href="${application.effectiveUrl}">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
class="Icon"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path d="M16 18H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2zM6 6v10h10V6zm20 6v4h-4v-4h4m0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2zm0 12v4h-4v-4h4m0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2zm-10 2v4h-4v-4h4m0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
<#if application.client.name?has_content>${advancedMsg(application.client.name)}<#else>${application.client.clientId}</#if>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- <table class="table table-striped table-bordered">-->
|
||||||
|
<#-- <thead>-->
|
||||||
|
<#-- <tr>-->
|
||||||
|
<#-- <td>${msg("application")}</td>-->
|
||||||
|
<#-- <td>${msg("availableRoles")}</td>-->
|
||||||
|
<#-- <td>${msg("grantedPermissions")}</td>-->
|
||||||
|
<#-- <td>${msg("additionalGrants")}</td>-->
|
||||||
|
<#-- <td>${msg("action")}</td>-->
|
||||||
|
<#-- </tr>-->
|
||||||
|
<#-- </thead>-->
|
||||||
|
|
||||||
|
<#-- <tbody>-->
|
||||||
|
<#-- <#list applications.applications as application>-->
|
||||||
|
<#-- <tr>-->
|
||||||
|
<#-- <td>-->
|
||||||
|
<#-- <#if application.effectiveUrl?has_content><a href="${application.effectiveUrl}"></#if>-->
|
||||||
|
<#-- <#if application.client.name?has_content>${advancedMsg(application.client.name)}<#else>${application.client.clientId}</#if>-->
|
||||||
|
<#-- <#if application.effectiveUrl?has_content></a></#if>-->
|
||||||
|
<#-- </td>-->
|
||||||
|
|
||||||
|
<#-- <td>-->
|
||||||
|
<#-- <#list application.realmRolesAvailable as role>-->
|
||||||
|
<#-- <#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)}</#if>-->
|
||||||
|
<#-- <#if role_has_next>, </#if>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- <#list application.resourceRolesAvailable?keys as resource>-->
|
||||||
|
<#-- <#if application.realmRolesAvailable?has_content>, </#if>-->
|
||||||
|
<#-- <#list application.resourceRolesAvailable[resource] as clientRole>-->
|
||||||
|
<#-- <#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)}</#if>-->
|
||||||
|
<#-- ${msg("inResource")}-->
|
||||||
|
<#-- <strong><#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId}</#if></strong>-->
|
||||||
|
<#-- <#if clientRole_has_next>, </#if>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- </td>-->
|
||||||
|
|
||||||
|
<#-- <td>-->
|
||||||
|
<#-- <#if application.client.consentRequired>-->
|
||||||
|
<#-- <#list application.clientScopesGranted as claim>-->
|
||||||
|
<#-- ${advancedMsg(claim)}<#if claim_has_next>, </#if>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- <#else>-->
|
||||||
|
<#-- <strong>${msg("fullAccess")}</strong>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- </td>-->
|
||||||
|
|
||||||
|
<#-- <td>-->
|
||||||
|
<#-- <#list application.additionalGrants as grant>-->
|
||||||
|
<#-- ${advancedMsg(grant)}<#if grant_has_next>, </#if>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- </td>-->
|
||||||
|
|
||||||
|
<#-- <td>-->
|
||||||
|
<#-- <#if (application.client.consentRequired && application.clientScopesGranted?has_content) || application.additionalGrants?has_content>-->
|
||||||
|
<#-- <button type='submit'-->
|
||||||
|
<#-- class='${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!}'-->
|
||||||
|
<#-- id='revoke-${application.client.clientId}' name='clientId'-->
|
||||||
|
<#-- value="${application.client.id}">${msg("revoke")}</button>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- </td>-->
|
||||||
|
<#-- </tr>-->
|
||||||
|
<#-- </#list>-->
|
||||||
|
<#-- </tbody>-->
|
||||||
|
<#-- </table>-->
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</@layout.mainLayout>
|
||||||
78
src/account/index.ts
Normal file
78
src/account/index.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import './style.scss';
|
||||||
|
import md5 from 'blueimp-md5';
|
||||||
|
|
||||||
|
function handleChangeAvatar() {
|
||||||
|
window.open(`https://en.gravatar.com/site/login`, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTime() {
|
||||||
|
const afterTime = document.getElementById('afterTime');
|
||||||
|
if (afterTime) {
|
||||||
|
afterTime.textContent = getTimeType();
|
||||||
|
}
|
||||||
|
const greetingsMessage = document.getElementById('greetingsMessage');
|
||||||
|
if (greetingsMessage) {
|
||||||
|
greetingsMessage.style.display = 'inherit';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTimeType() {
|
||||||
|
const today = new Date();
|
||||||
|
const curHr = today.getHours();
|
||||||
|
|
||||||
|
if (curHr < 12) {
|
||||||
|
return 'morning';
|
||||||
|
} else if (curHr < 18) {
|
||||||
|
return 'afternoon';
|
||||||
|
} else {
|
||||||
|
return 'evening';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
setTime();
|
||||||
|
|
||||||
|
const sideNavigation = document.getElementById('sideNavigation');
|
||||||
|
|
||||||
|
if (sideNavigation) {
|
||||||
|
const mediaQueryList = window.matchMedia('(max-width: 66rem)');
|
||||||
|
|
||||||
|
const initToggle = () => {
|
||||||
|
if (mediaQueryList.matches) {
|
||||||
|
sideNavigation.classList.remove('bx--side-nav--expanded');
|
||||||
|
} else {
|
||||||
|
sideNavigation.classList.add('bx--side-nav--expanded');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadProfile = () => {
|
||||||
|
const profileImage = document.getElementById('profileImage');
|
||||||
|
|
||||||
|
if (profileImage) {
|
||||||
|
profileImage['src'] = `https://www.gravatar.com/avatar/${ md5(window['f4erp'].user.email) }?d=retro&r=g`
|
||||||
|
profileImage.style.display = 'inherit';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initToggle();
|
||||||
|
loadProfile();
|
||||||
|
|
||||||
|
mediaQueryList.addEventListener('change', () => {
|
||||||
|
initToggle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleMenu(isOpen = false) {
|
||||||
|
const sideNavigation = document.getElementById('sideNavigation');
|
||||||
|
if (sideNavigation) {
|
||||||
|
if (sideNavigation.classList.contains('bx--side-nav--expanded') && isOpen !== true) {
|
||||||
|
sideNavigation.classList.remove('bx--side-nav--expanded');
|
||||||
|
} else {
|
||||||
|
sideNavigation.classList.add('bx--side-nav--expanded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window['toggleMenu'] = toggleMenu;
|
||||||
|
window['handleChangeAvatar'] = handleChangeAvatar;
|
||||||
116
src/account/password.ftl
Normal file
116
src/account/password.ftl
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.mainLayout active='password' bodyClass='password'; section>
|
||||||
|
|
||||||
|
<h1 class="GreetingsMessage NoMargin">
|
||||||
|
${msg("changePasswordHtmlTitle")}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<form action="${url.passwordUrl}" class="form-horizontal AccountForm" method="post">
|
||||||
|
<input type="text" id="username" name="username"
|
||||||
|
value="${(account.username!'')}"
|
||||||
|
autocomplete="username"
|
||||||
|
readonly="readonly" style="display:none;">
|
||||||
|
|
||||||
|
<#if password.passwordSet>
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="password" class="bx--label">${msg("password")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('password','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="password"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('password', 'bx--text-input--invalid') }"
|
||||||
|
type="password"
|
||||||
|
placeholder="${ msg('password') }"
|
||||||
|
name="password"
|
||||||
|
autocomplete="current-password"
|
||||||
|
value="${(account.password!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('password') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="passwordNew" class="bx--label">${msg("passwordNew")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('password','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="passwordNew"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('password', 'bx--text-input--invalid') }"
|
||||||
|
type="password"
|
||||||
|
placeholder="${ msg('password') }"
|
||||||
|
name="password-new"
|
||||||
|
autocomplete="current-password"
|
||||||
|
value="${(account.password!'')}">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('password') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bx--form-item bx--text-input-wrapper">
|
||||||
|
<label for="password-confirm" class="bx--label">${msg("passwordConfirm")}</label>
|
||||||
|
<div class="bx--text-input__field-wrapper" ${messagesPerField.printIfExists('passwordConfirm','data-invalid')}>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--text-input__invalid-icon" width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 1C4.2 1 1 4.2 1 8s3.2 7 7 7 7-3.1 7-7-3.1-7-7-7zm-.5 3h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"></path>
|
||||||
|
<path d="M7.5 4h1v5h-1V4zm.5 8.2c-.4 0-.8-.4-.8-.8s.3-.8.8-.8c.4 0 .8.4.8.8s-.4.8-.8.8z"
|
||||||
|
data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
</#if>
|
||||||
|
<input id="password-confirm"
|
||||||
|
class="bx--text-input ${ messagesPerField.printIfExists('password-confirm', 'bx--text-input--invalid') }"
|
||||||
|
type="password"
|
||||||
|
placeholder="${ msg('passwordConfirm') }"
|
||||||
|
name="password-confirm"
|
||||||
|
autocomplete="current-password">
|
||||||
|
</div>
|
||||||
|
<#if messagesPerField.exists('password')>
|
||||||
|
<div class="bx--form-requirement">${ messagesPerField.get('password') }</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- <div class="form-group">-->
|
||||||
|
<#-- <div class="col-sm-2 col-md-2">-->
|
||||||
|
<#-- <label for="password-confirm" class="control-label" class="two-lines">${msg("passwordConfirm")}</label>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#-- <div class="col-sm-10 col-md-10">-->
|
||||||
|
<#-- <input type="password" class="form-control" id="password-confirm" name="password-confirm"-->
|
||||||
|
<#-- autocomplete="new-password">-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<div class="FlexDisplay">
|
||||||
|
<button type="submit"
|
||||||
|
class="bx--btn bx--btn--primary ${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
name="submitAction" value="Save">
|
||||||
|
${msg("doSave")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</@layout.mainLayout>
|
||||||
0
src/account/resources/img/favicon.ico
Normal file
0
src/account/resources/img/favicon.ico
Normal file
33
src/account/style.scss
Normal file
33
src/account/style.scss
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
$app-page-background: #ECECEC;
|
||||||
|
$app-toolbar-background: #FFF;
|
||||||
|
|
||||||
|
@import "~carbon-components/css/carbon-components.css";
|
||||||
|
@import "style/dashboard";
|
||||||
|
@import "style/common";
|
||||||
|
@import "style/account";
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SideBar {
|
||||||
|
border-right: 1px #EEE solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PageTitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FixedNotification {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 12px;
|
||||||
|
z-index: 999999;
|
||||||
|
}
|
||||||
5
src/account/style/_account.scss
Normal file
5
src/account/style/_account.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.AccountForm {
|
||||||
|
.bx--form-item, .DisplayFlex, .FlexDisplay {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/account/style/_common.scss
Normal file
73
src/account/style/_common.scss
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
.CardList {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
|
||||||
|
@media (max-width: 399px) {
|
||||||
|
grid-template-columns: repeat(1, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 400px) and (max-width: 599px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 600px) and (max-width: 1099px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1100px) and (max-width: 1399px) {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1400px) {
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Card {
|
||||||
|
padding: 1.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
place-content: center;
|
||||||
|
min-height: 6rem;
|
||||||
|
transition: all 0.125s ease-in-out, transform 0.125s ease-in-out;
|
||||||
|
flex-direction: column;
|
||||||
|
user-select: none;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Icon {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.FlexLayout, .FlexDisplay, .DisplayFlex {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
@media (min-width: 66rem) {
|
||||||
|
> * {
|
||||||
|
margin-right: .4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 66rem) {
|
||||||
|
flex-direction: column;
|
||||||
|
> * {
|
||||||
|
margin-bottom: .8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/account/style/_dashboard.scss
Normal file
71
src/account/style/_dashboard.scss
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
.DashboardProfilePictureWrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DashboardProfilePicture {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProfileContent {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ChangeGravatar {
|
||||||
|
transition: opacity .2s ease-in-out;
|
||||||
|
background-color: rgba(32, 33, 36, 0.6);
|
||||||
|
bottom: 0;
|
||||||
|
height: 33%;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB70lEQVRoge2Yz0oCQQCHN0V8h4ylLuE9L0bQE0TQXwSFugVCnXqCLl56CDGKhDB7HgnsAUJSyujP12FWmKZVZ3RtFpwP9iLz2/l9y8zuup7ncDimBjjHnHPbvT3P8zzgeILyAN/Ake3y28DnhAIAH8CWrfKbwNsU5Qe8AhtRl8sC98BLBAWnpQc8AFmT8h27nUPpoCOBuPJxpakjEIdlM4yujkCscQJj6ANVYAfwgVRw+MFvtWBMLAVugEWN82eAepwEvoCTsSf+O085yFoX+FMeSALriPekYyAPJIdIWBW4UbILQAl4ChnbBgoh8xktpygF+khrPih/qZGrKPMtAe82BKpKrmSQPVCyVzYEdqRMkvBlM4xHICHl92wI+FJm3SA3ICfll3VDUQqkpMwk/8qKUj6tG3ICEvISyhvXhzUpv6IbilJA3cRtg2yL35t434ZATckVDLK7SvbahkAfyCjZikbuQsn4WHqQAdyG5A8R93mVFsqVD8bfmUwYtQBAOeQcCSAHFINjDWnNS+NOTSebhcBXmITGPGfE5HV6QB1Y0ji/j+Gy+S8BEJvxCvFus4x4QKUR9/l9xN1Ge8PaEJg5cyHQs11yBFofth5stxxBQ0cgrh93n4HVsQKSRBPo2u0MiA4NdMs7HA6HY674AcVRw/E55G45AAAAAElFTkSuQmCC");
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 24px 24px;
|
||||||
|
height: 100%;
|
||||||
|
opacity: .8;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.GreetingsMessage {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
|
||||||
|
&:not(.NoMargin) {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Username {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
274
src/account/template.ftl
Normal file
274
src/account/template.ftl
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<#macro mainLayout active bodyClass>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<title>${ realm.displayName } Accounts</title>
|
||||||
|
<link rel="icon" href="${url.resourcesPath}/img/favicon.ico">
|
||||||
|
<#if properties.styles?has_content>
|
||||||
|
<#list properties.styles?split(' ') as style>
|
||||||
|
<link href="${url.resourcesPath}/${style}" rel="stylesheet"/>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<#if properties.scripts?has_content>
|
||||||
|
<#list properties.scripts?split(' ') as script>
|
||||||
|
<script type="text/javascript" src="${url.resourcesPath}/${script}"></script>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.f4erp = window.f4erp || {};
|
||||||
|
window.f4erp.user = window.f4erp.user || {};
|
||||||
|
window.f4erp.user.email = '${(account.email!'')}';
|
||||||
|
window.f4erp.user.firstName = '${(account.firstName!'')}';
|
||||||
|
window.f4erp.user.lastName = '${(account.lastName!'')}';
|
||||||
|
window.f4erp.user.username = '${(account.username!'')}';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="admin-console user ${bodyClass}">
|
||||||
|
|
||||||
|
<header aria-label="Header" class="bx--header bx--header--website" role="banner">
|
||||||
|
<a class="bx--skip-to-content"
|
||||||
|
href="#main-content"
|
||||||
|
tabindex="0">
|
||||||
|
Skip to main content
|
||||||
|
</a>
|
||||||
|
<button aria-label="Open menu"
|
||||||
|
class="bx--header__action--menu bx--header__action bx--header__menu-trigger bx--header__menu-toggle bx--header__menu-toggle__hidden"
|
||||||
|
onclick="toggleMenu()"
|
||||||
|
title="Open menu" type="button">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" aria-hidden="true">
|
||||||
|
<path d="M2 14.8h16V16H2zm0-3.6h16v1.2H2zm0-3.6h16v1.2H2zM2 4h16v1.2H2z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<a class="bx--header__name" href="/">${ realm.displayName } <span>Accounts</span></a>
|
||||||
|
<div class="bx--header__global">
|
||||||
|
<#if referrer?has_content && referrer.url?has_content>
|
||||||
|
<button role="button" onclick="window.location = '${referrer.url}'"
|
||||||
|
title="${msg("backTo",referrer.name)}"
|
||||||
|
aria-label="${msg("backTo",referrer.name)}" class="bx--header__action" type="button">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path d="M15.5 15.5H18V18h-2.5zm-6.75 0h2.5V18h-2.5zM2 15.5h2.5V18H2zm13.5-6.75H18v2.5h-2.5zm-6.75 0h2.5v2.5h-2.5zM2 8.75h2.5v2.5H2zM15.5 2H18v2.5h-2.5zM8.75 2h2.5v2.5h-2.5zM2 2h2.5v2.5H2z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</#if>
|
||||||
|
<button aria-label="Logout" class="bx--header__action" type="button"
|
||||||
|
onclick="window.location = '${url.logoutUrl?esc}'">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<path d="M6 30h12a2.002 2.002 0 0 0 2-2v-3h-2v3H6V4h12v3h2V4a2.002 2.002 0 0 0-2-2H6a2.002 2.002 0 0 0-2 2v24a2.002 2.002 0 0 0 2 2z"></path>
|
||||||
|
<path d="M20.586 20.586L24.172 17H10v-2h14.172l-3.586-3.586L22 10l6 6-6 6-1.414-1.414z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<nav class="bx--side-nav__navigation bx--side-nav SideBar" aria-label="Side navigation" id="sideNavigation">
|
||||||
|
<script>
|
||||||
|
var mediaQueryList = window.matchMedia('(max-width: 66rem)');
|
||||||
|
if (mediaQueryList.matches) {
|
||||||
|
document.getElementById('sideNavigation').classList.remove('bx--side-nav--expanded');
|
||||||
|
} else {
|
||||||
|
document.getElementById('sideNavigation').classList.add('bx--side-nav--expanded');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<ul class="bx--side-nav__items">
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='applications'>active</#if>" href="${url.applicationsUrl}"
|
||||||
|
<#if active=='applications'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("applications")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='account'>active</#if>" href="${url.accountUrl}"
|
||||||
|
<#if active=='account'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("account")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<#if features.passwordUpdateSupported>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='password'>active</#if>" href="${url.passwordUrl}"
|
||||||
|
<#if active=='password'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("password")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='totp'>active</#if>" href="${url.totpUrl}"
|
||||||
|
<#if active=='totp'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("authenticator")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<#if features.identityFederation>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a href="${url.socialUrl}" class="bx--side-nav__link <#if active=='social'>active</#if>"
|
||||||
|
<#if active=='social'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("federatedIdentity")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='sessions'>active</#if>" href="${url.sessionsUrl}"
|
||||||
|
<#if active=='sessions'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("sessions")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<#if features.log>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='log'>active</#if>" href="${url.logUrl}"
|
||||||
|
<#if active=='log'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("log")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<#if realm.userManagedAccessAllowed && features.authorization>
|
||||||
|
<li class="bx--side-nav__item">
|
||||||
|
<a class="bx--side-nav__link <#if active=='authorization'>active</#if>" href="${url.resourceUrl}" <#if active=='authorization'>aria-current="page"</#if>>
|
||||||
|
<span class="bx--side-nav__link-text">${msg("myResources")}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<#if message?has_content>
|
||||||
|
|
||||||
|
<div data-notification
|
||||||
|
id="notificationSnackbar"
|
||||||
|
class="bx--inline-notification <#if message.type=='success' >bx--inline-notification--success</#if> <#if message.type=='error' >bx--inline-notification--error</#if> FixedNotification"
|
||||||
|
role="alert">
|
||||||
|
<div class="bx--inline-notification__details">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--inline-notification__icon" width="20" height="20"
|
||||||
|
viewBox="0 0 20 20" aria-hidden="true">
|
||||||
|
<path d="M10 1c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm3.5 13.5l-8-8 1-1 8 8-1 1z"></path>
|
||||||
|
<path d="M13.5 14.5l-8-8 1-1 8 8-1 1z" data-icon-path="inner-path" opacity="0"></path>
|
||||||
|
</svg>
|
||||||
|
<div class="bx--inline-notification__text-wrapper">
|
||||||
|
<p class="bx--inline-notification__title">${kcSanitize(message.summary)?no_esc}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button data-notification-btn class="bx--inline-notification__close-button" type="button" aria-label="close"
|
||||||
|
onclick="document.getElementById('notificationSnackbar').style.display = 'none'">
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--inline-notification__close-icon" width="16"
|
||||||
|
height="16" viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div class="bx--content" id="main-content">
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
This site require javascript
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<#nested "content">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#-- <aside class="bx--side-nav">-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<#-- <div class="bx-container">-->
|
||||||
|
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
<#--<#– <header class="navbar navbar-default navbar-pf navbar-main header">–>-->
|
||||||
|
<#--<#– <nav class="navbar" role="navigation">–>-->
|
||||||
|
<#--<#– <div class="navbar-header">–>-->
|
||||||
|
<#--<#– <div class="container">–>-->
|
||||||
|
<#--<#– <h1 class="navbar-title">Keycloak</h1>–>-->
|
||||||
|
<#--<#– </div>–>-->
|
||||||
|
<#--<#– </div>–>-->
|
||||||
|
<#--<#– <div class="navbar-collapse navbar-collapse-1">–>-->
|
||||||
|
<#--<#– <div class="container">–>-->
|
||||||
|
<#--<#– <ul class="nav navbar-nav navbar-utility">–>-->
|
||||||
|
<#--<#– <#if realm.internationalizationEnabled>–>-->
|
||||||
|
<#--<#– <li>–>-->
|
||||||
|
<#--<#– <div class="kc-dropdown" id="kc-locale-dropdown">–>-->
|
||||||
|
<#--<#– <a href="#" id="kc-current-locale-link">${locale.current}</a>–>-->
|
||||||
|
<#--<#– <ul>–>-->
|
||||||
|
<#--<#– <#list locale.supported as l>–>-->
|
||||||
|
<#--<#– <li class="kc-dropdown-item"><a href="${l.url}">${l.label}</a></li>–>-->
|
||||||
|
<#--<#– </#list>–>-->
|
||||||
|
<#--<#– </ul>–>-->
|
||||||
|
<#--<#– </div>–>-->
|
||||||
|
<#--<#– <li>–>-->
|
||||||
|
<#--<#– </#if>–>-->
|
||||||
|
<#--<#– <#if referrer?has_content && referrer.url?has_content>–>-->
|
||||||
|
<#-- <li><a href="${referrer.url}" id="referrer">${msg("backTo",referrer.name)}</a></li></#if>-->
|
||||||
|
<#--<#– <li><a href="${url.logoutUrl}">${msg("doSignOut")}</a></li>–>-->
|
||||||
|
<#--<#– </ul>–>-->
|
||||||
|
<#--<#– </div>–>-->
|
||||||
|
<#--<#– </div>–>-->
|
||||||
|
<#--<#– </nav>–>-->
|
||||||
|
<#--<#– </header>–>-->
|
||||||
|
|
||||||
|
<#-- <div class="container">-->
|
||||||
|
<#--<#– <div class="bs-sidebar col-sm-3">–>-->
|
||||||
|
<#--<#– <ul>–>-->
|
||||||
|
<#-- <li class="<#if active=='account'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.accountUrl}">${msg("account")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- <#if features.passwordUpdateSupported>-->
|
||||||
|
<#-- <li class="<#if active=='password'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.passwordUrl}">${msg("password")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- <li class="<#if active=='totp'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.totpUrl}">${msg("authenticator")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- <#if features.identityFederation>-->
|
||||||
|
<#-- <li class="<#if active=='social'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.socialUrl}">${msg("federatedIdentity")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- <li class="<#if active=='sessions'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.sessionsUrl}">${msg("sessions")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- <li class="<#if active=='applications'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.applicationsUrl}">${msg("applications")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- <#if features.log>-->
|
||||||
|
<#-- <li class="<#if active=='log'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.logUrl}">${msg("log")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- <#if realm.userManagedAccessAllowed && features.authorization>-->
|
||||||
|
<#-- <li class="<#if active=='authorization'>active</#if>">-->
|
||||||
|
<#-- <a href="${url.resourceUrl}">${msg("myResources")}</a>-->
|
||||||
|
<#-- </li>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
<#-- <#–<#– </ul>–>–>-->
|
||||||
|
<#-- <#–<#– </div>–>–>-->
|
||||||
|
|
||||||
|
<#-- <#– <div class="col-sm-9 content-area">–>-->
|
||||||
|
<#-- <#if message?has_content>-->
|
||||||
|
<#-- <div class="alert alert-${message.type}">-->
|
||||||
|
<#-- <#if message.type=='success' ><span class="pficon pficon-ok"></span></#if>-->
|
||||||
|
<#-- <#if message.type=='error' ><span class="pficon pficon-error-octagon"></span><span-->
|
||||||
|
<#-- class="pficon pficon-error-exclamation"></span></#if>-->
|
||||||
|
<#-- ${kcSanitize(message.summary)?no_esc}-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </#if>-->
|
||||||
|
|
||||||
|
<#-- <div class="bx--content">-->
|
||||||
|
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
<#-- </div>-->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</#macro>
|
||||||
14
src/account/theme.properties
Normal file
14
src/account/theme.properties
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
parent=base
|
||||||
|
import=common/keycloak
|
||||||
|
|
||||||
|
styles=
|
||||||
|
scripts=js/bundle.js
|
||||||
|
|
||||||
|
##### css classes for form buttons
|
||||||
|
# main class used for all buttons
|
||||||
|
kcButtonClass=btn
|
||||||
|
# classes defining priority of the button - primary or default (there is typically only one priority button for the form)
|
||||||
|
kcButtonPrimaryClass=btn-primary
|
||||||
|
kcButtonDefaultClass=btn-default
|
||||||
|
# classes defining size of the button
|
||||||
|
kcButtonLargeClass=btn-lg
|
||||||
3
src/account/utils/gravatar.ts
Normal file
3
src/account/utils/gravatar.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export function test() {
|
||||||
|
return 'test';
|
||||||
|
}
|
||||||
1
src/admin/index.ts
Normal file
1
src/admin/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import './style.scss';
|
||||||
431
src/admin/resources/css/styles.css
Normal file
431
src/admin/resources/css/styles.css
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
html,body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-inner {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-margin-top {
|
||||||
|
margin-top: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.clip {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.w-10 {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.w-15 {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.w-20 {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
th.w-25 {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.w-30 {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
th.w-35 {
|
||||||
|
width: 35%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.w-40 {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** Loading ***********/
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
padding: 2px 200px 2px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** Feedback ***********/
|
||||||
|
|
||||||
|
.feedback-aligner {
|
||||||
|
position: fixed;
|
||||||
|
top: 15px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
.feedback-aligner .alert {
|
||||||
|
border-radius: 2px;
|
||||||
|
border-width: 1px;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** On-Off Switch ***********/
|
||||||
|
|
||||||
|
.onoffswitch {
|
||||||
|
-moz-user-select: none;
|
||||||
|
height: 26px;
|
||||||
|
position: relative;
|
||||||
|
width: 62px;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-label {
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 62px;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-inner {
|
||||||
|
display: block;
|
||||||
|
margin-left: -100%;
|
||||||
|
transition: margin 0.3s ease-in 0s;
|
||||||
|
width: 200%;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-inner > span {
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
color: white;
|
||||||
|
float: left;
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 0;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-switch {
|
||||||
|
background-image: linear-gradient(top, #fafafa 0%, #ededed 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fafafa 0%, #ededed 100%);
|
||||||
|
background-image: -moz-linear-gradient(top, #fafafa 0%, #ededed 100%);
|
||||||
|
background-image: -webkit-linear-gradient(top, #fafafa 0%, #ededed 100%);
|
||||||
|
background-image: -ms-linear-gradient(top, #fafafa 0%, #ededed 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fafafa), color-stop(1, 0, #ededed));
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 2px;
|
||||||
|
bottom: 0;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 39px;
|
||||||
|
top: 0;
|
||||||
|
transition: all 0.3s ease-in 0s;
|
||||||
|
-webkit-transition: all 0.3s ease-in 0s;
|
||||||
|
width: 23px;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-inner .onoffswitch-active {
|
||||||
|
background-image: linear-gradient(top, #00a9ec 0%, #009bd3 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
|
||||||
|
background-image: -moz-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
|
||||||
|
background-image: -webkit-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
|
||||||
|
background-image: -ms-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #00a9ec), color-stop(1, 0, #009bd3));
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.onoffswitch-checkbox:disabled + .onoffswitch-label .onoffswitch-inner .onoffswitch-active,
|
||||||
|
.onoffswitch-checkbox:disabled + .onoffswitch-label .onoffswitch-inner .onoffswitch-inactive {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
color: #9d9fa1;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-inner .onoffswitch-inactive {
|
||||||
|
background: linear-gradient(#fefefe, #e8e8e8) repeat scroll 0 0 transparent;
|
||||||
|
color: #4d5258;
|
||||||
|
padding-right: 10px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.onoffswitch .onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********** Select 2 ***********/
|
||||||
|
|
||||||
|
.select2-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container-multi .select2-choices .select2-search-field {
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** html select ********/
|
||||||
|
.overflow-select {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********** New Menu ***********/
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar-pf-left{
|
||||||
|
background: #292e34;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-pf .nav-pills > li a i, .sidebar-pf .nav-pills > li a span{
|
||||||
|
color: #72767b;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.sidebar-pf .nav-pills > li > a{
|
||||||
|
color: #dbdada;
|
||||||
|
padding: 0px 20px 0 30px!important;
|
||||||
|
line-height: 30px;
|
||||||
|
border-left-width: 12px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: #292e34;
|
||||||
|
margin-left: -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-pf .nav-pills > li > a:hover{
|
||||||
|
background: #393f44;
|
||||||
|
border-color:#292e34;
|
||||||
|
border-left-color: #393f44;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-pf .nav-pills > li > a:after{
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar-pf .nav-pills > li.active > a {
|
||||||
|
color: #fff;
|
||||||
|
background: #393f44!important;
|
||||||
|
border-bottom: 1px solid #000!important;
|
||||||
|
border-top: 1px solid #000!important;
|
||||||
|
border-left-color: #39a5dc!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-pf .nav-pills > li.active a i, .sidebar-pf .nav-pills > li.active a span{
|
||||||
|
color: #39a5dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** Realm selector ***********/
|
||||||
|
|
||||||
|
.realm-selector{
|
||||||
|
color: #fff;
|
||||||
|
margin: 0 -20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-dropmenu{
|
||||||
|
display: none;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 60px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 999;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-selector:hover .realm-dropmenu{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-add{
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-selector h2{
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 60px;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin: 0;
|
||||||
|
border-bottom: 1px solid #d5d5d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-selector h2 i{
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
line-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.realm-selector ul{
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.realm-selector ul li a{
|
||||||
|
line-height: 60px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-bottom: 1px solid #d5d5d6;
|
||||||
|
line-height: 39px;
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********** Overwrites header defaults ***********/
|
||||||
|
|
||||||
|
.navbar-pf{
|
||||||
|
border-top: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-pf .navbar-brand {
|
||||||
|
padding: 0;
|
||||||
|
height: 56px;
|
||||||
|
line-height: 56px;
|
||||||
|
background-position: center center;
|
||||||
|
background-image: url('../img/keyclok-logo.png');
|
||||||
|
background-size: 148px 30px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 148px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-pf .navbar-utility > li > a{
|
||||||
|
padding: 22px 30px 23px 40px!important;
|
||||||
|
}
|
||||||
|
/* @media (min-width: 768px) */
|
||||||
|
.navbar-pf .navbar-utility li.dropdown > .dropdown-toggle .pficon-user {
|
||||||
|
top: 22px;
|
||||||
|
left:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 i {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Action cell */
|
||||||
|
.kc-action-cell {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
background-image: linear-gradient(to bottom, #fafafa 0%, #ededed 100%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-action-cell:hover {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-sorter span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Time selector */
|
||||||
|
|
||||||
|
.time-selector input {
|
||||||
|
display: inline-block;
|
||||||
|
width: 120px;
|
||||||
|
padding-right: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-selector select {
|
||||||
|
display: inline-block;
|
||||||
|
width: 80px;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_editor {
|
||||||
|
height: 600px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-button-input-file input {
|
||||||
|
float: left;
|
||||||
|
width: 73%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-button-input-file label {
|
||||||
|
float: left;
|
||||||
|
margin-left: 2%;
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.kc-authz-table-expanded {
|
||||||
|
margin-top: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-gutter > [class*='col-'] {
|
||||||
|
padding-right:0!important;
|
||||||
|
padding-left:0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-conceal {
|
||||||
|
font-family: 'text-security-disc';
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deactivation styles for user-group membership tree models */
|
||||||
|
|
||||||
|
div[tree-model] li .deactivate {
|
||||||
|
color: #4a5053;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[tree-model] li .deactivate_selected {
|
||||||
|
background-color: #dcdcdc;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search highlighting */
|
||||||
|
|
||||||
|
div[tree-model] li .highlight {
|
||||||
|
background-color: #aaddff;
|
||||||
|
}
|
||||||
BIN
src/admin/resources/img/favicon.ico
Normal file
BIN
src/admin/resources/img/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 627 B |
BIN
src/admin/resources/img/keyclok-logo.png
Normal file
BIN
src/admin/resources/img/keyclok-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
194
src/admin/resources/img/keyclok-logo.svg
Normal file
194
src/admin/resources/img/keyclok-logo.svg
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
|
||||||
|
viewBox="-145.2 359 325.4 77.2" enable-background="new -145.2 359 325.4 77.2" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||||
|
M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
|
||||||
|
c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
|
||||||
|
c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"
|
||||||
|
/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||||
|
M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
|
||||||
|
c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
|
||||||
|
v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5
|
||||||
|
c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-227.7191" y1="2220.7964" x2="-165.056" y2="2220.7964" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FDFDFD"/>
|
||||||
|
<stop offset="0.1452" style="stop-color:#F4F5F5"/>
|
||||||
|
<stop offset="0.6844" style="stop-color:#D9DBDB"/>
|
||||||
|
<stop offset="1" style="stop-color:#CFD1D1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_1_)" d="M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1
|
||||||
|
c-14-2.9-10.9,6-8.3,14c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6
|
||||||
|
c-0.5-1-0.2-2.4,0.6-3.1c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1
|
||||||
|
C-81.9,398.7-80.7,395-79.1,393.1z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="192.3203" y1="1507.8835" x2="184.0467" y2="1507.8835" gradientTransform="matrix(1 0 0 1 -302 -1102)">
|
||||||
|
<stop offset="0" style="stop-color:#E6E6E6"/>
|
||||||
|
<stop offset="1" style="stop-color:#B2B3B3"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_2_)" d="M-115,391.3c0,5,0.7,22.8,4.5,30.4l-8.7-0.2v-31.5L-115,391.3z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-200.8627" y1="2227.3811" x2="-193.8624" y2="2207.8804" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#F6F6F6"/>
|
||||||
|
<stop offset="1" style="stop-color:#B2B3B3"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_3_)" d="M-134.6,403.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
|
||||||
|
c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-18.5,7.5-15.4-5.3-21.4-9.5
|
||||||
|
c-3.2-2.2-7.7-2.1-11.2-0.8c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,390.8-136.7,391.9-134.6,403.1z"/>
|
||||||
|
<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="-117.4" y1="421.8" x2="-117.4" y2="390.6"/>
|
||||||
|
<g opacity="0.75">
|
||||||
|
<path fill="#FFFFFF" d="M-110.3,389c2.7,0,4.9,0.7,6.8,2.3c5.5,4.6,10.6,6.8,15.6,6.8c1.5,0,2.9-0.2,4.4-0.6
|
||||||
|
c-0.3,0.9-0.6,1.6-0.7,2.1c-0.4,1.4-1.6,1.8-4.4,2.4c-1.5,0.3-3.1,0.7-4.7,1.5c-1.6,0.8-2.5,2.3-2.5,3.9c0,1.5,0.9,2.8,2.4,3.5
|
||||||
|
c1.2,0.5,1.5,1.1,1.5,1.4c0,0.3-0.3,0.5-0.5,0.6c-0.6,0.3-1.2,0.4-2.1,0.4c-0.2,0-0.3,0-0.5,0c-0.2,0-0.4,0-0.5,0
|
||||||
|
c-1.6,0-3.4,0.2-5.2,1.7c-1.5,1.3-2,3.7-1.1,5.6c0.1,0.3,0.1,0.4,0.1,0.4c-0.1,0.1-0.8,0.6-2.6,0.6c-1.8,0-4.1-0.4-6.7-1.2
|
||||||
|
c-2-0.6-4.5-0.9-7.5-0.9c-3.8,0-8.4,0.6-12.6,1.5c-0.4,0.1-0.9,0.1-1.5,0.1c-1.9,0-4.2-0.5-5.7-1.6c1.7,0,3.3-0.9,4.4-2.4
|
||||||
|
c1.3-1.8,3.2-6.3,0.2-15.3l-0.1-0.2c-1.3-3.9-2.9-8.8-1.5-10.7c0.5-0.7,1.6-1.1,3.4-1.1c1.2,0,2.6,0.2,4.3,0.5
|
||||||
|
c1.8,0.4,3.6,0.6,5.4,0.6c1.9,0,3.7-0.2,5.1-0.7C-115.4,389.7-112.9,389-110.3,389 M-110.3,387c-2.7,0-5.2,0.6-7.3,1.3
|
||||||
|
c-1.3,0.4-2.9,0.6-4.6,0.6c-1.6,0-3.4-0.2-5-0.5c-1.9-0.4-3.4-0.6-4.7-0.6c-8.5,0-5.9,7.7-3.6,14.6c3.4,10.4,0.3,15.1-2.7,15.1
|
||||||
|
c-1.2,0-2.5-0.8-3.3-2.3c-1.5,5.6,4.8,7.9,9,7.9c0.7,0,1.4-0.1,2-0.2c3.7-0.8,8.1-1.5,12.2-1.5c2.5,0,4.9,0.2,6.9,0.8
|
||||||
|
c3,0.9,5.5,1.3,7.3,1.3c4,0,5.3-1.8,4.2-3.9c-0.5-1-0.2-2.4,0.6-3.1c1.4-1.2,2.7-1.3,3.9-1.3c0.3,0,0.7,0,1,0c1,0,2-0.1,3.1-0.7
|
||||||
|
c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1c0.4-1.5,1.7-5.2,3.3-7.1c-2.9,2-5.9,3-8.9,3
|
||||||
|
c-4.5,0-9.2-2.2-14.3-6.4C-104.7,387.7-107.6,387-110.3,387L-110.3,387z M-79.1,393.1L-79.1,393.1L-79.1,393.1z"/>
|
||||||
|
</g>
|
||||||
|
<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||||
|
M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
|
||||||
|
c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
|
||||||
|
c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"/>
|
||||||
|
<path fill="#034672" d="M-134.6,402.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
|
||||||
|
c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-13.1,4.8-14.1-5.5-20.1-9.7
|
||||||
|
c-3.2-2.2-9-1.9-12.5-0.6c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,389.8-136.7,390.9-134.6,402.1z"/>
|
||||||
|
<path fill="#FFFFFF" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1
|
||||||
|
c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7
|
||||||
|
c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7
|
||||||
|
c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-217.9037" y1="2215.0122" x2="-187.068" y2="2207.345" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#B8D7E9"/>
|
||||||
|
<stop offset="0.3324" style="stop-color:#CCE3F1"/>
|
||||||
|
<stop offset="0.6937" style="stop-color:#DAEBF7"/>
|
||||||
|
<stop offset="1" style="stop-color:#DFEEF9"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_4_)" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9v69.3l4.8-4.9v-34.2
|
||||||
|
c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
|
||||||
|
C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-214.9444" y1="2190.8406" x2="-206.3191" y2="2233.0925" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#F1F9FE"/>
|
||||||
|
<stop offset="0.4254" style="stop-color:#E9F5FD"/>
|
||||||
|
<stop offset="1" style="stop-color:#E4F3FD"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_5_)" d="M-122.3,362.5c-2.1,0-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
|
||||||
|
c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
|
||||||
|
v37.2l2.7,2.8h1.2l0.9-0.9L-122.3,362.5L-122.3,362.5z"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M-122.6,362.5c1.9,0.9,3.4,2,4.2,2.4
|
||||||
|
c0.8,0.5,4,2.5,5.1,3.1c0.8,0.5,3.7,2,3.7,6.3c0,1.3,0,2.8,0,3.8c0,2.8-1.6,5-4.5,6.4c-1,0.5-1.8,1.4-1.8,3.6v1.2"/>
|
||||||
|
<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1
|
||||||
|
c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4
|
||||||
|
c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2
|
||||||
|
c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
|
||||||
|
C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
|
||||||
|
<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-107.5,392.7"/>
|
||||||
|
<g>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-106.4885" y1="2203.667" x2="-106.4885" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_6_)" d="M-14.5,407.6h-11.6c0.3,2.3,1,3.9,2.1,4.7s2.9,1.2,5.5,1.2c3.4,0,7.4-0.2,12-0.7l0.9,6
|
||||||
|
c-3.3,1.6-8,2.4-14,2.4c-6,0-10.3-1.3-12.9-3.9c-2.6-2.6-3.8-6.9-3.8-12.9c0-6.3,1.2-10.7,3.7-13.2c2.5-2.5,6.7-3.8,12.6-3.8
|
||||||
|
c5.3,0,9.2,0.9,11.6,2.8c2.4,1.8,3.6,4.7,3.6,8.4c0,3-0.8,5.2-2.3,6.7C-8.5,406.8-11,407.6-14.5,407.6z M-26.3,401.8h9.1
|
||||||
|
c1.2,0,2-0.3,2.4-0.8c0.4-0.6,0.6-1.4,0.6-2.5c0-1.5-0.4-2.6-1.2-3.2c-0.8-0.6-2.2-0.9-4.3-0.9c-2.5,0-4.2,0.5-5.1,1.5
|
||||||
|
C-25.6,396.9-26.1,398.8-26.3,401.8z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-72.864" y1="2203.667" x2="-72.864" y2="2254.5503" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_7_)" d="M31,388.3l-11.4,32.6c-0.6,1.7-1.4,3.3-2.2,4.8c-0.9,1.5-2,2.9-3.4,4.3c-1.4,1.4-3.1,2.4-5.2,3
|
||||||
|
c-2.1,0.7-4.4,0.8-6.9,0.5L1,427.8c2.6-0.7,4.6-1.6,6.1-2.7c1.5-1.1,2.6-2.6,3.5-4.5l0.1-0.3H8.9c-1.6,0-2.6-0.8-3.1-2.3
|
||||||
|
l-10.5-29.8H5.6l6,20.8c0.4,1.5,0.7,3.1,1,4.8h0.8c0.1-0.5,0.3-1.3,0.7-2.4s0.5-1.9,0.7-2.4l5.9-20.8L31,388.3L31,388.3z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-41.775" y1="2203.667" x2="-41.775" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_8_)" d="M57.6,412.8l0.9,6.3c-3.3,1.4-7.5,2.1-12.4,2.1c-5.9,0-10.1-1.3-12.5-3.8
|
||||||
|
c-2.4-2.5-3.6-6.9-3.6-13.1c0-6.2,1.2-10.6,3.6-13.1c2.4-2.5,6.6-3.8,12.6-3.8c4.9,0,8.8,0.7,11.9,2l-1,6
|
||||||
|
c-4.7-0.1-7.8-0.1-9.2-0.1c-3,0-5,0.6-6.1,1.9c-1.1,1.3-1.7,3.6-1.7,7.2c0,3.5,0.6,5.9,1.7,7.2c1.1,1.3,3.1,1.9,6.1,1.9
|
||||||
|
C51.6,413.4,54.9,413.2,57.6,412.8z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="8.9715" y1="2203.667" x2="8.9715" y2="2254.553" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_9_)" d="M95,387.4c6,0,10.2,1.3,12.7,3.9c2.5,2.6,3.7,7,3.7,13.1c0,6.2-1.2,10.5-3.7,13.1
|
||||||
|
c-2.5,2.5-6.7,3.8-12.7,3.8c-6,0-10.3-1.3-12.8-3.8c-2.5-2.5-3.7-6.9-3.7-13.1c0-6.2,1.2-10.6,3.7-13.2
|
||||||
|
C84.7,388.7,89,387.4,95,387.4z M95,394.6c-2.6,0-4.3,0.6-5.1,2c-0.9,1.3-1.3,3.9-1.3,7.8c0,3.8,0.4,6.4,1.3,7.7
|
||||||
|
c0.9,1.3,2.6,2,5.1,2c2.5,0,4.2-0.7,5.1-2c0.9-1.3,1.3-3.9,1.3-7.7c0-3.9-0.4-6.5-1.3-7.8C99.2,395.3,97.5,394.6,95,394.6z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="42.879" y1="2203.667" x2="42.879" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_10_)" d="M115.9,395.5l-0.9-6.5c5.8-1,11.4-1.6,16.7-1.6c4.3,0,7.5,0.9,9.6,2.6c2,1.8,3.1,4.8,3.1,9.2v21.2
|
||||||
|
h-7.6l-1-4.9c-3.2,3.8-7.2,5.7-11.9,5.7c-3.1,0-5.6-0.8-7.6-2.4s-2.9-3.9-2.9-6.8v-3.3c0-2.6,0.9-4.6,2.6-6
|
||||||
|
c1.7-1.4,4.1-2.1,7.2-2.1h11.5v-1.4c0-1.6-0.4-2.8-1.1-3.3c-0.7-0.6-2.1-0.8-4.1-0.8C125.9,394.9,121.4,395.1,115.9,395.5z
|
||||||
|
M122.9,409.4v1.2c0,2.2,1.3,3.3,3.8,3.3c2.6,0,5.3-1,8-3.1v-4.5H126C124,406.4,122.9,407.4,122.9,409.4z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-136.063" y1="2203.667" x2="-136.063" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_11_)" d="M-43.5,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1H-46l-7.9,11.2h-3
|
||||||
|
c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9H-34L-43.5,406.1z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-16.68" y1="2203.667" x2="-16.68" y2="2254.551" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_12_)" d="M76.7,413.2h-2.6c-2.4,0-3.6-1.1-3.6-3.3v-35.1h-3l-6.6,9.4v28.2c0,2.8,0.8,5,2.5,6.5
|
||||||
|
c1.6,1.5,3.9,2.3,6.8,2.3c3.5,0,6-0.4,7.7-1.3L76.7,413.2z"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="78.107" y1="2203.667" x2="78.107" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFE"/>
|
||||||
|
<stop offset="0.4815" style="stop-color:#F2F1F1"/>
|
||||||
|
<stop offset="1" style="stop-color:#E9E7E8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_13_)" d="M170.7,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1h-10.8l-7.9,11.2h-3
|
||||||
|
c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9h10.8L170.7,406.1z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-208.281" y1="2186.001" x2="-208.281" y2="2196.1689" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#00639A"/>
|
||||||
|
<stop offset="0.2355" style="stop-color:#00578A"/>
|
||||||
|
<stop offset="0.507" style="stop-color:#004D7B"/>
|
||||||
|
<stop offset="0.7167" style="stop-color:#004773"/>
|
||||||
|
<stop offset="1" style="stop-color:#00446E"/>
|
||||||
|
</linearGradient>
|
||||||
|
<polygon fill="url(#SVGID_14_)" points="-122.3,372.4 -131.3,370.4 -132.3,374.1 -122.3,379.2 -112.2,374.1 -113.2,370.4 "/>
|
||||||
|
<polyline opacity="0.2" enable-background="new " points="-122.3,379.2 -112.2,374.1 -113.2,370.4 -122.3,372.4 "/>
|
||||||
|
<path fill="#034672" d="M-127.2,391.9c3.4,1.3,6.7,1.5,9.8,0.4l-0.3-2.2c-2.6,0.8-6.3,0.7-9.5,0.1L-127.2,391.9z"/>
|
||||||
|
<path fill="#034672" d="M-122.6,391.5c-0.4,2.8,1.9,4.7,1.9,7.6C-116.8,394.8-121.7,393.3-122.6,391.5z"/>
|
||||||
|
<path fill="#034672" d="M-122.6,391.7c-0.1,3.2-0.4,5.6-1.7,7.2C-126.8,394.2-123.7,392.6-122.6,391.7z"/>
|
||||||
|
<circle fill="#034672" cx="-122.6" cy="391.7" r="1.6"/>
|
||||||
|
|
||||||
|
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-197.511" y1="2237.772" x2="-197.511" y2="2237.772" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
|
||||||
|
<stop offset="0" style="stop-color:#F6F6F6"/>
|
||||||
|
<stop offset="0.5386" style="stop-color:#E4E4E4"/>
|
||||||
|
<stop offset="1" style="stop-color:#DADADA"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path fill="url(#SVGID_15_)" d="M-111.5,422.3"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 15 KiB |
BIN
src/admin/resources/img/select-arrow.png
Normal file
BIN
src/admin/resources/img/select-arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
5
src/admin/style.scss
Normal file
5
src/admin/style.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css?family=IBM+Plex+Sans&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
|
}
|
||||||
4
src/admin/theme.properties
Normal file
4
src/admin/theme.properties
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
parent=base
|
||||||
|
import=common/keycloak
|
||||||
|
styles=lib/patternfly/css/patternfly.css node_modules/select2/select2.css css/styles.css lib/angular/treeview/css/angular.treeview.css node_modules/text-security/dist/text-security.css
|
||||||
|
scripts=js/bundle.js
|
||||||
1
src/login/index.ts
Normal file
1
src/login/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import './style.scss';
|
||||||
97
src/login/login.ftl
Normal file
97
src/login/login.ftl
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayInfo=social.displayInfo displayWide=(realm.password && social.providers??); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("doLogIn", client.name)}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-form" <#if realm.password && social.providers??>class="${properties.kcContentWrapperClass!}"</#if>>
|
||||||
|
<div id="kc-form-wrapper"
|
||||||
|
<#if realm.password && social.providers??>class="${properties.kcFormSocialAccountContentClass!} ${properties.kcFormSocialAccountClass!}"</#if>>
|
||||||
|
<#if realm.password>
|
||||||
|
<form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="${url.loginAction}"
|
||||||
|
method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<label for="username"
|
||||||
|
class="${properties.kcLabelClass!}">
|
||||||
|
<#if !realm.loginWithEmailAllowed>
|
||||||
|
${msg("username")}
|
||||||
|
<#elseif !realm.registrationEmailAsUsername>
|
||||||
|
${msg("usernameOrEmail")}
|
||||||
|
<#else>
|
||||||
|
${msg("email")}
|
||||||
|
</#if>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<#if usernameEditDisabled??>
|
||||||
|
<input tabindex="1" id="username" class="${properties.kcInputClass!}" name="username"
|
||||||
|
value="${(login.username!'')}" type="text" disabled
|
||||||
|
placeholder="<#if !realm.loginWithEmailAllowed>${msg("username")} <#elseif !realm.registrationEmailAsUsername> ${msg("usernameOrEmail")} <#else> ${msg("email")} </#if>"/>
|
||||||
|
<#else>
|
||||||
|
<input tabindex="1" id="username" class="${properties.kcInputClass!}" name="username"
|
||||||
|
value="${(login.username!'')}" type="text" autofocus
|
||||||
|
placeholder="<#if !realm.loginWithEmailAllowed>${msg("username")} <#elseif !realm.registrationEmailAsUsername> ${msg("usernameOrEmail")} <#else> ${msg("email")} </#if>" autocomplete="off"/>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
||||||
|
<input tabindex="2" id="password" class="${properties.kcInputClass!}" name="password"
|
||||||
|
type="password" autocomplete="off" placeholder="${ msg("password") }"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!} ${properties.kcFormSettingClass!}">
|
||||||
|
<div id="kc-form-options">
|
||||||
|
<#if realm.rememberMe && !usernameEditDisabled??>
|
||||||
|
<div class="bx--form-item">
|
||||||
|
<#if login.rememberMe??>
|
||||||
|
<input tabindex="3" class="bx--checkbox" id="rememberMe" name="rememberMe"
|
||||||
|
type="checkbox" checked>
|
||||||
|
<#else>
|
||||||
|
<input tabindex="3" class="bx--checkbox" id="rememberMe" name="rememberMe"
|
||||||
|
type="checkbox">
|
||||||
|
</#if>
|
||||||
|
<label class="bx--checkbox-label" for="rememberMe">
|
||||||
|
${msg("rememberMe")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<#if realm.resetPasswordAllowed>
|
||||||
|
<span><a tabindex="5"
|
||||||
|
href="${url.loginResetCredentialsUrl}">${msg("doForgotPassword")}</a></span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
||||||
|
<input tabindex="4"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<#if realm.password && social.providers??>
|
||||||
|
<div id="kc-social-providers"
|
||||||
|
class="${properties.kcFormSocialAccountContentClass!} ${properties.kcFormSocialAccountClass!}">
|
||||||
|
<ul class="${properties.kcFormSocialAccountListClass!} <#if social.providers?size gt 4>${properties.kcFormSocialAccountDoubleListClass!}</#if>">
|
||||||
|
<#list social.providers as p>
|
||||||
|
<li class="${properties.kcFormSocialAccountListLinkClass!}"><a href="${p.loginUrl}"
|
||||||
|
id="zocial-${p.alias}"
|
||||||
|
class="zocial ${p.providerId}">
|
||||||
|
<span>${p.displayName}</span></a></li>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<#elseif section = "info" >
|
||||||
|
<#if realm.password && realm.registrationAllowed && !usernameEditDisabled??>
|
||||||
|
<div id="kc-registration">
|
||||||
|
<span>${msg("noAccount")} <a tabindex="6" href="${url.registrationUrl}">${msg("doRegister")}</a></span>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
||||||
43
src/login/style.scss
Normal file
43
src/login/style.scss
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
$app-page-background: #ECECEC;
|
||||||
|
$app-toolbar-background: #FFF;
|
||||||
|
|
||||||
|
@import "~carbon-components/css/carbon-components.css";
|
||||||
|
@import "style/login";
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SideBar {
|
||||||
|
border-right: 1px #EEE solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PageTitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FixedNotification {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 12px;
|
||||||
|
z-index: 999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FixedLanguageSelect {
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #FFF;
|
||||||
|
width: 100%;
|
||||||
|
.FillFlex {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/login/style/_login.scss
Normal file
73
src/login/style/_login.scss
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
@media (max-width: 66rem) {
|
||||||
|
.login-pf-page.bx--content {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.bx--tile {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-pf {
|
||||||
|
.bx--tile {
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body, .bx--content {
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
|
||||||
|
@media (max-width: 66rem) {
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
.FixedLanguageSelect {
|
||||||
|
.bx--select, select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-pf-page.bx--content {
|
||||||
|
|
||||||
|
.bx--form-item {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bx--tile {
|
||||||
|
max-width: 30rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #FFF;
|
||||||
|
padding: 1.1rem;
|
||||||
|
|
||||||
|
&.bx--wide {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-pf-settings {
|
||||||
|
> * {
|
||||||
|
margin-bottom: .4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 36px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#kc-form-buttons {
|
||||||
|
margin-top: .4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DisplayFlex {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.FillFlex {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
109
src/login/template.ftl
Normal file
109
src/login/template.ftl
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayWide=false>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" class="${properties.kcHtmlClass!}">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
|
||||||
|
<#if properties.meta?has_content>
|
||||||
|
<#list properties.meta?split(' ') as meta>
|
||||||
|
<meta name="${meta?split('==')[0]}" content="${meta?split('==')[1]}"/>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<title>${msg("loginTitle", (realm.displayName!''))}</title>
|
||||||
|
|
||||||
|
<link rel="icon" href="${url.resourcesPath}/img/favicon.ico"/>
|
||||||
|
|
||||||
|
<#if properties.styles?has_content>
|
||||||
|
<#list properties.styles?split(' ') as style>
|
||||||
|
<link href="${url.resourcesPath}/${style}" rel="stylesheet"/>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if properties.scripts?has_content>
|
||||||
|
<#list properties.scripts?split(' ') as script>
|
||||||
|
<script src="${url.resourcesPath}/${script}" type="text/javascript"></script>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if scripts??>
|
||||||
|
<#list scripts as script>
|
||||||
|
<script src="${script}" type="text/javascript"></script>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="${properties.kcBodyClass!}">
|
||||||
|
<header aria-label="Header" class="bx--header bx--header--website" role="banner">
|
||||||
|
<a class="bx--skip-to-content"
|
||||||
|
href="#main-content"
|
||||||
|
tabindex="0">
|
||||||
|
Skip to main content
|
||||||
|
</a>
|
||||||
|
<a class="bx--header__name" href="/">
|
||||||
|
${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="${properties.kcLoginClass!} bx--content" id="main-content">
|
||||||
|
<div class="${properties.kcFormCardClass!} form-card bx--tile <#if displayWide>${properties.kcFormCardAccountClass!} bx--wide</#if>">
|
||||||
|
<header class="${properties.kcFormHeaderClass!}">
|
||||||
|
<h1 id="kc-page-title" class="page-title"><#nested "header"></h1>
|
||||||
|
</header>
|
||||||
|
<div id="kc-content">
|
||||||
|
<div id="kc-content-wrapper">
|
||||||
|
|
||||||
|
<#if displayMessage && message?has_content>
|
||||||
|
<div class="alert alert-${message.type}">
|
||||||
|
<#if message.type = 'success'><span
|
||||||
|
class="${properties.kcFeedbackSuccessIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'warning'><span
|
||||||
|
class="${properties.kcFeedbackWarningIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'error'><span class="${properties.kcFeedbackErrorIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'info'><span class="${properties.kcFeedbackInfoIcon!}"></span></#if>
|
||||||
|
<span class="kc-feedback-text">${kcSanitize(message.summary)?no_esc}</span>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#nested "form">
|
||||||
|
|
||||||
|
<#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>
|
||||||
|
<#if realm.internationalizationEnabled && locale.supported?size gt 1>
|
||||||
|
<div class="FixedLanguageSelect">
|
||||||
|
<span class="FillFlex"></span>
|
||||||
|
<div class="bx--select">
|
||||||
|
<label for="select-id" class="bx--label">Select language</label>
|
||||||
|
<div class="bx--select-input__wrapper">
|
||||||
|
<select id="select-id" class="bx--select-input" onchange="window.location = this.value" >
|
||||||
|
<#list locale.supported as l>
|
||||||
|
<option class="bx--select-option"value="${ l.url }" <#if locale.current == l.label>selected</#if>>
|
||||||
|
${l.label}
|
||||||
|
</option>
|
||||||
|
</#list>
|
||||||
|
</select>
|
||||||
|
<svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="bx--select__arrow" width="10" height="6"
|
||||||
|
viewBox="0 0 10 6" aria-hidden="true">
|
||||||
|
<path d="M5 6L0 1 .7.3 5 4.6 9.3.3l.7.7z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</#macro>
|
||||||
69
src/login/theme.properties
Normal file
69
src/login/theme.properties
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
parent=base
|
||||||
|
import=common/keycloak
|
||||||
|
|
||||||
|
styles=
|
||||||
|
scripts=js/bundle.js
|
||||||
|
meta=viewport==width=device-width,initial-scale=1
|
||||||
|
|
||||||
|
kcHtmlClass=login-pf
|
||||||
|
kcLoginClass=login-pf-page
|
||||||
|
|
||||||
|
kcLogoLink=http://www.keycloak.org
|
||||||
|
|
||||||
|
kcLogoClass=login-pf-brand
|
||||||
|
|
||||||
|
kcContainerClass=container-fluid
|
||||||
|
kcContentClass=col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3
|
||||||
|
kcContentWrapperClass=row
|
||||||
|
|
||||||
|
kcHeaderClass=login-pf-page-header
|
||||||
|
kcFeedbackAreaClass=col-md-12
|
||||||
|
kcLocaleClass=col-xs-12 col-sm-1
|
||||||
|
kcAlertIconClasserror=pficon pficon-error-circle-o
|
||||||
|
|
||||||
|
kcFormAreaClass=col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2
|
||||||
|
kcFormCardClass=card-pf
|
||||||
|
kcFormCardAccountClass=login-pf-accounts
|
||||||
|
kcFormSocialAccountClass=login-pf-social-section
|
||||||
|
kcFormSocialAccountContentClass=col-xs-12 col-sm-6
|
||||||
|
kcFormSocialAccountListClass=login-pf-social list-unstyled login-pf-social-all
|
||||||
|
kcFormSocialAccountDoubleListClass=login-pf-social-double-col
|
||||||
|
kcFormSocialAccountListLinkClass=login-pf-social-link
|
||||||
|
kcFormHeaderClass=login-pf-header
|
||||||
|
|
||||||
|
kcFeedbackErrorIcon=pficon pficon-error-circle-o
|
||||||
|
kcFeedbackWarningIcon=pficon pficon-warning-triangle-o
|
||||||
|
kcFeedbackSuccessIcon=pficon pficon-ok
|
||||||
|
kcFeedbackInfoIcon=pficon pficon-info
|
||||||
|
|
||||||
|
doLogIn=Sign in to continue to {}
|
||||||
|
kcFormClass=form-horizontal
|
||||||
|
kcFormGroupClass=bx--form-item
|
||||||
|
kcFormGroupErrorClass=has-error
|
||||||
|
kcLabelClass=bx--label
|
||||||
|
kcLabelWrapperClass=
|
||||||
|
kcInputClass=bx--text-input
|
||||||
|
kcInputWrapperClass=
|
||||||
|
kcFormOptionsClass=
|
||||||
|
kcFormButtonsClass=
|
||||||
|
kcFormSettingClass=login-pf-settings
|
||||||
|
kcTextareaClass=form-control
|
||||||
|
kcSignUpClass=login-pf-signup
|
||||||
|
|
||||||
|
kcInfoAreaClass=col-xs-12 col-sm-4 col-md-4 col-lg-5 details
|
||||||
|
|
||||||
|
##### css classes for form buttons
|
||||||
|
# main class used for all buttons
|
||||||
|
kcButtonClass=bx--btn
|
||||||
|
# classes defining priority of the button - primary or default (there is typically only one priority button for the form)
|
||||||
|
kcButtonPrimaryClass=bx--btn--primary
|
||||||
|
kcButtonDefaultClass=
|
||||||
|
# classes defining size of the button
|
||||||
|
kcButtonLargeClass=btn-lg
|
||||||
|
kcButtonBlockClass=btn-block
|
||||||
|
|
||||||
|
##### css classes for input
|
||||||
|
kcInputLargeClass=input-lg
|
||||||
|
|
||||||
|
##### css classes for form accessability
|
||||||
|
kcSrOnlyClass=sr-only
|
||||||
26
src/welcome/index.ftl
Normal file
26
src/welcome/index.ftl
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Welcome to ${productNameFull}</title>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="welcome-content/favicon.ico" type="image/x-icon">
|
||||||
|
|
||||||
|
<#if properties.styles?has_content>
|
||||||
|
<#list properties.styles?split(' ') as style>
|
||||||
|
<link href="${resourcesPath}/${style}" rel="stylesheet" />
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
0
src/welcome/index.ts
Normal file
0
src/welcome/index.ts
Normal file
4
src/welcome/style.scss
Normal file
4
src/welcome/style.scss
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
$app-page-background: #ECECEC;
|
||||||
|
$app-toolbar-background: #FFF;
|
||||||
|
|
||||||
|
@import "~carbon-components/css/carbon-components.css";
|
||||||
6
src/welcome/theme.properties
Normal file
6
src/welcome/theme.properties
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import=common/keycloak
|
||||||
|
|
||||||
|
styles=node_modules/patternfly/dist/css/patternfly.css node_modules/patternfly/dist/css/patternfly-additions.css css/welcome.css
|
||||||
|
|
||||||
|
documentationUrl=https://www.keycloak.org/documentation.html
|
||||||
|
displayCommunityLinks=true
|
||||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"module": "es6",
|
||||||
|
"target": "es5",
|
||||||
|
"allowJs": true,
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
103
webpack.config.dev.js
Normal file
103
webpack.config.dev.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const CopyPlugin = require('copy-webpack-plugin');
|
||||||
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
|
const Dotenv = require('dotenv-webpack');
|
||||||
|
|
||||||
|
const commonConfig = (entryPoint) => ({
|
||||||
|
entry: `./src/${entryPoint}/index.ts`,
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.tsx', '.js']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
include: [
|
||||||
|
path.resolve(__dirname, 'src', entryPoint, '*'),
|
||||||
|
],
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
include: [path.resolve(__dirname, 'src')],
|
||||||
|
loader: 'babel-loader',
|
||||||
|
|
||||||
|
options: {
|
||||||
|
plugins: [
|
||||||
|
'syntax-dynamic-import',
|
||||||
|
],
|
||||||
|
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
test: /\.js$/,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(scss|css)$/,
|
||||||
|
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'style-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
output: {
|
||||||
|
filename: 'bundle.js',
|
||||||
|
path: path.join(__dirname, `./carbon/${entryPoint}/resources/js/`),
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: process.env.NODE_ENV || 'development',
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
new CleanWebpackPlugin(),
|
||||||
|
new webpack.BannerPlugin({
|
||||||
|
banner: () => `Copyright ${new Date().getFullYear()}`,
|
||||||
|
}),
|
||||||
|
new webpack.EnvironmentPlugin({}),
|
||||||
|
new Dotenv(),
|
||||||
|
new CopyPlugin([
|
||||||
|
{
|
||||||
|
from: path.join(__dirname, `src/${entryPoint}`),
|
||||||
|
to: path.join(__dirname, `/carbon/${entryPoint}`),
|
||||||
|
ignore: ['*.js', '*.ts', '*.scss'],
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
vendors: {
|
||||||
|
priority: -10,
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
chunks: 'async',
|
||||||
|
minChunks: 1,
|
||||||
|
minSize: 30000,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
minimizer: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ['login', 'account', 'welcome', 'admin'].map(res => commonConfig(res));
|
||||||
10
webpack.config.js
Normal file
10
webpack.config.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
const devConfig = require('./webpack.config.dev');
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
|
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
|
||||||
|
|
||||||
|
for (const config of devConfig) {
|
||||||
|
config.optimization.minimizer.push(new TerserPlugin());
|
||||||
|
config.plugins.push(new UglifyJSPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
app.exports = devConfig;
|
||||||
Reference in New Issue
Block a user