Show/Hide password toggle in password field in Keycloak - keycloak

I have edited code of script.js for show/Hide password toggle in password field in Keycloak but It is not working. Please see it and let me know, How can I make it work? Thank you
Addition in script.js:
// Rudimentary method for adding a password reveal button.
window.onload = function() {
var fToggle = function($password, e) {
e.preventDefault();
const type = $password.getAttribute('type') === 'password' ? 'text' : 'password';
$password.setAttribute('type', type);
this.classList.toggle('bi-eye');
};
var createReveal = function(passwordId, toggleId) {
var password = document.getElementById(passwordId);
if ((password) && (password.style) && (password.style.display !== 'none')){
var icon = document.createElement("i");
icon.id = toggleId;
icon.classList.add('password-reveal', 'bi', 'bi-eye-slash');
icon.addEventListener('click', fToggle.bind(icon, password));
password.parentNode.insertBefore(icon, password.nextSibling);
}
};
createReveal('password', 'togglePassword');
createReveal('password-new', 'togglePasswordNew');
createReveal('password-confirm', 'togglePasswordConfirm');
css:
.password-reveal {
color: #5500B3;
margin-left: -40px;
font-size: 20px;
cursor: pointer;
}

I think the problem is import of library of icon is missing. It is working for me as follow:
In script.js file:
setTimeout(() => {
var fToggle = function($password, e) {
e.preventDefault();
const type = $password.getAttribute('type') === 'password' ? 'text' : 'password';
$password.setAttribute('type', type);
this.classList.toggle('fa-eye-slash');
};
var createReveal = function(passwordId, toggleId) {
var password = document.getElementById(passwordId);
if ((password) && (password.style) && (password.style.display !== 'none')){
var icon = document.createElement("i");
icon.id = toggleId;
icon.classList.add('password-reveal', 'fa','fa-eye', 'fa-eye-slash');
icon.addEventListener('click', fToggle.bind(icon, password));
password.parentNode.insertBefore(icon, password.nextSibling);
}
};
createReveal('password', 'togglePassword');
createReveal('password-new', 'togglePasswordNew');
createReveal('password-confirm', 'togglePasswordConfirm');
}, 5);
In styles.css
#import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css");
.password-reveal {
color: #0052f0;
background-color: white;
margin-left: -40px;
font-size: 24px !important;
}
For edting the files, go inside your keycloak project, go to your theme folder inside keycloak folder and then there will be the css folder with file styles.css and js folder with script.js. You can edit the code there.
If these folders or files do not exist then create them and add this code. And then update theme.properties file.
For example in the theme.properties file, add:
styles=css/styles.css
scripts=js/script.js

Related

Conditionally add styles properties on MUI

On styled-components we can have something like this
import syled, { css } from 'styled-components';
const StyledButton = styled.button<StyledButtonProps>`
display: flex;
${textStyles.styledButton}
${props =>
props.disabled &&
css`
opacity: 0.5;
`}
`
I'm trying to use MUI's styled but can't find how to conditionally add the opacity property based on the props passed to the button. I'm trying something like this, but don't want to define the default value of every conditional styles as on opacity here (since there could be a LOT of conditional properties based on the value of a passed prop)
import { styled } from '#material-ui/core/styles';
// eslint-disable-next-line #typescript-eslint/no-unused-vars
const StyledMUIButton = styled(({ disabled, disclosure, whiteButton, fullWidth, noMarginTop, ...rest }: StyledButtonProps) => (
<button {...rest} />
))({
display: 'flex',
...textStyles.button,
opacity: (props: StyledButtonProps) => props.disabled ? 0.5 : 1
})
Another case would be something like this in styled-components, how can be that applied to MUI's styled?
${props =>
props.whiteButton
? css`
background-color: transparent;
border: none;
${textStyles.styledLink}
`
: css`
&:focus {
background: transparent;
border: 1px solid ${colors.textLink};
color: ${colors.textLink};
}
`}
I ended up using makeStyles the following way
const useStyles = makeStyles({
button: (props: StyledButtonProps) => ({
display: 'flex',
...textStyles.button,
...props.disabled && { opacity: 0.5 },
})
})

Using Protractor: Switch to iframe using browser.switchTo().frame

So I have already written the testing script which:
1) Logs into the application framework, then
2) Clicks menu to launch the app which I am testing ("MyAwesomeApp.html" for this post)
And my main problem is: In navpanel-spec.js below, I want to target the https://server/apps/Default.aspx?r=1 URL, then click within the iframe where MyAwesomeApp is running.
**** ERROR Trying to switch to the iframe this way, but it does NOT work:
browser.switchTo().frame(element(by.id('1')).getWebElement());
Error in cmd prompt:
Started
[15:43:29] E/launcher - No element found using locator: By(css selector, *[id="\31 "])
...
sat-navpanel-spec.js:52:24)
So there are two URLs going on here:
1) https://server/apps/Default.aspx?r=1 (the main app framework with menu system in top nav).
2) https://server/apps/MyAwesomeApp.html (the web app which the test script launches within the <iframe> tag.
The html looks like this, where the application renders within the <iframe> :
<body>
<div id="top">
<!-- top nav menu systems rendered here -->
</div>
<div id="middle">
<div id="m1">
<div id="m2" class="hidden">
<div id="m3">
<div id="right" class="hidden">
<div>
<div id="frame_holder" style="height: 940px;">
<iframe style="width: 100%; height: 100%;" name="1" id="1" src="https://server/apps/MyAwesomeApp.html">
</iframe>
</div>
</div>
</div>
</div>
<div id="left" style="display: none;"></div>
</div>
</div>
</div>
</body>
In my Protractor.config.js file I have a few specs :
specs: [
'spec/login.js',
'spec/launch-awesome-app.js',
'spec/navpanel-spec.js',
'spec/another-spec.js',
'spec/yet-another-spec.js'
]
login.js and launch-awesome-app.js work fine. They log into the menu system, then click thru the menus in order to launch myAwesomeapp - no problem.
MY PROBLEM:
In navpanel-spec.js I want to target the https://server/apps/Default.aspx?r=1 URL, then click within the iframe where MyAwesomeApp is running.
However, it is NOT selecting any of my elements.
If I target https://server/apps/MyAwesomeApp.html in navpanel-spec.js, of course it launches a new browser window and runs the test just fine.
Here's my navpanel-spec.js test spec:
describe('Testing My Awesome App', function () {
var panelObj = new PanelObjects();
var urlDefault = 'https://server/apps/Default.aspx?r=1';
var urlApp = 'https://server/apps/MyAwesomeApp.html';
browser.get(urlApp); // Runs my AwesomeApp tests okay, HOWEVER it launches a new browser window.
browser.get(urlDefault); // Launches app framework with top nav menus and embedded <iframe>,
// HOWEVER I cannot select iframe and successfully run tests here.
beforeEach(function () {
browser.sleep(5000);
browser.waitForAngular();
});
// USE-CASE OBJECT !!
var items = browser.params.useCaseJsonFile["navigatePanels"];
browser.getAllWindowHandles().then(function (handles) {
handles.map(function (win, idx) {
browser.driver.getCurrentUrl().then(function (curr) {
if (curr.indexOf('Default.aspx') >= 0) {
browser.driver.switchTo().window(handles[idx]);
}
});
});
});
browser.switchTo().frame(element(by.id('1')).getWebElement());
var testId = element(by.id('middle'));
console.log(testId);
items.map(function (item) {
if (item.enableTest) {
var specItem = it(item.name, function () {
console.log('------------------------------');
console.log('---- ' + item.describe);
browser.waitForAngular();
// select panels, etc..
panelObj.panelClick(item.panelName).then(function () {
// ...
});
panelObj.getPanelText(item.panelName).then(function (title) {
expect(title).toContain(item.panelTitle);
});
});
}
});
});
UPDATE
var LoginObjects = require('../pageObjects/login-objects.js');
describe('Testing My Awesome App', function () {
var panelObj = new PanelObjects();
var loginObj = new LoginObjects();
//var urlDefault = 'https://server/apps/Default.aspx?r=1';
//browser.get(urlApp); // Runs my AwesomeApp tests okay, HOWEVER it launches a new browser window.
browser.ignoreSynchronization = true;
// LOGIN AND LAUNCH APP !!!
loginObj.Login();
loginObj.Launch();
beforeEach(function () {
browser.sleep(5000);
browser.waitForAngular();
});
// USE-CASE OBJECT !!
var items = browser.params.useCaseJsonFile["navigatePanels"];
// SWITCH TO iframe ELEMENT
loginObj.switchWindowAndFrame();
items.map(function (item) {
if (item.enableTest) {
var specItem = it(item.name, function () {
console.log('------------------------------');
console.log('---- ' + item.describe);
browser.waitForAngular();
// select panels, etc..
panelObj.panelClick(item.panelName).then(function () {
// ...
});
panelObj.getPanelText(item.panelName).then(function (title) {
expect(title).toContain(item.panelTitle);
});
});
}
});
});
and my page objects :
module.exports = function(){
this.Login = function(){
var url = browser.params.loginUrl;
browser.driver.get(url);
browser.sleep(200);
var userName = browser.params.credential.userId;
var password = browser.params.credential.password;
element(by.id('username')).clear().then(function(){
element(by.id('username')).sendKeys(userName);
element(by.id('password')).sendKeys(password);
});
browser.sleep(1000);
var that = this;
var submitElement = element(by.id('bthLogin'));
submitElement.click().then(function () {
browser.getAllWindowHandles().then(function (handles) {
// LOGIN MESSAGE WINDOW
browser.driver.getCurrentUrl().then(function(curr){
if (curr.indexOf('LoginMsg.aspx') >= 0){
// Do we really need to close the login successful browser ???
browser.driver.close();
}
});
browser.driver.switchTo().window(handles[1]);
});
});
},
this.Launch = function(){
var sel = '#TheMenu1 > ul > li:first-child';
var elem = element(by.css(sel));
elem.click().then(function(){
browser.sleep(1000);
var elem2 = element(by.cssContainingText('.rmLink', 'The First Menu Item'));
elem2.click();
// Select menu item; sleep before attempting to click().
var subElem = element(by.cssContainingText('.rmLink', 'My Awesome App'));
browser.sleep(1000);
subElem.click();
browser.waitForAngular();
});
},
this.switchWindowAndFrame = function(){
browser.getAllWindowHandles().then(function (handles) {
handles.map(function(win, idx){
browser.driver.getCurrentUrl().then(function(curr){
if (curr.indexOf('Default.aspx') >= 0){
browser.driver.switchTo().window(handles[idx]);
}
});
});
});
browser.switchTo().frame(element(by.css('[name="1"]')).getWebElement());
}
};
As mentioned in the comments above, protractor has a bug which prefixes '\3' to your id element with number.
The temporary way is to change you locator. :P

