Browse Source

extract entry form in its own component

pull/342/head
Guillaume Vincent 8 years ago
parent
commit
9811ce6b9f
3 changed files with 197 additions and 153 deletions
  1. +122
    -0
      src/app/Entries/EntryForm.vue
  2. +26
    -137
      src/app/Entries/newEntry.vue
  3. +49
    -16
      src/app/Index.vue

+ 122
- 0
src/app/Entries/EntryForm.vue View File

@@ -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>

+ 26
- 137
src/app/Entries/newEntry.vue View File

@@ -1,13 +1,12 @@
<template> <template>
<div class="row"> <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"> data-target="#newEntryModal">
create new password
{{{ $t('entry.create_new_entry') }}}
</button> </button>
</div> </div>
</div> </div>

<div class="modal fade" id="newEntryModal" tabindex="-1" role="dialog" aria-labelledby="newEntry" <div class="modal fade" id="newEntryModal" tabindex="-1" role="dialog" aria-labelledby="newEntry"
aria-hidden="true"> aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
@@ -16,162 +15,52 @@
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </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>
<div class="modal-body text-xs-left"> <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>
<div class="modal-footer"> <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>
</div> </div>
</div> </div>
</template> </template>
<script type="text/ecmascript-6"> <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 http from '../../services/http';
import logging from '../../services/logging'; import logging from '../../services/logging';
import EntryForm from './EntryForm';


export default { export default {
data() { data() {
return { 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: { methods: {
create() { 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')); logging.error(this.$t('entries.site_mandatory'));
return; return;
} }
http.entries.create(entry)
http.entries.create(this.entry)
.then(() => { .then(() => {
$('#newEntryModal').modal('hide'); $('#newEntryModal').modal('hide');
logging.success(this.$t('entries.entry_created')); logging.success(this.$t('entries.entry_created'));


+ 49
- 16
src/app/Index.vue View File

@@ -3,35 +3,63 @@
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.30); box-shadow: 0 2px 15px rgba(0, 0, 0, 0.30);
cursor: pointer; 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> </style>
<template> <template>
<div id="index"> <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="row">
<div class="col-lg-6 ">
<div class="col-md-6 p-t-1">
<div id="searchEntries bg-card-white"> <div id="searchEntries bg-card-white">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="search-addon"> <span class="input-group-addon" id="search-addon">
<i class="fa fa-search"></i> <i class="fa fa-search"></i>
</span> </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>
</div> </div>
<div class="col-lg-6">
<div class="col-md-6 p-t-1">
<new-entry></new-entry> <new-entry></new-entry>
</div> </div>
</div> </div>
<div class="row m-t-3">
<div class="row m-t-2">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="card-columns"> <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"> <blockquote class="card-blockquote">
<p>{{ entry.site }}</p> <p>{{ entry.site }}</p>
<footer> <footer>
<small class="text-muted"> <small class="text-muted">
Email / Username : {{ entry.email }}
{{ entry.email }}
</small> </small>
</footer> </footer>
</blockquote> </blockquote>
@@ -41,21 +69,21 @@
</div> </div>
<div class="row m-t-1"> <div class="row m-t-1">
<div class="paginate"> <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" <button class="btn btn-primary btn-sm" v-if="count > limit"
:disabled="(currentPage*limit >= count)" :disabled="(currentPage*limit >= count)"
@click="getPreviousEntries()"> @click="getPreviousEntries()">
précédent
{{ $t('index.previous') }}
</button> </button>
</div> </div>
<div class="col-sm-4 text-xs-center">
<div class="col-xs-4 text-xs-center">
{{ currentPage }} / {{ numberPages }} {{ currentPage }} / {{ numberPages }}
</div> </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" <button class="btn btn-primary btn-sm" v-if="count > limit"
:disabled="(currentPage===1)" :disabled="(currentPage===1)"
@click="getNextEntries()"> @click="getNextEntries()">
suivant
{{ $t('index.next') }}
</button> </button>
</div> </div>
</div> </div>
@@ -64,7 +92,8 @@
</div> </div>
</template> </template>
<script type="text/ecmascript-6"> <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'; import http from '../services/http';
export default { export default {
data() { data() {
@@ -84,7 +113,7 @@
this.getEntries(this.limit, this.offset); this.getEntries(this.limit, this.offset);
}, },
methods: { methods: {
getEntries(limit, offset, search=''){
getEntries(limit, offset, search = ''){
http.entries.all(limit, offset, search).then((response) => { http.entries.all(limit, offset, search).then((response) => {
this.entries = response.data.results; this.entries = response.data.results;
this.count = response.data.count; this.count = response.data.count;
@@ -101,8 +130,12 @@
this.offset = (this.currentPage - 1) * this.limit; this.offset = (this.currentPage - 1) * this.limit;
this.getEntries(this.limit, this.offset); this.getEntries(this.limit, this.offset);
}, },
copyPassword(entry){
alert('password copied !');
},
openEntry(entry){ 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){ filterEntry(query){
this.getEntries(this.limit, this.offset, query); this.getEntries(this.limit, this.offset, query);


Loading…
Cancel
Save