@@ -0,0 +1,122 @@ | |||
<template> | |||
<form id="password-generator-form"> | |||
<div class="form-group row"> | |||
<div class="col-lg-6 m-t-1"> | |||
<label for="pg-email" class="sr-only"> | |||
{{ $t('passwordgenerator.who_are_you') }} | |||
</label> | |||
<input id="pg-email" | |||
class="form-control" | |||
type="text" | |||
placeholder="{{ $t('passwordgenerator.who_are_you') }}" | |||
value="{{entry.email}}" | |||
v-model="entry.email" | |||
autofocus | |||
autocomplete="off" | |||
autocorrect="off" | |||
autocapitalize="none"> | |||
</div> | |||
</div> | |||
<div class="form-group row"> | |||
<div class="col-lg-12"> | |||
<label for="pg-site" class="sr-only"> | |||
{{ $t('passwordgenerator.where_are_you_going') }} | |||
</label> | |||
<input id="pg-site" | |||
class="form-control" | |||
list="domains" | |||
type="text" | |||
placeholder="{{ $t('passwordgenerator.where_are_you_going') }}" | |||
value="{{entry.site}}" | |||
v-model="entry.site" | |||
autocorrect="off" | |||
autocapitalize="none"> | |||
<datalist id="domains"> | |||
<option v-for="domain in domains" v-bind:value="domain"> | |||
</datalist> | |||
</div> | |||
</div> | |||
<div class="form-group row m-b-0"> | |||
<div class="col-lg-12"> | |||
<div class="row"> | |||
<div class="col-lg-5"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="lowercase" value="lowercase" | |||
v-model="entry.password.settings"> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.lowercase_options') }} | |||
</label> | |||
</div> | |||
<div class="col-lg-7"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="uppercase" value="uppercase" | |||
v-model="entry.password.settings"> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.uppercase_options') }} | |||
</label> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-5"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="numbers" value="numbers" | |||
v-model="entry.password.settings"> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.numbers_options') }} | |||
</label> | |||
</div> | |||
<div class="col-lg-7"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="symbols" value="symbols" | |||
v-model="entry.password.settings"> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.symbols_options') }} | |||
</label> | |||
</div> | |||
</div> | |||
<div class="row m-t-1"> | |||
<div class="col-lg-5 m-b-1"> | |||
<label for="passwordLength" class="sr-only"> | |||
{{ $t('passwordgenerator.length') }} | |||
</label> | |||
<div class="input-group input-group-sm"> | |||
<span class="input-group-addon" id="passwordLengthAddon"> | |||
{{ $t('passwordgenerator.length') }} | |||
</span> | |||
<input type="number" class="form-control" id="passwordLength" | |||
aria-describedby="passwordLengthAddon" | |||
v-model="entry.password.length" | |||
value="{{entry.password.length}}" min="6" max="64"> | |||
</div> | |||
</div> | |||
<div class="col-lg-4 m-b-1"> | |||
<label for="passwordCounter" class="sr-only"> | |||
{{ $t('passwordgenerator.counter') }} | |||
</label> | |||
<div class="input-group input-group-sm"> | |||
<span class="input-group-addon" id="passwordCounterAddon"> | |||
{{ $t('passwordgenerator.counter') }} | |||
</span> | |||
<input type="number" class="form-control" id="passwordCounter" | |||
aria-describedby="passwordCounterAddon" | |||
v-model="entry.password.counter" | |||
value="{{entry.password.counter}}" min="1" max="100"> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</form> | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
import topDomains from '../../landing-page/PasswordGenerator/top-domains.json'; | |||
export default { | |||
data() { | |||
return { | |||
domains: topDomains.domains | |||
}; | |||
}, | |||
props: ['entry'] | |||
}; | |||
</script> |
@@ -1,13 +1,12 @@ | |||
<template> | |||
<div class="row"> | |||
<div class="col-lg-12"> | |||
<button type="button" class="btn btn-primary pull-xs-right" data-toggle="modal" | |||
<div class="col-xs-12 col-md-8 col-lg-6 pull-xs-left pull-md-right"> | |||
<button type="button" class="btn btn-primary btn-block" data-toggle="modal" | |||
data-target="#newEntryModal"> | |||
create new password | |||
{{{ $t('entry.create_new_entry') }}} | |||
</button> | |||
</div> | |||
</div> | |||
<div class="modal fade" id="newEntryModal" tabindex="-1" role="dialog" aria-labelledby="newEntry" | |||
aria-hidden="true"> | |||
<div class="modal-dialog" role="document"> | |||
@@ -16,162 +15,52 @@ | |||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |||
<span aria-hidden="true">×</span> | |||
</button> | |||
<h4 class="modal-title" id="newEntry">Create new password</h4> | |||
<h4 class="modal-title" id="newEntry">{{{ $t('entry.Create_new_entry') }}}</h4> | |||
</div> | |||
<div class="modal-body text-xs-left"> | |||
<form id="password-generator-form"> | |||
<div class="form-group row"> | |||
<div class="col-lg-6 m-t-1"> | |||
<label for="pg-email" class="sr-only"> | |||
{{ $t('passwordgenerator.who_are_you') }} | |||
</label> | |||
<input id="pg-email" | |||
class="form-control" | |||
type="text" | |||
placeholder="{{ $t('passwordgenerator.who_are_you') }}" | |||
value="{{email}}" | |||
v-model="email" | |||
autofocus | |||
autocomplete="off" | |||
autocorrect="off" | |||
autocapitalize="none"> | |||
</div> | |||
</div> | |||
<div class="form-group row"> | |||
<div class="col-lg-12"> | |||
<label for="pg-site" class="sr-only"> | |||
{{ $t('passwordgenerator.where_are_you_going') }} | |||
</label> | |||
<input id="pg-site" | |||
class="form-control" | |||
list="domains" | |||
type="text" | |||
placeholder="{{ $t('passwordgenerator.where_are_you_going') }}" | |||
v-model="site" | |||
autocorrect="off" | |||
autocapitalize="none"> | |||
<datalist id="domains"> | |||
<option v-for="domain in domains" v-bind:value="domain"> | |||
</datalist> | |||
</div> | |||
</div> | |||
<div class="form-group row m-b-0"> | |||
<div class="col-lg-12"> | |||
<div class="row"> | |||
<div class="col-lg-5"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="lowercase" value="lowercase" | |||
v-model="passwordInfo.settings" checked> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.lowercase_options') }} | |||
</label> | |||
</div> | |||
<div class="col-lg-7"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="uppercase" value="uppercase" | |||
v-model="passwordInfo.settings" checked> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.uppercase_options') }} | |||
</label> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-5"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="numbers" value="numbers" | |||
v-model="passwordInfo.settings" | |||
checked> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.numbers_options') }} | |||
</label> | |||
</div> | |||
<div class="col-lg-7"> | |||
<label class="c-input c-checkbox"> | |||
<input type="checkbox" id="symbols" value="symbols" | |||
v-model="passwordInfo.settings" | |||
checked> | |||
<span class="c-indicator"></span> | |||
{{ $t('passwordgenerator.symbols_options') }} | |||
</label> | |||
</div> | |||
</div> | |||
<div class="row m-t-1"> | |||
<div class="col-lg-5 m-b-1"> | |||
<label for="passwordLength" class="sr-only"> | |||
{{ $t('passwordgenerator.length') }} | |||
</label> | |||
<div class="input-group input-group-sm"> | |||
<span class="input-group-addon" id="passwordLengthAddon"> | |||
{{ $t('passwordgenerator.length') }} | |||
</span> | |||
<input type="number" class="form-control" id="passwordLength" | |||
aria-describedby="passwordLengthAddon" | |||
v-model="passwordInfo.length" | |||
value="12" min="6" max="64"> | |||
</div> | |||
</div> | |||
<div class="col-lg-4 m-b-1"> | |||
<label for="passwordCounter" class="sr-only"> | |||
{{ $t('passwordgenerator.counter') }} | |||
</label> | |||
<div class="input-group input-group-sm"> | |||
<span class="input-group-addon" id="passwordCounterAddon"> | |||
{{ $t('passwordgenerator.counter') }} | |||
</span> | |||
<input type="number" class="form-control" id="passwordCounter" | |||
aria-describedby="passwordCounterAddon" | |||
v-model="passwordInfo.counter" | |||
value="1" min="1" max="100"> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</form> | |||
<entry-form :entry="entry" v-bind:prop.sync></entry-form> | |||
</div> | |||
<div class="modal-footer"> | |||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> | |||
<button type="button" class="btn btn-primary" @click="create()">Create</button> | |||
<button type="button" class="btn btn-secondary" data-dismiss="modal"> | |||
{{{ $t('entry.Cancel') }}} | |||
</button> | |||
<button type="button" class="btn btn-primary" @click="create()"> | |||
{{{ $t('entry.Create') }}} | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
import 'bootstrap/dist/js/umd/modal'; | |||
import topDomains from '../../landing-page/PasswordGenerator/top-domains.json'; | |||
import http from '../../services/http'; | |||
import logging from '../../services/logging'; | |||
import EntryForm from './EntryForm'; | |||
export default { | |||
data() { | |||
return { | |||
email: '', | |||
site: '', | |||
passwordInfo: { | |||
counter: 1, | |||
length: 12, | |||
settings: ["lowercase", "uppercase", "numbers", "symbols"] | |||
}, | |||
domains: topDomains.domains | |||
entry: { | |||
email: '', | |||
site: '', | |||
password: { | |||
counter: 1, | |||
length: 12, | |||
settings: ["lowercase", "uppercase", "numbers", "symbols"] | |||
}, | |||
} | |||
}; | |||
}, | |||
components: { | |||
EntryForm, | |||
}, | |||
methods: { | |||
create() { | |||
var entry = { | |||
email: this.email, | |||
site: this.site, | |||
password: { | |||
counter: this.passwordInfo.counter, | |||
length: this.passwordInfo.length, | |||
settings: this.passwordInfo.settings, | |||
} | |||
}; | |||
if (entry.site === '') { | |||
if (this.entry.site === '') { | |||
logging.error(this.$t('entries.site_mandatory')); | |||
return; | |||
} | |||
http.entries.create(entry) | |||
http.entries.create(this.entry) | |||
.then(() => { | |||
$('#newEntryModal').modal('hide'); | |||
logging.success(this.$t('entries.entry_created')); | |||
@@ -3,35 +3,63 @@ | |||
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.30); | |||
cursor: pointer; | |||
} | |||
.card .edit-icon { | |||
display: block; | |||
position: absolute; | |||
top: 10px; | |||
right: 10px; | |||
} | |||
@media (min-width: 480px) { | |||
.card .edit-icon { | |||
display: none; | |||
} | |||
.card:hover .edit-icon:hover { | |||
color: inherit; | |||
} | |||
.card:hover .edit-icon { | |||
display: block; | |||
position: absolute; | |||
top: 10px; | |||
right: 10px; | |||
} | |||
} | |||
</style> | |||
<template> | |||
<div id="index"> | |||
<div class="container text-xs-center p-t-3"> | |||
<div class="container text-xs-center p-t-1"> | |||
<div class="row"> | |||
<div class="col-lg-6 "> | |||
<div class="col-md-6 p-t-1"> | |||
<div id="searchEntries bg-card-white"> | |||
<div class="input-group"> | |||
<span class="input-group-addon" id="search-addon"> | |||
<i class="fa fa-search"></i> | |||
</span> | |||
<input type="text" class="form-control" placeholder="search" v-model="search" | |||
aria-describedby="search-addon" @keyup="filterEntry(search) | debounce 500"> | |||
<input type="text" class="form-control" placeholder="{{ $t('index.search') }}" | |||
v-model="search" aria-describedby="search-addon" | |||
@keyup="filterEntry(search) | debounce 500"> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="col-lg-6"> | |||
<div class="col-md-6 p-t-1"> | |||
<new-entry></new-entry> | |||
</div> | |||
</div> | |||
<div class="row m-t-3"> | |||
<div class="row m-t-2"> | |||
<div class="col-lg-12"> | |||
<div class="card-columns"> | |||
<div class="card card-block" v-for="entry in entries" @click="openEntry(entry)"> | |||
<div class="card card-block" v-for="entry in entries" | |||
v-on:dblclick="copyPassword(entry)"> | |||
<i class="fa fa-pencil-square-o fa-lg edit-icon text-muted" | |||
v-on:click="openEntry(entry)"></i> | |||
<blockquote class="card-blockquote"> | |||
<p>{{ entry.site }}</p> | |||
<footer> | |||
<small class="text-muted"> | |||
Email / Username : {{ entry.email }} | |||
{{ entry.email }} | |||
</small> | |||
</footer> | |||
</blockquote> | |||
@@ -41,21 +69,21 @@ | |||
</div> | |||
<div class="row m-t-1"> | |||
<div class="paginate"> | |||
<div class="col-sm-4 text-xs-left"> | |||
<div class="col-xs-4 text-xs-left"> | |||
<button class="btn btn-primary btn-sm" v-if="count > limit" | |||
:disabled="(currentPage*limit >= count)" | |||
@click="getPreviousEntries()"> | |||
précédent | |||
{{ $t('index.previous') }} | |||
</button> | |||
</div> | |||
<div class="col-sm-4 text-xs-center"> | |||
<div class="col-xs-4 text-xs-center"> | |||
{{ currentPage }} / {{ numberPages }} | |||
</div> | |||
<div class="col-sm-4 text-xs-right"> | |||
<div class="col-xs-4 text-xs-right"> | |||
<button class="btn btn-primary btn-sm" v-if="count > limit" | |||
:disabled="(currentPage===1)" | |||
@click="getNextEntries()"> | |||
suivant | |||
{{ $t('index.next') }} | |||
</button> | |||
</div> | |||
</div> | |||
@@ -64,7 +92,8 @@ | |||
</div> | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
import NewEntry from './Entries/newEntry.vue'; | |||
import 'bootstrap/dist/js/umd/modal'; | |||
import NewEntry from './Entries/newEntry'; | |||
import http from '../services/http'; | |||
export default { | |||
data() { | |||
@@ -84,7 +113,7 @@ | |||
this.getEntries(this.limit, this.offset); | |||
}, | |||
methods: { | |||
getEntries(limit, offset, search=''){ | |||
getEntries(limit, offset, search = ''){ | |||
http.entries.all(limit, offset, search).then((response) => { | |||
this.entries = response.data.results; | |||
this.count = response.data.count; | |||
@@ -101,8 +130,12 @@ | |||
this.offset = (this.currentPage - 1) * this.limit; | |||
this.getEntries(this.limit, this.offset); | |||
}, | |||
copyPassword(entry){ | |||
alert('password copied !'); | |||
}, | |||
openEntry(entry){ | |||
this.$router.go(`/app/entries/${entry.id}/`); | |||
alert(`redirect to /app/entries/${entry.id}/`); | |||
// this.$router.go(`/app/entries/${entry.id}/`); | |||
}, | |||
filterEntry(query){ | |||
this.getEntries(this.limit, this.offset, query); | |||