Ocasional gulp-sass 'not found or unreadable' error when importing variable partial

Every few times I edit my _vars.scss file, gulp-sass watch will throw the error
Error in plugin 'sass'
Message:
sass\stylesheet.scss
Error: File to import not found or unreadable: vars
Parent style sheet: stdin
on line 10 of stdin
>> #import 'vars';
^
I can get it to compile again if I comment out the line
#import 'vars';
Here is my code
stylesheet.scss
//Settings
#import 'colors';
#import 'vars';
//External libs
#import 'font-awesome';
#import 'susy';
#import 'breakpoint';
//Global and default styles
#import 'global';
//sections
#import 'styles/header';
#import 'styles/main';
#import 'styles/footer';
_vars.scss
$font-heading: 'Oswald', sans-serif;
$font-paragraph: 'Raleway', sans-serif;
// Padding
$spacing: 5px;
#function spacing($size){
#return $spacing * $size;
}
$footer-height: spacing(10);
$susy: (
columns: 12,
gutters: 1 / 4,
// debug: (image: show)
);
Gulpfile,js
var gulp = require('gulp');
var util = require('gulp-util');
var replace = require('gulp-replace');
var browserSync = require('browser-sync').create();
var sass = require('gulp-sass');
var inclPaths = require('sass-include-paths');
var sourcemaps = require('gulp-sourcemaps');
var bower = require('gulp-bower');
var stylePaths = {
sass: './sass/**/*.scss',
css: './css'
}
var sassIncludes = []
.concat(inclPaths.bowerComponentsSync());
var sassOptions = {
style: 'expanded',
includePaths: sassIncludes
}
var bowerDir = './bower_components';
var faPaths = {
src: bowerDir + '/font-awesome/fonts/**.*',
dest: 'fonts',
}
var vendorJS = {
base: bowerDir,
scripts: [bowerDir + '/jquery/dist/jquery.js'],
dest: './js/vendor'
}
gulp.task('sass', function(){
return gulp
.src(stylePaths.sass)
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(sourcemaps.write())
.pipe(gulp.dest(stylePaths.css))
.pipe(browserSync.stream({match: '**/*.css'}));
});
gulp.task('watch', ['sass'], function(){
browserSync.init({
proxy: 'mysite.local'
});
gulp.watch(stylePaths.sass, ['sass']);
gulp.watch('./*.html').on('change', browserSync.reload);
});
gulp.task('bower', function(){
return bower()
.pipe(gulp.dest(bowerDir));
});
gulp.task('faFonts', function(){
return gulp.src(faPaths.src)
.pipe(gulp.dest(faPaths.dest));
});
gulp.task('vendorScripts', function(){
return gulp.src(vendorJS.scripts, {base: vendorJS.base})
.pipe(gulp.dest(vendorJS.dest));
})
gulp.task('default', ['watch']);
I have been reading a lot about this error, and it is usually because of sublime text and using a windows machine. If you already have those settings you have to go into sublime preferences, then "Settings - User" and add another option "atomic_save": true. You can research more about this as there are tons of persons having this issue.
Code of Settings - User:
{
"color_scheme": "Packages/Color Scheme - Default/Twilight.tmTheme",
"font_size": 9,
"atomic_save": true
}
Regards.

