瀏覽代碼

make version more visible and accessible

pull/342/head
Guillaume Vincent 8 年之前
父節點
當前提交
f58dc94a9b
共有 7 個檔案被更改,包括 131 行新增109 行删除
  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 查看文件

@@ -6,9 +6,21 @@
<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">
<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>
<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>
</body>
</html>

+ 19
- 2
src/LessPass.vue 查看文件

@@ -3,6 +3,20 @@
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 {
text-decoration: none;
color: white;
@@ -13,7 +27,8 @@
}
</style>
<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>
<div class="card-block">
<router-view></router-view>
@@ -22,12 +37,14 @@
</template>
<script type="text/ecmascript-6">
import Menu from './components/Menu.vue';
import {mapGetters} from 'vuex';

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

+ 1
- 1
src/api/tooltip.js 查看文件

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


+ 5
- 4
src/components/Menu.vue 查看文件

@@ -24,10 +24,11 @@
</style>
<template>
<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="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">
<i class="fa fa-save ml-1 fa-clickable" v-if="passwordStatus=='DIRTY'"></i>
</span>
@@ -36,10 +37,10 @@
</span>
</div>
<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>
</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>
</button>
</div>


+ 4
- 5
src/store.js 查看文件

@@ -22,12 +22,12 @@ const defaultPassword = {
length: 12,
counter: 1
};
function getDefaultPasswordProfile(version) {
function getDefaultPasswordProfile(version, passwordProfile = {}) {
if (version === 1) {
return Object.assign({}, defaultPassword, {version: 1, length: 12});
return Object.assign({}, defaultPassword, passwordProfile, {version: 1, length: 12});
}
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
},
CHANGE_VERSION(state, {version}){
state.password = getDefaultPasswordProfile(version);
state.password = getDefaultPasswordProfile(version, state.password);
state.version = version;
storage.save({version});
},
};



+ 6
- 7
src/views/Login.vue 查看文件

@@ -34,7 +34,8 @@
class="form-control"
required
placeholder="LessPass password"
v-model="password">
v-model="password"
v-on:keyup.enter.prevent="signIn">
<small class="form-text text-muted">
<span v-if="errors.passwordRequired" class="text-danger">A password is required</span>
<label class="form-check-label">
@@ -85,12 +86,10 @@
</button>
</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>
</form>
</template>


+ 83
- 89
src/views/PasswordGenerator.vue 查看文件

@@ -82,72 +82,76 @@
autocomplete="new-password"
autocorrect="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 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 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 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>
</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">
<i class="fa fa-sliders" aria-hidden="true"></i>
</button>
</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 class="form-group row" v-if="showOptions">
<div class="col-xs-5">
<div class="col-xs-6">
<label for="passwordLength">Length</label>
<div class="input-group">
<input class="form-control" type="number" id="passwordLength" v-model="password.length" min="4">
@@ -159,7 +163,7 @@
</span>
</div>
</div>
<div class="col-xs-5 offset-xs-2">
<div class="col-xs-6">
<label for="passwordCounter">Counter</label>
<div class="input-group">
<input class="form-control" type="number" id="passwordCounter" v-model="password.counter" min="1">
@@ -172,38 +176,19 @@
</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="alert alert-danger" role="alert">
site, login and master password fields are mandatory
</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>
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
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>
</div>
</div>
@@ -264,9 +249,8 @@
generatedPassword: '',
cleanTimeout: null,
showOptions: false,
showPassword: false,
showCopyBtn: false,
showError: false
showError: false,
generatingPassword: false
}
},
watch: {
@@ -313,6 +297,7 @@
},
'masterPassword': function () {
this.cleanErrors();
this.cleanFormInSeconds(30);
this.showFingerprint();
}
},
@@ -320,16 +305,16 @@
showFingerprint: debounce(function () {
this.fingerprint = this.masterPassword;
}, 3000),
showMasterPassword(){
if (this.$refs.masterPassword.type === 'password') {
this.$refs.masterPassword.type = 'text';
togglePasswordType(element){
if (element.type === 'password') {
element.type = 'text';
} else {
this.$refs.masterPassword.type = 'password';
element.type = 'password';
}
},
cleanErrors(){
this.showPassword = false;
this.showCopyBtn = false;
clearTimeout(this.cleanTimeout);
this.generatedPassword = '';
this.showError = false;
},
cleanFormInSeconds(seconds){
@@ -352,6 +337,7 @@
return;
}

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

@@ -365,14 +351,22 @@
version: this.password.version || this.version,
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(generatedPassword => {
this.showCopyBtn = true;
this.generatingPassword = false;
this.generatedPassword = generatedPassword;
window.document.getElementById('copyPasswordButton').setAttribute('data-clipboard-text', generatedPassword);
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(){
var oneDay = 24 * 60 * 60 * 1000;


Loading…
取消
儲存