Make the accounts sortable and persist new order.

Deactivate Pull-to-refresh feature to prevent side effects
This commit is contained in:
Bubka 2020-03-27 22:36:01 +01:00
parent 361e6a87f1
commit eaabe6e9e3
5 changed files with 83 additions and 41 deletions

View File

@ -62,6 +62,19 @@ public function show(TwoFAccount $twofaccount)
}
/**
* Save new order.
*
* @param \App\TwoFAccount $twofaccount
* @return \Illuminate\Http\Response
*/
public function reorder(Request $request)
{
TwoFAccount::setNewOrder($request->orderedIds);
return response()->json('order saved', 200);
}
/**
* Generate a TOTP
*

View File

@ -14,7 +14,8 @@ import {
faLock,
faLockOpen,
faSearch,
faEllipsisH
faEllipsisH,
faBars
} from '@fortawesome/free-solid-svg-icons'
library.add(
@ -27,7 +28,8 @@ library.add(
faLock,
faLockOpen,
faSearch,
faEllipsisH
faEllipsisH,
faBars
);
Vue.component('font-awesome-icon', FontAwesomeIcon)

View File

@ -26,39 +26,46 @@
</div>
</div>
<!-- accounts -->
<vue-pull-refresh :on-refresh="onRefresh" :config="{
<!-- <vue-pull-refresh :on-refresh="onRefresh" :config="{
errorLabel: 'error',
startLabel: '',
readyLabel: '',
loadingLabel: 'refreshing'
}" class="accounts columns is-multiline is-centered">
<div class="tfa column is-narrow has-text-white" v-for="account in filteredAccounts">
<div class="tfa-container">
<transition name="slideCheckbox">
<div class="tfa-checkbox" v-if="editMode">
<div class="field">
<input class="is-checkradio is-small is-white" :id="'ckb_' + account.id" :value="account.id" type="checkbox" :name="'ckb_' + account.id" v-model="selectedAccounts">
<label :for="'ckb_' + account.id"></label>
</div>
</div>
</transition>
<div class="tfa-content is-size-3 is-size-4-mobile" @click.stop="showAccount(account)">
<div class="tfa-text has-ellipsis">
<img :src="'/storage/icons/' + account.icon" v-if="account.icon">
{{ account.service }}
<span class="is-family-primary is-size-6 is-size-7-mobile has-text-grey ">{{ account.account }}</span>
}" > -->
<draggable v-model="filteredAccounts" @end="saveOrder" handle=".tfa-dots" class="accounts columns is-multiline is-centered">
<div class="tfa column is-narrow has-text-white" v-for="account in filteredAccounts" :key="account.id">
<div class="tfa-container">
<transition name="slideCheckbox">
<div class="tfa-checkbox" v-if="editMode">
<div class="field">
<input class="is-checkradio is-small is-white" :id="'ckb_' + account.id" :value="account.id" type="checkbox" :name="'ckb_' + account.id" v-model="selectedAccounts">
<label :for="'ckb_' + account.id"></label>
</div>
</div>
</transition>
<div class="tfa-content is-size-3 is-size-4-mobile" @click.stop="showAccount(account)">
<div class="tfa-text has-ellipsis">
<img :src="'/storage/icons/' + account.icon" v-if="account.icon">
{{ account.service }}
<span class="is-family-primary is-size-6 is-size-7-mobile has-text-grey ">{{ account.account }}</span>
</div>
</div>
<transition name="fadeInOut">
<div class="tfa-edit has-text-grey" v-if="editMode">
<router-link :to="{ name: 'edit', params: { twofaccountId: account.id }}" class="tag is-dark is-rounded">
{{ $t('commons.edit') }}
</router-link>
</div>
</transition>
<transition name="fadeInOut">
<div class="tfa-dots has-text-grey" v-if="editMode">
<font-awesome-icon :icon="['fas', 'bars']" />
</div>
</transition>
</div>
<transition name="fadeInOut">
<div class="tfa-dots has-text-grey" v-if="editMode">
<router-link :to="{ name: 'edit', params: { twofaccountId: account.id }}" class="tag is-dark is-rounded">
{{ $t('commons.edit') }}
</router-link>
</div>
</transition>
</div>
</div>
</vue-pull-refresh>
</draggable>
<!-- </vue-pull-refresh> -->
</div>
<!-- No account -->
<div class="container has-text-centered" v-show="showQuickForm">
@ -132,6 +139,7 @@
import TwofaccountShow from '../components/TwofaccountShow'
import Form from './../components/Form'
import vuePullRefresh from 'vue-pull-refresh';
import draggable from 'vuedraggable'
export default {
data(){
@ -149,12 +157,17 @@
},
computed: {
filteredAccounts() {
return this.accounts.filter(
item => {
return item.service.toLowerCase().includes(this.search.toLowerCase()) || item.account.toLowerCase().includes(this.search.toLowerCase());
}
);
filteredAccounts: {
get: function() {
return this.accounts.filter(
item => {
return item.service.toLowerCase().includes(this.search.toLowerCase()) || item.account.toLowerCase().includes(this.search.toLowerCase());
}
);
},
set: function(reorderedAccounts) {
this.accounts = reorderedAccounts
}
},
showAccounts() {
@ -179,7 +192,8 @@
components: {
Modal,
TwofaccountShow,
'vue-pull-refresh': vuePullRefresh
'vue-pull-refresh': vuePullRefresh,
draggable,
},
methods: {
@ -241,6 +255,10 @@
}
},
saveOrder() {
this.axios.patch('/api/twofaccounts/reorder', {orderedIds: this.accounts.map(a => a.id)})
},
deleteAccount: function (id) {
if(confirm(this.$t('twofaccounts.confirm.delete'))) {
this.axios.delete('/api/twofaccounts/' + id)

View File

@ -52,7 +52,6 @@ a:hover {
.tfa {
border-radius: 6px;
text-align: center;
cursor: pointer;
background-color: hsl(0, 0%, 10%); /*black-bis from Bulma*/
padding: 0.75rem 1.5rem;
margin: 0.5rem;
@ -89,22 +88,26 @@ a:hover {
}
.tfa-container > div:last-of-type {
padding: 0 0.5rem 0 0;
padding: 0 1rem 0 0;
}
}
.tfa-checkbox, .tfa-dots {
.tfa-checkbox, .tfa-dots, .tfa-edit {
display: flex;
align-items: center;
padding: 0.5rem 0 0 0;
}
@media screen and (max-width: 768px) {
.tfa-checkbox, .tfa-dots {
.tfa-checkbox, .tfa-dots, .tfa-edit {
display: flex;
align-items: center;
padding: 0
}
.tfa-dots {
margin-left: 1.5rem;
}
}
.tfa-content {
@ -118,7 +121,7 @@ a:hover {
}
.tfa-dots {
// order: 3;
cursor: grab;
}
@media screen and (max-width: 768px) {
@ -130,9 +133,13 @@ a:hover {
order: 2;
}
.tfa-dots {
.tfa-edit {
order: 3;
}
.tfa-dots {
order: 4;
}
}
@media screen and (min-width: 769px) {
@ -146,6 +153,7 @@ a:hover {
.tfa-text {
display: block;
max-width: 300px;
cursor: pointer;
}
.tfa img {

View File

@ -37,6 +37,7 @@
});
Route::delete('twofaccounts/batch', 'TwoFAccountController@batchDestroy');
Route::patch('twofaccounts/reorder', 'TwoFAccountController@reorder');
Route::apiResource('twofaccounts', 'TwoFAccountController');
Route::post('twofaccounts/otp', 'TwoFAccountController@generateOTP')->name('twofaccounts.generateOTP');
Route::post('qrcode/decode', 'QrCodeController@decode');