Is it possible to create a 'view all' page in Tumblr?

I've tried creating pages using the 'standard layout' and 'custom layout' but neither allows the use of the {block:Posts} variable(s). I need to re-create essentially the archive page but with some custom css. Is there any way to accomplish this?
If I try $("#someDiv").load("/archive", "#content"); the whole page formatting gets screwed up. Is there a way to load just the <a> tags into a div on my custom page?
Or would it be possible to use the API entirely client side to accomplish this?
Any ideas on this would be appreciated.
I came up with two possible solutions if anyone else finds themselves stuck on this. I abandoned this first one before finalizing it, so it's a bit rough but a good start. It uses the API to load photos (that was all I needed) as you scroll down the page.
<script>
function getPhotos(offset){
$.ajax({
url: "http://api.tumblr.com/v2/blog/[tumblr].tumblr.com/posts?api_key=[key]&offset="+offset,
dataType: 'jsonp',
success: function(results){
loaded += 20;
total = results.response.blog.posts;
if(total > loaded){
results.response.posts.forEach(function(post){
post.photos.forEach(function(photo){
$("#photos ul").append("<li class='"+post.tags.join(" ")+"'><img src='"+photo.alt_sizes[0].url+"'></li>");
$("#photos").imagesLoaded(function(){
$("#photos").masonry({
itemSelector: 'li'
});
});
});
});
if($("#photos ul").height() < $(window).height()){
getPhotos(loaded);
}
}
}
});
}
loaded = 0;
getPhotos(loaded);
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
getPhotos(loaded);
}
});
</script>
What I've ended up doing is just using an iframe with a custom stylesheet appended to the head.
html:
<head>
<script src="http://[remote location]/frame.js"></script>
</head>
<body>
<div id="photos">
<iframe name="frame1" id="frame1" src="http://[tumblr]/archive" frameBorder="0"></iframe>
</div>
</body>
frame.js:
$(function(){
function insertCSS(){
var frm = frames['frame1'].document;
var otherhead = frm.getElementsByTagName("head")[0];
if(otherhead.length != 0){
var link = frm.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", "http://[remote location]/frame.css");
otherhead.appendChild(link);
setTimeout(function(){$("#frame1").show();}, 200);
clearInterval(cssInsertion);
}
}
cssInsertion = setInterval(insertCSS, 500);
//setTimeout(insertCSS, 1000);
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100 && $("#frame1").height() < 50000) {
$("#frame1").css("height", "+=1000px");
}
});
});
frame.css (stylesheet appended into iframe)
body{
overflow: hidden;
}
#nav_archive{
display: none;
}
.heading{
display: block !important;
}
.old_archive #content{
margin: 0 auto 0;
}
style.css (stylesheet on page where iframe is located)
#frame1{
border: none;
width: 100%;
height: 3000px;
overflow: hidden;
display: none;
}

