Set up the Accounts view with components

This commit is contained in:
Bubka
2023-10-20 13:28:17 +02:00
parent 4055a52daf
commit 5f83b5d70b
11 changed files with 909 additions and 19 deletions

View File

@ -0,0 +1,73 @@
<script setup>
import twofaccountService from '@/services/twofaccountService'
import groupService from '@/services/groupService'
import { UseColorMode } from '@vueuse/components'
const props = defineProps({
showDestinationGroupSelector: Boolean,
selectedAccountsIds: Array,
groups: Array
})
const destinationGroupId = ref(null)
const emit = defineEmits(['update:showDestinationGroupSelector, accounts-moved'])
/**
* Move accounts selected from the Edit mode to another group or withdraw them
*/
async function moveAccounts() {
// Backend will associate all provided accounts with the selected group in the same move
// or withdraw the accounts if destination is 'no group' (id = 0)
if (destinationGroupId.value === 0) {
await twofaccountService.withdraw(props.selectedAccountsIds)
}
else await groupService.assign(props.selectedAccountsIds, destinationGroupId.value)
emit('accounts-moved')
}
</script>
<template>
<!-- Group selector -->
<div class="container group-selector">
<div class="columns is-centered is-multiline">
<div class="column is-full has-text-centered">
{{ $t('groups.move_selected_to') }}
</div>
<div class="column is-one-third-tablet is-one-quarter-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
<div class="columns is-multiline">
<div class="column is-full" v-for="group in groups" :key="group.id">
<UseColorMode v-slot="{ mode }">
<button class="button is-fullwidth" :class="{'is-link' : destinationGroupId === group.id, 'is-dark has-text-light is-outlined': mode == 'dark'}" @click="destinationGroupId = group.id">
<span v-if="group.id === 0" class="is-italic">
{{ $t('groups.no_group') }}
</span>
<span v-else>
{{ group.name }}
</span>
</button>
</UseColorMode>
</div>
</div>
<div class="columns is-centered">
<div class="column has-text-centered">
<RouterLink :to="{ name: 'groups' }" >{{ $t('groups.manage_groups') }}</RouterLink>
</div>
</div>
</div>
</div>
<VueFooter :showButtons="true">
<!-- Move to selected group button -->
<p class="control">
<button class="button is-link is-rounded" @click="moveAccounts">{{ $t('commons.move') }}</button>
</p>
<!-- Cancel button -->
<p class="control">
<UseColorMode v-slot="{ mode }">
<button id="btnCancel" class="button is-rounded" :class="{'is-dark' : mode == 'dark'}" @click="$emit('update:showDestinationGroupSelector', false)">{{ $t('commons.cancel') }}</button>
</UseColorMode>
</p>
</VueFooter>
</div>
</template>

View File

@ -0,0 +1,56 @@
<script setup>
import userService from '@/services/userService'
import { useUserStore } from '@/stores/user'
import { UseColorMode } from '@vueuse/components'
const user = useUserStore()
const props = defineProps({
showGroupSwitch: Boolean,
groups: Array
})
const emit = defineEmits(['update:showGroupSwitch'])
/**
* Sets the selected group as the active group
*/
function setActiveGroup(id) {
user.preferences.activeGroup = id
if( user.preferences.rememberActiveGroup ) {
userService.updatePreference('activeGroup', id)
}
emit('update:showGroupSwitch', false)
}
</script>
<template>
<div id="groupSwitch" class="container groups">
<div class="columns is-centered">
<div class="column is-one-third-tablet is-one-quarter-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
<div class="columns is-multiline">
<div class="column is-full" v-for="group in groups" :key="group.id">
<UseColorMode v-slot="{ mode }">
<button class="button is-fullwidth" :class="{'is-dark has-text-light is-outlined': mode == 'dark'}" @click="setActiveGroup(group.id)">{{ group.name }}</button>
</UseColorMode>
</div>
</div>
<div class="columns is-centered">
<div class="column has-text-centered">
<RouterLink :to="{ name: 'groups' }" >{{ $t('groups.manage_groups') }}</RouterLink>
</div>
</div>
</div>
</div>
<VueFooter :showButtons="true">
<!-- Close Group switch button -->
<p class="control">
<UseColorMode v-slot="{ mode }">
<button id="btnClose" class="button is-rounded" :class="{'is-dark' : mode == 'dark'}" @click="$emit('update:showGroupSwitch', false)">{{ $t('commons.close') }}</button>
</UseColorMode>
</p>
</VueFooter>
</div>
</template>

View File

@ -0,0 +1,45 @@
<script setup>
const props = defineProps({
keyword: String
})
const searchInput = ref(null)
onMounted(() => {
document.addEventListener('keydown', keyListener)
})
onUnmounted(() => {
document.removeEventListener('keydown', keyListener)
})
/**
* Attach an event listen for ctrl+F
*/
function keyListener(e) {
if (e.key === "f" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
searchInput.value?.focus()
}
}
</script>
<template>
<div role="search" class="field">
<div class="control has-icons-right">
<input
ref="searchInput"
id="txtSearch"
type="search"
tabindex="1"
:aria-label="$t('commons.search')"
:title="$t('commons.search')"
class="input is-rounded is-search"
:value="keyword"
v-on:keyup="$emit('update:keyword', $event.target.value)">
<span class="icon is-small is-right">
<button v-if="keyword != ''" id="btnClearSearch" tabindex="1" :title="$t('commons.clear_search')" class="clear-selection delete" @click="$emit('update:keyword','')"></button>
<FontAwesomeIcon v-else :icon="['fas', 'search']" />
</span>
</div>
</div>
</template>

View File

@ -0,0 +1,30 @@
<script setup>
const props = defineProps({
selectedCount: Number
})
</script>
<template>
<div class="toolbar has-text-centered">
<div class="columns">
<div class="column">
<!-- selected label -->
<span class="has-text-grey mr-1">{{ selectedCount }}&nbsp;{{ $t('commons.selected') }}</span>
<!-- deselect all -->
<button id="btnUnselectAll" @click="$emit('clear-selected')" class="clear-selection delete mr-4" :style="{visibility: selectedCount > 0 ? 'visible' : 'hidden'}" :title="$t('commons.clear_selection')"></button>
<!-- select all button -->
<button id="btnSelectAll" @click="$emit('select-all')" class="button mr-5 has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.select_all')">
<span>{{ $t('commons.all') }}</span>
<FontAwesomeIcon class="ml-1" :icon="['fas', 'check-square']" />
</button>
<!-- sort asc/desc buttons -->
<button id="btnSortAscending" @click="$emit('sort-asc')" class="button has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.sort_ascending')">
<FontAwesomeIcon :icon="['fas', 'sort-alpha-down']" />
</button>
<button id="btnSortDescending" @click="$emit('sort-desc')" class="button has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.sort_descending')">
<FontAwesomeIcon :icon="['fas', 'sort-alpha-up']" />
</button>
</div>
</div>
</div>
</template>