Refine UI code

This commit is contained in:
CzBiX
2019-04-19 18:36:04 +08:00
parent 021c7c6b1f
commit d6704eaeca
8 changed files with 88 additions and 43 deletions

View File

@@ -26,7 +26,7 @@
<main-toolbar v-model="drawer" />
<v-content>
<v-container pa-0 fluid>
<v-container fluid>
<torrents />
</v-container>
</v-content>
@@ -141,7 +141,7 @@ export default Vue.extend({
<style lang="scss" scoped>
.container {
margin-bottom: 80px;
padding: 0 0 80px;
}
.drawer {
display: flex;

13
src/assets/mdi.scss Normal file
View File

@@ -0,0 +1,13 @@
@import "~@mdi/font/scss/variables";
@import "~@mdi/font/scss/functions";
@import "~@mdi/font/scss/core";
@import "~@mdi/font/scss/icons";
@import "~@mdi/font/scss/extras";
@import "~@mdi/font/scss/animated";
@font-face {
font-family: "Material Design Icons";
src: url("~@mdi/font/fonts/materialdesignicons-webfont.woff2") format("woff2");
font-weight: normal;
font-style: normal;
}

View File

@@ -50,7 +50,7 @@
</v-list-tile-content>
</v-list-tile>
</v-list-group>
<template v-if="item.filterGroups">
<template v-else-if="item.filterGroups">
<filter-group
v-for="(child, i) in item.filterGroups"
:key="i"
@@ -153,6 +153,7 @@ export default {
...mapGetters([
'isDataReady',
'allTorrents',
'allCategories',
'torrentGroupByCategory',
'torrentGroupBySite',
'torrentGroupByState',
@@ -187,21 +188,26 @@ export default {
],
});
const categories: any[] = _.sortBy(Object.entries(this.torrentGroupByCategory).map(([key, value]) => {
const categories: any[] = [{
key: '',
name: 'Uncategorized',
}].concat(this.allCategories).map(category => {
let value = this.torrentGroupByCategory[category.key]
if (_.isUndefined(value)) {
value = [];
}
const size = formatSize(_.sumBy(value, 'size'));
const title = (key ? key : 'Uncategorized') + ` (${value.length})`;
const title = category.name + ` (${value.length})`;
const append = `[${size}]`;
return { icon: 'mdi-folder-open', title, key, append};
}), 'key');
return { icon: 'mdi-folder-open', title, key: category.key, append};
});
filterGroups.push({
'icon': 'mdi-menu-up',
'icon-alt': 'mdi-menu-down',
'title': 'Categories',
'model': false,
'model': true,
'select': 'category',
'children': [
...categories,
],
'children': categories,
});
const sites: any[] = _.sortBy(Object.entries(this.torrentGroupBySite).map(([key, value]) => {

View File

@@ -8,7 +8,7 @@
:align-center="!phoneLayout"
>
<v-flex v-if="!phoneLayout">
<v-tooltip top>
<v-tooltip top lazy>
<template v-slot:activator="{ on }">
<span v-on="on">
qBittorrent {{ app.version }}
@@ -21,12 +21,13 @@
</v-flex>
<v-divider vertical class="mx-2" v-if="!phoneLayout"/>
<v-flex class="icon-label">
<v-icon color="info">mdi-nas</v-icon>
Free: {{ info.free_space_on_disk | formatSize }}
<v-icon>mdi-sprout</v-icon>
{{ allTorrents.length }} [{{ totalSize | formatSize }}]
</v-flex>
<v-divider vertical class="mx-2" v-if="!phoneLayout"/>
<v-flex v-if="!phoneLayout">
Torrents: {{ allTorrents.length }} ({{ totalSize | formatSize }})
<v-flex class="icon-label">
<v-icon>mdi-nas</v-icon>
{{ info.free_space_on_disk | formatSize }}
</v-flex>
</v-layout>
</v-flex>
@@ -35,12 +36,13 @@
:column="phoneLayout"
:align-center="!phoneLayout"
>
<v-flex v-if="!phoneLayout">
DHT: {{ info.dht_nodes }} nodes
<v-flex v-if="!phoneLayout" class="icon-label">
<v-icon>mdi-access-point-network</v-icon>
{{ info.dht_nodes }} nodes
</v-flex>
<v-divider vertical class="mx-2" v-if="!phoneLayout"/>
<v-flex class="icon-label">
<v-tooltip top>
<v-tooltip top lazy>
<template v-slot:activator="{ on }">
<v-icon
v-on="on"
@@ -71,7 +73,7 @@
>mdi-speedometer</v-icon>
</template>
</v-switch>
<v-tooltip top v-else>
<v-tooltip top lazy v-else>
<template v-slot:activator="{ on }">
<v-icon
v-on="on"
@@ -86,7 +88,9 @@
</v-flex>
<v-divider vertical class="mx-2" v-if="!phoneLayout"/>
<v-flex class="icon-label">
<v-icon color="success">mdi-download</v-icon>
<v-icon
:color=" info.dl_info_speed > 0 ? 'success' : null"
>mdi-download</v-icon>
<span>
{{ info.dl_info_speed | formatSize }}/s
<template v-if="info.dl_rate_limit">
@@ -99,7 +103,9 @@
</v-flex>
<v-divider vertical class="mx-2" v-if="!phoneLayout"/>
<v-flex class="icon-label">
<v-icon color="warning">mdi-upload</v-icon>
<v-icon
:color=" info.up_info_speed > 0 ? 'warning' : null"
>mdi-upload</v-icon>
<span>
{{ info.up_info_speed | formatSize }}/s
<template v-if="info.up_rate_limit">
@@ -266,7 +272,7 @@ export default Vue.extend({
transform: scaleX(-1);
}
.in-drawer {
padding: 0 16px;
padding: 0 16px 0 20px;
.no-icon {
margin-left: 24px;

View File

@@ -35,25 +35,29 @@
Set category
</v-subheader>
<v-list-tile
v-for="(item, i) in categories"
v-for="(item, i) in allCategories"
:key="i"
@click="setTorrentsCategory(item)"
@click="setTorrentsCategory(item.key)"
>
<v-list-tile-action>
<v-icon>mdi-folder-open</v-icon>
</v-list-tile-action>
<v-list-tile-title>
{{ item }}
</v-list-tile-title>
<v-list-tile-content>
<v-list-tile-title>
{{ item.name }}
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-divider />
<v-list-tile @click="setTorrentsCategory('')">
<v-list-tile-action>
<v-icon>mdi-folder-remove</v-icon>
</v-list-tile-action>
<v-list-tile-title>
Reset
</v-list-tile-title>
<v-list-tile-content>
<v-list-tile-title>
Reset
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
@@ -152,6 +156,7 @@ export default Vue.extend({
...mapGetters([
'isDataReady',
'allTorrents',
'allCategories',
'torrentGroupByCategory',
'torrentGroupBySite',
'torrentGroupByState',
@@ -160,9 +165,6 @@ export default Vue.extend({
filter(state, getters) {
return getters.config.filter;
},
categories(state, getters) {
return Object.keys(getters.torrentGroupByCategory).filter(_.identity);
},
}),
hasSelected() {
return this.selectedRows.length;

View File

@@ -24,11 +24,12 @@ export interface DurationOptions {
export function formatDuration(value: number, options?: DurationOptions) {
const minute = 60;
const hour = 3600;
const day = 3600 * 24;
const hour = minute * 60;
const day = hour * 24;
const year = day * 365;
const durations = [day, hour, minute, 1];
const units = 'dhms';
const durations = [year, day, hour, minute, 1];
const units = 'ydhms';
let index = 0;
let unitSize = 0;
@@ -41,6 +42,10 @@ export function formatDuration(value: number, options?: DurationOptions) {
const opt = options ? Object.assign(defaultOptions, options) : defaultOptions;
if (opt.dayLimit && value >= opt.dayLimit * day) {
return '∞';
}
while (true) {
if ((opt.maxUnitSize && unitSize === opt.maxUnitSize) || index === durations.length) {
break;
@@ -52,9 +57,6 @@ export function formatDuration(value: number, options?: DurationOptions) {
continue;
}
const result = Math.floor(value / duration);
if (index === 0 && opt.dayLimit && result >= opt.dayLimit) {
return '∞';
}
parts.push(result + units[index]);
value %= duration;

View File

@@ -6,7 +6,7 @@ import './directives';
import App from './App.vue';
// import './registerServiceWorker';
import 'roboto-fontface/css/roboto/roboto-fontface.css';
import '@mdi/font/css/materialdesignicons.css';
import '@/assets/mdi.scss';
Vue.config.productionTip = false;

View File

@@ -9,7 +9,7 @@ Vue.use(Vuex);
const defaultConfig = {
updateInterval: 2000,
pagination: {
rowsPerPage: 100,
rowsPerPage: 50,
},
filter: {
state: null,
@@ -53,6 +53,12 @@ export default new Vuex.Store({
}
delete payload.torrents_removed;
}
if (payload.categories_removed) {
for (const key of payload.categories_removed) {
delete tmp.categories[key];
}
delete payload.categories_removed;
}
state.mainData = _.merge(tmp, payload);
}
},
@@ -84,6 +90,16 @@ export default new Vuex.Store({
return _.merge({}, value, { hash: key });
});
},
allCategories(state) {
if (!state.mainData) {
return [];
}
const categories = _.map(state.mainData.categories, (value, key) => {
return _.merge({}, value, { key });
});
return _.sortBy(categories, 'name')
},
torrentGroupByCategory(state, getters) {
return _.groupBy(getters.allTorrents, (torrent) => torrent.category);
},