Browse Source

make version more visible and accessible

pull/342/head
Guillaume Vincent 8 years ago
parent
commit
f58dc94a9b
7 changed files with 131 additions and 109 deletions
  1. +13
    -1
      index.html
  2. +19
    -2
      src/LessPass.vue
  3. +1
    -1
      src/api/tooltip.js
  4. +5
    -4
      src/components/Menu.vue
  5. +4
    -5
      src/store.js
  6. +6
    -7
      src/views/Login.vue
  7. +83
    -89
      src/views/PasswordGenerator.vue

+ 13
- 1
index.html View File

@@ -6,9 +6,21 @@
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"> <meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="dist/lesspass.min.css"> <link rel="stylesheet" href="dist/lesspass.min.css">
<style>
div.centre {
width: 470px;
max-width: 100%;
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
</head> </head>
<body> <body>
<div id="lesspass"></div>
<div class="centre">
<div class="py-1 hidden-sm-down"></div>
<div id="lesspass" class="m-x-auto"></div>
</div>
<script src="dist/lesspass.min.js"></script> <script src="dist/lesspass.min.js"></script>
</body> </body>
</html> </html>

+ 19
- 2
src/LessPass.vue View File

@@ -3,6 +3,20 @@
color: white; color: white;
} }


#lesspass.card {
border: none;
}

@media (min-width: 544px) {
#lesspass.v1 {
border: 1px solid #f0ad4e;
}

#lesspass.v2 {
border: 1px solid #0275d8;
}
}

#lesspass .white-link:hover, #lesspass .white-link:focus, #lesspass .white-link:active { #lesspass .white-link:hover, #lesspass .white-link:focus, #lesspass .white-link:active {
text-decoration: none; text-decoration: none;
color: white; color: white;
@@ -13,7 +27,8 @@
} }
</style> </style>
<template> <template>
<div id="lesspass" class="card" style="max-width: 475px;">
<div id="lesspass" class="card" style="max-width: 470px;"
v-bind:class="{ 'v1': version===1, 'v2': version===2 }">
<lesspass-menu></lesspass-menu> <lesspass-menu></lesspass-menu>
<div class="card-block"> <div class="card-block">
<router-view></router-view> <router-view></router-view>
@@ -22,12 +37,14 @@
</template> </template>
<script type="text/ecmascript-6"> <script type="text/ecmascript-6">
import Menu from './components/Menu.vue'; import Menu from './components/Menu.vue';
import {mapGetters} from 'vuex';


export default { export default {
name: 'LessPass', name: 'LessPass',
components: { components: {
'lesspass-menu': Menu 'lesspass-menu': Menu
}, },
computed: mapGetters(['version']),
created(){ created(){
const fiveMinutes = 1000 * 60 * 5; const fiveMinutes = 1000 * 60 * 5;
this.$store.dispatch('REFRESH_TOKEN'); this.$store.dispatch('REFRESH_TOKEN');
@@ -36,4 +53,4 @@
}, fiveMinutes); }, fiveMinutes);
} }
} }
</script>
</script>

+ 1
- 1
src/api/tooltip.js View File

