mirror of
https://github.com/gotson/komga.git
synced 2025-12-22 00:13:30 +01:00
parent
9440654340
commit
28598cbef5
9 changed files with 290 additions and 146 deletions
53
komga-webui/src/components/FilterDrawer.vue
Normal file
53
komga-webui/src/components/FilterDrawer.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<template>
|
||||
<v-navigation-drawer
|
||||
v-model="display"
|
||||
right
|
||||
fixed
|
||||
temporary
|
||||
disable-route-watcher
|
||||
class="fill-height"
|
||||
>
|
||||
<slot></slot>
|
||||
|
||||
<template v-if="$slots.filter">
|
||||
<v-divider/>
|
||||
<v-subheader>FILTER</v-subheader>
|
||||
</template>
|
||||
<slot name="filter"></slot>
|
||||
|
||||
<template v-if="$slots.sort">
|
||||
<v-divider/>
|
||||
<v-subheader>SORT</v-subheader>
|
||||
</template>
|
||||
<slot name="sort"></slot>
|
||||
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FilterDrawer',
|
||||
data: () => {
|
||||
return {
|
||||
display: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: Boolean,
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.display = val
|
||||
},
|
||||
display (val) {
|
||||
!val && this.$emit('input', false)
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
@ -1,13 +1,5 @@
|
|||
<template>
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{on}">
|
||||
<v-btn icon v-on="on">
|
||||
<v-icon :color="filterCustom ? 'secondary' : null"
|
||||
>mdi-filter-variant
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list dense>
|
||||
<div v-for="(f, key) in filtersOptions"
|
||||
:key="key"
|
||||
>
|
||||
|
|
@ -29,26 +21,14 @@
|
|||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</div>
|
||||
|
||||
<template v-if="filterCustom">
|
||||
<v-divider/>
|
||||
|
||||
<v-list-item @click="clearAll" dense>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>Clear</v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FilterMenuButton',
|
||||
name: 'FilterList',
|
||||
props: {
|
||||
filtersOptions: {
|
||||
type: Object as () => FiltersOptions,
|
||||
|
|
@ -59,24 +39,7 @@ export default Vue.extend({
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
filterCustom (): boolean {
|
||||
let r = false
|
||||
for (const [key, value] of Object.entries(this.filtersActive)) {
|
||||
if (!this.$_.isEmpty(value)) r = true
|
||||
}
|
||||
return r
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clearAll () {
|
||||
let r = this.$_.cloneDeep(this.filtersActive)
|
||||
for (const key of Object.keys(r)) {
|
||||
r[key] = []
|
||||
}
|
||||
|
||||
this.$emit('update:filtersActive', r)
|
||||
},
|
||||
click (key: string, value: string) {
|
||||
let r = this.$_.cloneDeep(this.filtersActive)
|
||||
if (r[key].includes(value)) this.$_.pull(r[key], (value))
|
||||
86
komga-webui/src/components/FilterPanels.vue
Normal file
86
komga-webui/src/components/FilterPanels.vue
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<v-expansion-panels accordion multiple flat tile hover>
|
||||
<v-expansion-panel
|
||||
v-for="(f, key) in filtersOptions"
|
||||
:key="key"
|
||||
>
|
||||
<v-expansion-panel-header>
|
||||
<v-icon
|
||||
color="secondary"
|
||||
style="max-width: 24px"
|
||||
class="mr-2"
|
||||
@click.stop="clear(key)"
|
||||
>{{ groupActive(key) ? 'mdi-checkbox-marked' : '' }}
|
||||
</v-icon>
|
||||
{{ f.name }}
|
||||
</v-expansion-panel-header>
|
||||
<v-expansion-panel-content class="no-padding">
|
||||
<v-list dense>
|
||||
<v-list-item v-for="v in f.values"
|
||||
:key="v"
|
||||
@click.stop="click(key, v)"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon v-if="filtersActive[key].includes(v)" color="secondary">
|
||||
mdi-checkbox-marked
|
||||
</v-icon>
|
||||
<v-icon v-else>
|
||||
mdi-checkbox-blank-outline
|
||||
</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title class="text-capitalize">
|
||||
{{ v.toString().toLowerCase().replace('_', ' ') }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-expansion-panel-content>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FilterPanels',
|
||||
props: {
|
||||
filtersOptions: {
|
||||
type: Object as () => FiltersOptions,
|
||||
required: true,
|
||||
},
|
||||
filtersActive: {
|
||||
type: Object as () => FiltersActive,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clear (key: string) {
|
||||
let r = this.$_.cloneDeep(this.filtersActive)
|
||||
r[key] = []
|
||||
|
||||
this.$emit('update:filtersActive', r)
|
||||
},
|
||||
groupActive (key: string): boolean {
|
||||
for (let v of this.filtersOptions[key].values) {
|
||||
if (this.filtersActive[key].includes(v)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
click (key: string, value: string) {
|
||||
let r = this.$_.cloneDeep(this.filtersActive)
|
||||
if (r[key].includes(value)) this.$_.pull(r[key], (value))
|
||||
else r[key].push(value)
|
||||
|
||||
this.$emit('update:filtersActive', r)
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.no-padding .v-expansion-panel-content__wrap {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
57
komga-webui/src/components/SortList.vue
Normal file
57
komga-webui/src/components/SortList.vue
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<v-list dense>
|
||||
<v-list-item v-for="(item, index) in sortOptions"
|
||||
:key="index"
|
||||
@click="setSort(item)"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon color="secondary" v-if="item.key === sortActive.key && sortActive.order === 'asc'">
|
||||
mdi-chevron-up
|
||||
</v-icon>
|
||||
<v-icon color="secondary" v-if="item.key === sortActive.key && sortActive.order === 'desc'">
|
||||
mdi-chevron-down
|
||||
</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'SortList',
|
||||
props: {
|
||||
sortOptions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
sortDefault: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
sortActive: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setSort (sort: SortOption) {
|
||||
if (this.sortActive.key === sort.key) {
|
||||
if (this.sortActive.order === 'desc') {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'asc' })
|
||||
} else {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'desc' })
|
||||
}
|
||||
} else {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'desc' })
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
<template>
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{on}">
|
||||
<v-btn icon v-on="on">
|
||||
<v-icon :color="sortCustom ? 'secondary' : null"
|
||||
>mdi-sort-variant
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-for="(item, index) in sortOptions"
|
||||
:key="index"
|
||||
@click="setSort(item)"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon color="secondary" v-if="item.key === sortActive.key && sortActive.order === 'asc'">
|
||||
mdi-chevron-up
|
||||
</v-icon>
|
||||
<v-icon color="secondary" v-if="item.key === sortActive.key && sortActive.order === 'desc'">
|
||||
mdi-chevron-down
|
||||
</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'SortMenuButton',
|
||||
props: {
|
||||
sortOptions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
sortDefault: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
sortActive: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sortCustom (): boolean {
|
||||
return this.sortActive.key !== this.sortDefault.key || this.sortActive.order !== this.sortDefault.order
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setSort (sort: SortOption) {
|
||||
if (this.sortActive.key === sort.key) {
|
||||
if (this.sortActive.order === 'desc') {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'asc' })
|
||||
} else {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'desc' })
|
||||
}
|
||||
} else {
|
||||
this.$emit('update:sortActive', { key: sort.key, order: 'desc' })
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
5
komga-webui/src/functions/filter.ts
Normal file
5
komga-webui/src/functions/filter.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export function sortOrFilterActive (sortActive: SortActive, sortDefault: SortActive, filters: FiltersActive): boolean {
|
||||
const sortCustom = sortActive.key !== sortDefault.key || sortActive.order !== sortDefault.order
|
||||
const filterCustom = Object.keys(filters).some(x => filters[x].length !== 0)
|
||||
return sortCustom || filterCustom
|
||||
}
|
||||
|
|
@ -14,18 +14,11 @@
|
|||
|
||||
<v-spacer/>
|
||||
|
||||
<!-- Filter menu -->
|
||||
<filter-menu-button :filters-options="filterOptions"
|
||||
:filters-active.sync="filters"
|
||||
/>
|
||||
|
||||
<!-- Sort menu -->
|
||||
<sort-menu-button :sort-default="sortDefault"
|
||||
:sort-options="sortOptions"
|
||||
:sort-active.sync="sortActive"
|
||||
/>
|
||||
|
||||
<page-size-select v-model="pageSize"/>
|
||||
|
||||
<v-btn icon @click="drawer = !drawer">
|
||||
<v-icon :color="sortOrFilterActive ? 'secondary' : ''">mdi-filter-variant</v-icon>
|
||||
</v-btn>
|
||||
</toolbar-sticky>
|
||||
|
||||
<series-multi-select-bar
|
||||
|
|
@ -39,11 +32,35 @@
|
|||
|
||||
<library-navigation :libraryId="libraryId"/>
|
||||
|
||||
<filter-drawer v-model="drawer">
|
||||
<template v-slot:default>
|
||||
<filter-list
|
||||
:filters-options="filterOptionsList"
|
||||
:filters-active.sync="filters"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-slot:filter>
|
||||
<filter-panels
|
||||
:filters-options="filterOptionsPanel"
|
||||
:filters-active.sync="filters"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-slot:sort>
|
||||
<sort-list
|
||||
:sort-default="sortDefault"
|
||||
:sort-options="sortOptions"
|
||||
:sort-active.sync="sortActive"
|
||||
/>
|
||||
</template>
|
||||
</filter-drawer>
|
||||
|
||||
<v-container fluid>
|
||||
<empty-state
|
||||
v-if="totalPages === 0"
|
||||
title="The active filter has no matches"
|
||||
sub-title="Use the menu above to change the active filter"
|
||||
sub-title="Use the filter panel to change the active filter"
|
||||
icon="mdi-book-multiple"
|
||||
icon-color="secondary"
|
||||
>
|
||||
|
|
@ -72,12 +89,10 @@
|
|||
import SeriesMultiSelectBar from '@/components/bars/SeriesMultiSelectBar.vue'
|
||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||
import EmptyState from '@/components/EmptyState.vue'
|
||||
import FilterMenuButton from '@/components/FilterMenuButton.vue'
|
||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||
import SortMenuButton from '@/components/SortMenuButton.vue'
|
||||
import { parseQueryFilter, parseQuerySort } from '@/functions/query-params'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { SeriesStatus } from '@/types/enum-series'
|
||||
|
|
@ -85,6 +100,11 @@ import { LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_CHANGED } from '@/types/events
|
|||
import Vue from 'vue'
|
||||
import { Location } from 'vue-router'
|
||||
import { LIBRARIES_ALL } from '@/types/library'
|
||||
import FilterDrawer from '@/components/FilterDrawer.vue'
|
||||
import SortList from '@/components/SortList.vue'
|
||||
import FilterPanels from '@/components/FilterPanels.vue'
|
||||
import FilterList from '@/components/FilterList.vue'
|
||||
import { sortOrFilterActive } from '@/functions/filter'
|
||||
|
||||
const cookiePageSize = 'pagesize'
|
||||
|
||||
|
|
@ -94,12 +114,14 @@ export default Vue.extend({
|
|||
LibraryActionsMenu,
|
||||
EmptyState,
|
||||
ToolbarSticky,
|
||||
SortMenuButton,
|
||||
FilterMenuButton,
|
||||
ItemBrowser,
|
||||
PageSizeSelect,
|
||||
LibraryNavigation,
|
||||
SeriesMultiSelectBar,
|
||||
FilterDrawer,
|
||||
FilterPanels,
|
||||
FilterList,
|
||||
SortList,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
|
|
@ -117,10 +139,12 @@ export default Vue.extend({
|
|||
] as SortOption[],
|
||||
sortActive: {} as SortActive,
|
||||
sortDefault: { key: 'metadata.titleSort', order: 'asc' } as SortActive,
|
||||
filterOptions: {
|
||||
filterOptionsList: {
|
||||
readStatus: {
|
||||
values: [ReadStatus.UNREAD],
|
||||
},
|
||||
} as FiltersOptions,
|
||||
filterOptionsPanel: {
|
||||
status: {
|
||||
name: 'STATUS',
|
||||
values: Object.values(SeriesStatus),
|
||||
|
|
@ -131,6 +155,7 @@ export default Vue.extend({
|
|||
filterUnwatch: null as any,
|
||||
pageUnwatch: null as any,
|
||||
pageSizeUnwatch: null as any,
|
||||
drawer: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
|
@ -208,6 +233,9 @@ export default Vue.extend({
|
|||
return 15
|
||||
}
|
||||
},
|
||||
sortOrFilterActive (): boolean {
|
||||
return sortOrFilterActive(this.sortActive, this.sortDefault, this.filters)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
cookieSort (libraryId: string): string {
|
||||
|
|
|
|||
|
|
@ -26,19 +26,11 @@
|
|||
<v-icon>mdi-pencil</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<!-- Filter menu -->
|
||||
<filter-menu-button :filters-options="filterOptions"
|
||||
:filters-active.sync="filters"
|
||||
/>
|
||||
|
||||
<!-- Sort menu -->
|
||||
<sort-menu-button :sort-default="sortDefault"
|
||||
:sort-options="sortOptions"
|
||||
:sort-active.sync="sortActive"
|
||||
/>
|
||||
|
||||
<page-size-select v-model="pageSize"/>
|
||||
|
||||
<v-btn icon @click="drawer = !drawer">
|
||||
<v-icon :color="sortOrFilterActive ? 'secondary' : ''">mdi-filter-variant</v-icon>
|
||||
</v-btn>
|
||||
</toolbar-sticky>
|
||||
|
||||
<books-multi-select-bar
|
||||
|
|
@ -50,6 +42,30 @@
|
|||
@edit="editMultipleBooks"
|
||||
/>
|
||||
|
||||
<filter-drawer v-model="drawer">
|
||||
<template v-slot:default>
|
||||
<filter-list
|
||||
:filters-options="filterOptionsList"
|
||||
:filters-active.sync="filters"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- <template v-slot:filter>-->
|
||||
<!-- <filter-panels-->
|
||||
<!-- :filters-options="filterOptionsPanels"-->
|
||||
<!-- :filters-active.sync="filters"-->
|
||||
<!-- />-->
|
||||
<!-- </template>-->
|
||||
|
||||
<template v-slot:sort>
|
||||
<sort-list
|
||||
:sort-default="sortDefault"
|
||||
:sort-options="sortOptions"
|
||||
:sort-active.sync="sortActive"
|
||||
/>
|
||||
</template>
|
||||
</filter-drawer>
|
||||
|
||||
<v-container fluid>
|
||||
<v-row>
|
||||
<v-col cols="4" sm="4" md="auto" lg="auto" xl="auto">
|
||||
|
|
@ -149,7 +165,7 @@
|
|||
<empty-state
|
||||
v-if="totalPages === 0"
|
||||
title="The active filter has no matches"
|
||||
sub-title="Use the menu above to change the active filter"
|
||||
sub-title="Use the filter panel to change the active filter"
|
||||
icon="mdi-book-multiple"
|
||||
icon-color="secondary"
|
||||
>
|
||||
|
|
@ -179,12 +195,10 @@ import BooksMultiSelectBar from '@/components/bars/BooksMultiSelectBar.vue'
|
|||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||
import CollectionsExpansionPanels from '@/components/CollectionsExpansionPanels.vue'
|
||||
import EmptyState from '@/components/EmptyState.vue'
|
||||
import FilterMenuButton from '@/components/FilterMenuButton.vue'
|
||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||
import ItemCard from '@/components/ItemCard.vue'
|
||||
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
|
||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||
import SortMenuButton from '@/components/SortMenuButton.vue'
|
||||
import { parseQueryFilter, parseQuerySort } from '@/functions/query-params'
|
||||
import { seriesThumbnailUrl } from '@/functions/urls'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
|
|
@ -192,6 +206,10 @@ import { BOOK_CHANGED, LIBRARY_DELETED, READLIST_CHANGED, SERIES_CHANGED } from
|
|||
import Vue from 'vue'
|
||||
import { Location } from 'vue-router'
|
||||
import { SeriesStatus } from '@/types/enum-series'
|
||||
import FilterDrawer from '@/components/FilterDrawer.vue'
|
||||
import FilterList from '@/components/FilterList.vue'
|
||||
import SortList from '@/components/SortList.vue'
|
||||
import { sortOrFilterActive } from '@/functions/filter'
|
||||
|
||||
const tags = require('language-tags')
|
||||
|
||||
|
|
@ -201,8 +219,6 @@ export default Vue.extend({
|
|||
name: 'BrowseSeries',
|
||||
components: {
|
||||
ToolbarSticky,
|
||||
SortMenuButton,
|
||||
FilterMenuButton,
|
||||
ItemBrowser,
|
||||
PageSizeSelect,
|
||||
SeriesActionsMenu,
|
||||
|
|
@ -210,6 +226,9 @@ export default Vue.extend({
|
|||
EmptyState,
|
||||
BooksMultiSelectBar,
|
||||
CollectionsExpansionPanels,
|
||||
FilterDrawer,
|
||||
FilterList,
|
||||
SortList,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
|
|
@ -226,7 +245,7 @@ export default Vue.extend({
|
|||
}] as SortOption[],
|
||||
sortActive: {} as SortActive,
|
||||
sortDefault: { key: 'metadata.numberSort', order: 'asc' } as SortActive,
|
||||
filterOptions: {
|
||||
filterOptionsList: {
|
||||
readStatus: {
|
||||
values: [ReadStatus.UNREAD],
|
||||
},
|
||||
|
|
@ -237,6 +256,7 @@ export default Vue.extend({
|
|||
pageUnwatch: null as any,
|
||||
pageSizeUnwatch: null as any,
|
||||
collections: [] as CollectionDto[],
|
||||
drawer: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -276,6 +296,9 @@ export default Vue.extend({
|
|||
}
|
||||
return { color: undefined, text: undefined }
|
||||
},
|
||||
sortOrFilterActive (): boolean {
|
||||
return sortOrFilterActive(this.sortActive, this.sortDefault, this.filters)
|
||||
},
|
||||
},
|
||||
props: {
|
||||
seriesId: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="fill-height">
|
||||
<v-app-bar
|
||||
app
|
||||
>
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
</template>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<v-main>
|
||||
<v-main class="fill-height">
|
||||
<dialogs/>
|
||||
<router-view/>
|
||||
</v-main>
|
||||
|
|
|
|||
Loading…
Reference in a new issue