Add state fileter

This commit is contained in:
CzBiX
2019-04-16 19:32:56 +08:00
parent a0c826de2d
commit 0c70e5b30c
7 changed files with 208 additions and 61 deletions

View File

@@ -75,7 +75,50 @@ import FilterGroup from './drawer/FilterGroup.vue';
import { api } from '../Api';
import { mapState, mapMutations, mapGetters } from 'vuex';
import { formatSize } from '../filters';
import { SiteMap } from '../consts';
import { SiteMap, StateType, AllStateTypes } from '../consts';
const stateList = [
{
title: 'Downloading',
state: StateType.Downloading,
icon: 'download',
},
{
title: 'Seeding',
state: StateType.Seeding,
icon: 'upload',
},
{
title: 'Completed',
state: StateType.Completed,
icon: 'check',
},
{
title: 'Resumed',
state: StateType.Resumed,
icon: 'play',
},
{
title: 'Paused',
state: StateType.Paused,
icon: 'pause',
},
{
title: 'Active',
state: StateType.Active,
icon: 'filter',
},
{
title: 'Inactive',
state: StateType.Inactive,
icon: 'filter-outline',
},
{
title: 'Errored',
state: StateType.Errored,
icon: 'alert',
},
];
export default {
components: {
@@ -89,23 +132,6 @@ export default {
data() {
return {
basicItems: null,
// {
// 'icon': 'mdi-menu-up',
// 'icon-alt': 'mdi-menu-down',
// 'text': 'Status',
// 'model': true,
// 'children': [
// { icon: 'mdi-filter-remove', text: 'All' },
// { icon: 'mdi-download', text: 'Downloading' },
// { icon: 'mdi-upload', text: 'Seeding' },
// { icon: 'mdi-check', text: 'Completed' },
// { icon: 'mdi-play', text: 'Resumed' },
// { icon: 'mdi-pause', text: 'Paused' },
// { icon: 'mdi-filter', text: 'Active' },
// { icon: 'mdi-filter-outline', text: 'Inactive' },
// { icon: 'mdi-alert', text: 'Errored' },
// ],
// },
endItems: null,
};
},
@@ -126,19 +152,44 @@ export default {
'allTorrents',
'torrentGroupByCategory',
'torrentGroupBySite',
'torrentGroupByState',
]),
items() {
if (!this.isDataReady) {
return _.concat(this.basicItems, this.endItems);
}
const filterGroups = [];
const totalSize = formatSize(_.sumBy(this.allTorrents, 'size'));
const states = stateList.map((item) => {
let value = this.torrentGroupByState[item.state];
if (_.isUndefined(value)) {
value = [];
}
const size = formatSize(_.sumBy(value, 'size'));
const title = item.title + ` (${value.length})`;
const append = `[${size}]`;
return { icon: 'mdi-' + item.icon, title, key: item.state, append};
});
filterGroups.push({
'icon': 'mdi-menu-up',
'icon-alt': 'mdi-menu-down',
'title': 'State',
'model': true,
'select': 'state',
'children': [
{ icon: 'mdi-filter-remove', title: `All (${this.allTorrents.length})`, key: null, append: `[${totalSize}]` },
...states,
],
});
const categories: any[] = _.sortBy(Object.entries(this.torrentGroupByCategory).map(([key, value]) => {
const size = formatSize(_.sumBy(value, 'size'));
const title = key ? key : 'Uncategorized';
const append = `(${value.length})[${size}]`;
const title = (key ? key : 'Uncategorized') + ` (${value.length})`;
const append = `[${size}]`;
return { icon: 'mdi-folder-open', title, key, append};
}), 'key');
const totalSize = formatSize(_.sumBy(this.allTorrents, 'size'));
filterGroups.push({
'icon': 'mdi-menu-up',
'icon-alt': 'mdi-menu-down',
@@ -146,7 +197,6 @@ export default {
'model': false,
'select': 'category',
'children': [
{ icon: 'mdi-folder-open', title: 'All', key: null, append: `(${this.allTorrents.length})[${totalSize}]` },
...categories,
],
});
@@ -154,9 +204,9 @@ export default {
const sites: any[] = _.sortBy(Object.entries(this.torrentGroupBySite).map(([key, value]) => {
const size = formatSize(_.sumBy(value, 'size'));
const site = (SiteMap as any)[key];
const title = site ? site.name : 'Others';
const title = (site ? site.name : 'Others') + ` (${value.length})`;
const icon = _.defaultTo(site ? site.icon : null, 'mdi-server');
const append = `(${value.length})[${size}]`;
const append = `[${size}]`;
return { icon, title, key, append };
}), 'title');
filterGroups.push({

View File

@@ -13,20 +13,20 @@
hide-details
@click.stop="selectedRows = []"
></v-checkbox>
<v-btn icon @click="confirmDelete">
<v-btn icon @click="confirmDelete" title="Delete">
<v-icon>mdi-delete</v-icon>
</v-btn>
<v-divider vertical inset />
<v-btn icon @click="resumeTorrents">
<v-btn icon @click="resumeTorrents" title="Resume">
<v-icon>mdi-play</v-icon>
</v-btn>
<v-btn icon @click="pauseTorrents">
<v-btn icon @click="pauseTorrents" title="Pause">
<v-icon>mdi-pause</v-icon>
</v-btn>
<v-divider vertical inset />
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on">
<v-btn icon v-on="on" title="Category">
<v-icon>mdi-folder</v-icon>
</v-btn>
</template>
@@ -157,6 +157,7 @@ export default Vue.extend({
'allTorrents',
'torrentGroupByCategory',
'torrentGroupBySite',
'torrentGroupByState',
]),
...mapState({
filter(state, getters) {
@@ -183,6 +184,9 @@ export default Vue.extend({
if (this.filter.category !== null) {
list = _.intersection(list, this.torrentGroupByCategory[this.filter.category]);
}
if (this.filter.state !== null) {
list = _.intersection(list, this.torrentGroupByState[this.filter.state]);
}
return list;
},

View File

@@ -1,7 +1,7 @@
<template>
<v-list-group
v-model="group.model"
:prepend-icon="group.model ? group.icon : group['icon-alt']"
v-model="model"
:prepend-icon="model ? group.icon : group['icon-alt']"
>
<template v-slot:activator>
<v-list-tile>
@@ -51,6 +51,7 @@ export default Vue.extend({
},
data() {
return {
model: this.group.model,
selected: null,
}
},

View File

@@ -1,30 +1,25 @@
export const SiteMap = {
'tp.m-team.cc': {
name: 'M-Team',
icon: 'https://tp.m-team.cc/favicon.ico',
},
'pt.keepfrds.com': {
name: 'FRDS',
icon: 'https://pt.keepfrds.com/static/favicon.ico',
},
'hdcmct.org': {
name: 'CMCT',
icon: 'https://hdcmct.org/favicon.ico',
},
'hdchina.org': {
name: 'HDChina',
icon: 'https://hdchina.org/favicon.ico',
},
'chdbits.co': {
name: 'CHDBits',
icon: 'https://chdbits.co/favicon.ico',
},
'hdhome.org': {
name: 'HDHome',
icon: 'https://hdhome.org/favicon.ico',
},
'u2.dmhy.org': {
name: 'U2',
icon: 'https://u2.dmhy.org/favicon.ico',
},
};
import sites from './sites';
export const SiteMap = sites;
export const enum StateType {
Downloading = 'downloading',
Seeding = 'seeding',
Completed = 'completed',
Resumed = 'resumed',
Paused = 'pasued',
Active = 'active',
Inactive = 'inactive',
Errored = 'errored',
}
export const AllStateTypes = [
StateType.Downloading,
StateType.Seeding,
StateType.Completed,
StateType.Resumed,
StateType.Paused,
StateType.Active,
StateType.Inactive,
StateType.Errored,
];

30
src/sites.ts Normal file
View File

@@ -0,0 +1,30 @@
export default {
'tp.m-team.cc': {
name: 'M-Team',
icon: 'https://tp.m-team.cc/favicon.ico',
},
'pt.keepfrds.com': {
name: 'FRDS',
icon: 'https://pt.keepfrds.com/static/favicon.ico',
},
'hdcmct.org': {
name: 'CMCT',
icon: 'https://hdcmct.org/favicon.ico',
},
'hdchina.org': {
name: 'HDChina',
icon: 'https://hdchina.org/favicon.ico',
},
'chdbits.co': {
name: 'CHDBits',
icon: 'https://chdbits.co/favicon.ico',
},
'hdhome.org': {
name: 'HDHome',
icon: 'https://hdhome.org/favicon.ico',
},
'u2.dmhy.org': {
name: 'U2',
icon: 'https://u2.dmhy.org/favicon.ico',
},
};

View File

@@ -1,6 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import _ from 'lodash';
import { AllStateTypes } from './consts';
import { torrentIsState } from './utils';
Vue.use(Vuex);
@@ -10,7 +12,7 @@ const defaultConfig = {
rowsPerPage: 100,
},
filter: {
type: null,
state: null,
category: null,
site: null,
},
@@ -95,5 +97,26 @@ export default new Vuex.Store({
return url.hostname;
});
},
torrentGroupByState(__, getters) {
const result: any = {};
const put = (state: any, torrent: any) => {
let list: any[] = result[state];
if (!list) {
list = [];
result[state] = list;
}
list.push(torrent);
};
for (const torrent of getters.allTorrents) {
for (const type of AllStateTypes) {
if (torrentIsState(type, torrent.state)) {
put(type, torrent);
}
}
}
return result;
},
},
});

44
src/utils.ts Normal file
View File

@@ -0,0 +1,44 @@
import _ from 'lodash';
import { StateType } from './consts';
const dlState = ['downloading', 'metaDL', 'stalledDL', 'checkingDL', 'pausedDL', 'queuedDL', 'forceDL'];
const upState = ['uploading', 'stalledUP', 'checkingUP', 'queuedUP', 'forceUP'];
const completeState = ['uploading', 'stalledUP', 'checkingUP', 'pausedUP', 'queuedUP', 'forceUP'];
const activeState = ['metaDL', 'downloading', 'forceDL', 'uploading', 'forcedUP', 'moving'];
const errorState = ['error', 'missingFiles'];
export function torrentIsState(type: StateType, state: string) {
let result;
switch (type) {
case StateType.Downloading: {
result = dlState.includes(state);
break;
}
case StateType.Seeding: {
result = upState.includes(state);
break;
}
case StateType.Completed: {
result = completeState.includes(state);
break;
}
case StateType.Resumed:
case StateType.Paused: {
const paused = state.startsWith('paused');
result = type === StateType.Paused ? paused : !paused;
break;
}
case StateType.Active:
case StateType.Inactive: {
const active = activeState.includes(state);
result = type === StateType.Active ? active : !active;
break;
}
case StateType.Errored: {
result = errorState.includes(state);
break;
}
}
return result;
}