@@ -1,6 +1,6 @@
export function showTooltip(elem, msg) { export function showTooltip(elem, msg) {
var classNames = elem.className; var classNames = elem.className;
elem.setAttribute('class', classNames + ' hint--top');
elem.setAttribute('class', classNames + ' hint--right');
elem.setAttribute('aria-label', msg); elem.setAttribute('aria-label', msg);
setTimeout(function () { setTimeout(function () {
elem.setAttribute('class', classNames); elem.setAttribute('class', classNames);


+ 5
- 4
src/components/Menu.vue View File

@@ -24,10 +24,11 @@
</style> </style>
<template> <template>
<div id="menu"> <div id="menu">
<div class="card-header" v-show="isAuthenticated">
<div class="card-header" v-show="isAuthenticated"
v-bind:class="{ 'card-warning': version===1, 'card-primary': version===2 }">
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<router-link class="grey-link" :to="{ name: 'home'}">LessPass</router-link>
<router-link class="white-link" :to="{ name: 'home'}">LessPass</router-link>
<span v-on:click="saveOrUpdatePassword"> <span v-on:click="saveOrUpdatePassword">
<i class="fa fa-save ml-1 fa-clickable" v-if="passwordStatus=='DIRTY'"></i> <i class="fa fa-save ml-1 fa-clickable" v-if="passwordStatus=='DIRTY'"></i>
</span> </span>
@@ -36,10 +37,10 @@
</span> </span>
</div> </div>
<div class="col-xs-6 text-xs-right"> <div class="col-xs-6 text-xs-right">
<router-link class="grey-link ml-1" :to="{ name: 'passwords'}">
<router-link class="white-link ml-1" :to="{ name: 'passwords'}">
<i class="fa fa-key" aria-hidden="true"></i> <i class="fa fa-key" aria-hidden="true"></i>
</router-link> </router-link>
<button class="grey-link ml-1 btn btn-link p-0 m-0" type="button" v-on:click="logout">
<button class="white-link ml-1 btn btn-link p-0 m-0" type="button" v-on:click="logout">
<i class="fa fa-sign-out" aria-hidden="true"></i> <i class="fa fa-sign-out" aria-hidden="true"></i>
</button> </button>
</div> </div>


+ 4
- 5
src/store.js View File

@@ -22,12 +22,12 @@ const defaultPassword = {
length: 12, length: 12,
counter: 1 counter: 1
}; };
function getDefaultPasswordProfile(version) {
function getDefaultPasswordProfile(version, passwordProfile = {}) {
if (version === 1) { if (version === 1) {
return Object.assign({}, defaultPassword, {version: 1, length: 12});
return Object.assign({}, defaultPassword, passwordProfile, {version: 1, length: 12});
} }
if (version === 2) { if (version === 2) {
return Object.assign({}, defaultPassword, {version: 2, length: 16});
return Object.assign({}, defaultPassword, passwordProfile, {version: 2, length: 16});
} }
} }


@@ -87,9 +87,8 @@ const mutations = {
state.email = email state.email = email
}, },
CHANGE_VERSION(state, {version}){ CHANGE_VERSION(state, {version}){
state.password = getDefaultPasswordProfile(version);
state.password = getDefaultPasswordProfile(version, state.password);
state.version = version; state.version = version;
storage.save({version});
}, },
}; };




+ 6
- 7
src/views/Login.vue View File

@@ -34,7 +34,8 @@
class="form-control" class="form-control"
required required
placeholder="LessPass password" placeholder="LessPass password"
v-model="password">
v-model="password"
v-on:keyup.enter.prevent="signIn">
<small class="form-text text-muted"> <small class="form-text text-muted">
<span v-if="errors.passwordRequired" class="text-danger">A password is required</span> <span v-if="errors.passwordRequired" class="text-danger">A password is required</span>
<label class="form-check-label"> <label class="form-check-label">
@@ -85,12 +86,10 @@
</button> </button>
</div> </div>
</div> </div>
<div class="form-group row">
<div class="col-xs-12">
<router-link :to="{ name: 'passwordReset'}">
Forgot your password?
</router-link>
</div>
<div class="form-group mb-0">
<router-link :to="{ name: 'passwordReset'}">
Forgot your password?
</router-link>
</div> </div>
</form> </form>
</template> </template>


+ 83
- 89
src/views/PasswordGenerator.vue View File

@@ -82,72 +82,76 @@
autocomplete="new-password" autocomplete="new-password"
autocorrect="off" autocorrect="off"
autocapitalize="off" autocapitalize="off"
v-model="masterPassword">
<fingerprint :fingerprint="fingerprint" v-on:click.native="showMasterPassword"></fingerprint>
v-model="masterPassword"
v-on:keyup.enter.prevent="generatePassword">
<fingerprint :fingerprint="fingerprint" v-on:click.native="togglePasswordType($refs.masterPassword)">
</fingerprint>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-xs-8">
<input id="generatedPassword" type="text" class="form-control mb-0" v-bind:value="generatedPassword"
v-show="showPassword && showCopyBtn" readonly>
<button id="copyPasswordButton" type="button" v-show="!showPassword && showCopyBtn"
data-clipboard-text=""
class="btn btn-block mt-0"
v-bind:class="{ 'btn-warning': password.version===1, 'btn-primary': password.version===2 }">
<i class="fa fa-clipboard" aria-hidden="true"></i>
Copy
</button>
<button type="button" class="btn btn-block mt-0" v-show="!showCopyBtn" v-on:click="generatePassword"
v-bind:class="{ 'btn-outline-warning': password.version===1, 'btn-outline-primary': password.version===2 }">
<i class="fa fa-calculator fa-fw" aria-hidden="true"></i>
Generate
</button>
<div class="col-xs-9" v-show="generatedPassword">
<div class="input-group">
<span class="input-group-btn">
<button id="copyPasswordButton" type="button" data-clipboard-text="" class="btn"
ref="copyPasswordButton"
v-bind:class="{ 'btn-warning': password.version===1, 'btn-primary': password.version===2 }">
<i class="fa fa-clipboard" aria-hidden="true"></i>
</button>
</span>
<input type="password" class="form-control read-only" readonly tabindex="-1"
v-bind:class="{ 'btn-outline-warning': password.version===1, 'btn-outline-primary': password.version===2 }"
v-on:click="togglePasswordType($event.target)" v-bind:value="generatedPassword">
</div>
</div> </div>
<div class="col-xs-4 pl-0">
<div class="btn-group float-xs-right" role="group">
<button type="button" class="btn btn-secondary" v-show="showPassword && showCopyBtn"
v-on:click="showPassword=false">
<i class="fa fa-eye-slash" aria-hidden="true"></i>
<div class="col-xs-9" v-show="!generatedPassword">
<div class="btn-group" role="group">
<button type="button" class="btn" v-on:click="generatePassword"
v-bind:class="{ 'btn-outline-warning': password.version===1, 'btn-outline-primary': password.version===2 }">
<span v-if="!generatingPassword">Generate</span>
<span v-if="generatingPassword">Generating...</span>
</button> </button>
<button type="button" class="btn btn-secondary" v-show="!showPassword && showCopyBtn"
v-on:click="showPassword=true">
<i class="fa fa-eye" aria-hidden="true"></i>
<button type="button" class="btn btn-secondary" v-on:click="toggleVersion"
v-bind:class="{ 'btn-outline-warning': password.version===1, 'btn-outline-primary': password.version===2 }">
<small v-show="password.version===1">v1</small>
<small v-show="password.version===2">v2</small>
</button> </button>
</div>
</div>
<div class="col-xs-3">
<div class="btn-group float-xs-right" role="group">
<button type="button" class="btn btn-secondary" v-on:click="showOptions=!showOptions"> <button type="button" class="btn btn-secondary" v-on:click="showOptions=!showOptions">
<i class="fa fa-sliders" aria-hidden="true"></i> <i class="fa fa-sliders" aria-hidden="true"></i>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group row pt-1" v-if="showOptions">
<div class="col-xs-3">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="lowercase" v-model="password.lowercase"> abc
</label>
</div>
<div class="col-xs-3">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="uppercase"
v-model="password.uppercase"> ABC
</label>
</div>
<div class="col-xs-3">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="numbers"
v-model="password.numbers">
123
</label>
</div>
<div class="col-xs-3 text-right-center">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="symbols"
v-model="password.symbols">
%!@
</label>
</div>
<div class="form-group" v-if="showOptions">
Options
</div>
<div class="form-group" v-if="showOptions">
<label class="custom-control custom-checkbox">
<input type="checkbox" id="lowercase" v-model="password.lowercase" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">abc</span>
</label>
<label class="custom-control custom-checkbox">
<input type="checkbox" id="uppercase" v-model="password.uppercase" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">ABC</span>
</label>
<label class="custom-control custom-checkbox">
<input type="checkbox" id="numbers" v-model="password.numbers" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">123</span>
</label>
<label class="custom-control custom-checkbox">
<input type="checkbox" id="symbols" v-model="password.symbols" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">%!@</span>
</label>
</div> </div>
<div class="form-group row" v-if="showOptions"> <div class="form-group row" v-if="showOptions">
<div class="col-xs-5">
<div class="col-xs-6">
<label for="passwordLength">Length</label> <label for="passwordLength">Length</label>
<div class="input-group"> <div class="input-group">
<input class="form-control" type="number" id="passwordLength" v-model="password.length" min="4"> <input class="form-control" type="number" id="passwordLength" v-model="password.length" min="4">
@@ -159,7 +163,7 @@
</span> </span>
</div> </div>
</div> </div>
<div class="col-xs-5 offset-xs-2">
<div class="col-xs-6">
<label for="passwordCounter">Counter</label> <label for="passwordCounter">Counter</label>
<div class="input-group"> <div class="input-group">
<input class="form-control" type="number" id="passwordCounter" v-model="password.counter" min="1"> <input class="form-control" type="number" id="passwordCounter" v-model="password.counter" min="1">
@@ -172,38 +176,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-group row" v-if="showOptions">
<div class="col-xs-12 col-sm-4 pb-1">
<label for="version">
Version
</label>
<select id="version" v-model="password.version" v-on:change="selectVersion" class="form-control">
<option value="1">v1</option>
<option value="2">v2</option>
</select>
</div>
</div>
<div class="form-group" v-if="showError"> <div class="form-group" v-if="showError">
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
site, login and master password fields are mandatory site, login and master password fields are mandatory
</div> </div>
</div> </div>
<div class="form-group" v-if="version === 2 && password.version ===1 && !showError">
<div class="alert alert-warning" role="alert">
This is a password in version&nbsp;1.
You should update your password and use version&nbsp;2
<br>
<a href="#" v-on:click.prevent="showOptions=!showOptions" v-if="!showOptions"> show me the options</a>
</div>
</div>
<div class="form-group" v-if="version === 1 && !showError">
<div class="alert alert-warning" role="alert">
<div class="form-group mb-0" v-if="version === 1 && !showError">
<div class="alert alert-warning mb-0" role="alert">
<small> <small>
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
You use an obsolette version of LessPass. You use an obsolette version of LessPass.
<br>
The default version will be version&nbsp;2 in <strong>{{ getDayBeforeV2() }}&nbsp;days</strong>.
You can still use LessPass version 1 in the options.
The default version will be version&nbsp;2 in
<strong aria-label="10 jan 2017" class="hint--right">{{ getDayBeforeV2() }}&nbsp;days</strong>.
You can continue to use version 1 even if we advise you to update your passwords.
</small> </small>
</div> </div>
</div> </div>
@@ -264,9 +249,8 @@
generatedPassword: '', generatedPassword: '',
cleanTimeout: null, cleanTimeout: null,
showOptions: false, showOptions: false,
showPassword: false,
showCopyBtn: false,
showError: false
showError: false,
generatingPassword: false
} }
}, },
watch: { watch: {
@@ -313,6 +297,7 @@
}, },
'masterPassword': function () { 'masterPassword': function () {
this.cleanErrors(); this.cleanErrors();
this.cleanFormInSeconds(30);
this.showFingerprint(); this.showFingerprint();
} }
}, },
@@ -320,16 +305,16 @@
showFingerprint: debounce(function () { showFingerprint: debounce(function () {
this.fingerprint = this.masterPassword; this.fingerprint = this.masterPassword;
}, 3000), }, 3000),
showMasterPassword(){
if (this.$refs.masterPassword.type === 'password') {
this.$refs.masterPassword.type = 'text';
togglePasswordType(element){
if (element.type === 'password') {
element.type = 'text';
} else { } else {
this.$refs.masterPassword.type = 'password';
element.type = 'password';
} }
}, },
cleanErrors(){ cleanErrors(){
this.showPassword = false;
this.showCopyBtn = false;
clearTimeout(this.cleanTimeout);
this.generatedPassword = '';
this.showError = false; this.showError = false;
}, },
cleanFormInSeconds(seconds){ cleanFormInSeconds(seconds){
@@ -352,6 +337,7 @@
return; return;
} }