Form not submit

I have a edit user form. The form is loaded from a Json store with this code:
var store = Ext.create('cp.store.form.Paciente',{});
store.load({params:{idUsuario: idPaciente}});
var form = Ext.create('cp.view.form.EditPaciente',{
action: 'bin/paciente/modificar.php'
});
// note: write this lines in the controller
form.on('afterrender',function(form,idPaciente){
form.getForm().loadRecord(store.first());
form.getForm().findField('idUsuario').setValue(idPaciente);
});
var win = Ext.create('cp.view.ui.DecoratorForm',{
aTitle: 'Editar paciente',
aForm: form
});
win.show();
The load code works fine. The submit code is:
var me = this;
console.log('Submit...');
console.log(this.url);
// WHY NOT SUBMIT !!!!
this.getForm().submit({
console.log('submit !');
success: function(form,action){
if(action.result.success === true){
Ext.create('cp.view.ui.AlertOk',{mensaje:action.result.msg}).showDialog();
me.up('decoratorForm').close();
}else{
Ext.create('cp.view.ui.AlertErr',{mensaje:action.result.msg}).showDialog();
}
}
});
So, the submit code starts running. FireBug shows the first and second "console.log", and the "this.url" value is correct. But, the third "console.log" not execute, and the form not send to the server.
Firebug not says 404 error for "this.url" value.
Any ideas ?
Thanks !
Add the form definition:
Ext.define('cp.view.form.EditPaciente',{
extend: 'Ext.form.Panel',
alias: 'widget.editPaciente',
bodyPadding: '5px 5px 5px 5px',
bodyStyle: 'border: none',
fieldDefaults: {
labelWidth: 65,
labelAlign: 'top'
},
initComponent: function(){
this.url = this.action,
this.method = 'POST',
this.items = [ .... ]
this.callParent(arguments);
}
});
You cant put log statements inside object literals.
submit({ <-- This is an object literal
console.log('submit !'); <-- This can not be in an object literal
success: function(form,action){
if(action.result.success === true){
Ext.create('cp.view.ui.AlertOk',{mensaje:action.result.msg}).showDialog();
me.up('decoratorForm').close();
}else{
Ext.create('cp.view.ui.AlertErr',{mensaje:action.result.msg}).showDialog();
}
}
});