this.generatingPassword = true;
this.cleanErrors(); this.cleanErrors();
this.fingerprint = this.masterPassword; this.fingerprint = this.masterPassword;


@@ -365,14 +351,22 @@
version: this.password.version || this.version, version: this.password.version || this.version,
}; };
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(generatedPassword => { return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(generatedPassword => {
this.showCopyBtn = true;
this.generatingPassword = false;
this.generatedPassword = generatedPassword; this.generatedPassword = generatedPassword;
window.document.getElementById('copyPasswordButton').setAttribute('data-clipboard-text', generatedPassword); window.document.getElementById('copyPasswordButton').setAttribute('data-clipboard-text', generatedPassword);
this.$store.dispatch('PASSWORD_GENERATED'); this.$store.dispatch('PASSWORD_GENERATED');
}); });
}, },
selectVersion(event){
this.password.version = parseInt(event.target.value);
setDefaultVersion(version){
this.$store.commit('CHANGE_VERSION', {version});
},
toggleVersion(){
if (this.password.version === 1) {
this.password.version = 2;
} else {
this.password.version = 1;
}
this.$store.commit('CHANGE_VERSION', {version: this.password.version});
}, },
getDayBeforeV2(){ getDayBeforeV2(){
var oneDay = 24 * 60 * 60 * 1000; var oneDay = 24 * 60 * 60 * 1000;


Loading…
Cancel
Save