diff --git a/src/Api.ts b/src/Api.ts
index 7d3e555..8aa8103 100644
--- a/src/Api.ts
+++ b/src/Api.ts
@@ -307,6 +307,15 @@ class Api {
return this.axios.get(`/search/results?id=${id}`).then(Api.handleResponse);
}
+ public enablePlugin(plugin: SearchPlugin, enable: boolean) {
+ const body = new URLSearchParams({
+ names: plugin.name,
+ enable: JSON.stringify(enable)
+ });
+
+ return this.axios.post('/search/enablePlugin', body).then(Api.handleResponse);
+ }
+
private actionTorrents(action: string, hashes: string[], extra?: any) {
const params: any = {
hashes: hashes.join('|'),
diff --git a/src/components/dialogs/searchDialog/PluginsManager.vue b/src/components/dialogs/searchDialog/PluginsManager.vue
new file mode 100644
index 0000000..1235937
--- /dev/null
+++ b/src/components/dialogs/searchDialog/PluginsManager.vue
@@ -0,0 +1,49 @@
+
+
+
+ mdi-toy-brick Plugins manager
+
+
+
+
+
+
+
+
diff --git a/src/components/dialogs/searchDialog/SearchDialog.vue b/src/components/dialogs/searchDialog/SearchDialog.vue
index f3a212c..f1593ff 100644
--- a/src/components/dialogs/searchDialog/SearchDialog.vue
+++ b/src/components/dialogs/searchDialog/SearchDialog.vue
@@ -48,9 +48,14 @@
-
+
+
+ mdi-cog Plugins manager
+
+
+
@@ -59,9 +64,10 @@ import api from "@/Api";
import HasTask from "@/mixins/hasTask";
import { Component, Prop, Emit } from "vue-property-decorator";
import { SearchTaskTorrent } from "@/types";
-import { mapGetters, mapMutations } from "vuex";
+import { mapActions, mapGetters, mapMutations } from "vuex";
import { tr } from "@/locale";
import SearchDialogForm from "./SearchDialogForm.vue";
+import PluginManager from "./PluginsManager.vue";
interface GridConfig {
searchItems: SearchTaskTorrent[];
@@ -71,7 +77,8 @@ interface GridConfig {
@Component({
components: {
- SearchDialogForm
+ SearchDialogForm,
+ PluginManager
},
computed: {
...mapGetters({
@@ -80,7 +87,10 @@ interface GridConfig {
})
},
methods: {
- ...mapMutations(["openAddForm", "setPasteUrl", "addFormDownloadItem"])
+ ...mapMutations(["openAddForm", "setPasteUrl", "addFormDownloadItem", "openPluginManager"]),
+ ...mapActions({
+ loadSearchPlugins: 'fetchSearchPlugins'
+ })
}
})
export default class SearchDialog extends HasTask {
@@ -115,6 +125,12 @@ export default class SearchDialog extends HasTask {
setPasteUrl!: (_: any) => void;
openAddForm!: () => void;
addFormDownloadItem!: (_: any) => void;
+ loadSearchPlugins!: () => void;
+ openPluginManager!: () => void;
+
+ mounted() {
+ this.loadSearchPlugins(); // load the plugins so they are available in the entire module
+ }
async downloadTorrent(item: SearchTaskTorrent) {
this.addFormDownloadItem({
diff --git a/src/components/dialogs/searchDialog/SearchDialogForm.vue b/src/components/dialogs/searchDialog/SearchDialogForm.vue
index 74e0748..a6cb0aa 100644
--- a/src/components/dialogs/searchDialog/SearchDialogForm.vue
+++ b/src/components/dialogs/searchDialog/SearchDialogForm.vue
@@ -25,6 +25,8 @@
x.enabled);
+ this.toggleSelectAll();
+ }
}
- async getAvailablePlugins(): Promise {
- const availablePlugins = await api.getSearchPlugins();
-
- return availablePlugins
- .filter(plugin => plugin.enabled === true)
- .sort((p1, p2) => p1.fullName.localeCompare(p2.fullName));
- }
-
- @Emit('triggerSearch')
+ @Emit("triggerSearch")
triggerSearch(): SearchForm | void {
if (!this.searchForm.valid) {
return;
}
- const plugins = this.hasSelectAllPlugins
+ const plugins = this.hasSelectAllPlugins
? ALL_KEY
: this.searchForm.plugins.map(p => p.name).join("|");
@@ -209,7 +212,7 @@ export default class SearchDialogForm extends Vue {
return searchForm;
}
- @Emit('stopSearch')
+ @Emit("stopSearch")
stopSearch() {
//
}
diff --git a/src/store/index.ts b/src/store/index.ts
index 07a9834..9e47e5c 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -9,6 +9,7 @@ import { snackBarStore } from './snackBar';
import { addFormStore } from './addForm';
import { AllStateTypes } from '../consts';
import { torrentIsState } from '../utils';
+import searchEngineStore from './searchEngine';
import { RootState } from './types';
Vue.use(Vuex);
@@ -18,7 +19,8 @@ const store = new Vuex.Store({
config: configStore,
dialog: dialogStore,
snackBar: snackBarStore,
- addForm: addFormStore
+ addForm: addFormStore,
+ searchEngine: searchEngineStore
},
state: {
rid: 0,
@@ -117,7 +119,7 @@ const store = new Vuex.Store({
return result;
},
- },
+ }
});
export default store;
diff --git a/src/store/searchEngine.ts b/src/store/searchEngine.ts
new file mode 100644
index 0000000..f86f061
--- /dev/null
+++ b/src/store/searchEngine.ts
@@ -0,0 +1,65 @@
+import { Module } from "vuex";
+import { SearchPlugin } from "@/types";
+import { SearchEnginePage } from "./types";
+import api from "@/Api";
+
+export default {
+ state: {
+ searchPlugins: [],
+ isPluginManagerOpen: false
+ },
+ mutations: {
+ setSearchPlugins(state, plugins: SearchPlugin[] | undefined | null) {
+ state.searchPlugins = plugins;
+ },
+ openPluginManager(state) {
+ state.isPluginManagerOpen = true;
+ },
+ closePluginManager(state) {
+ state.isPluginManagerOpen = false;
+ }
+ },
+ getters: {
+ allSearchPlugins(state): SearchPlugin[] | undefined | null {
+ return state.searchPlugins;
+ }
+ },
+ actions: {
+ fetchSearchPlugins({ dispatch }) {
+ // semantic helper
+ dispatch("getSearchPluginsRequest");
+ },
+ async getSearchPluginsRequest({ dispatch }) {
+ try {
+ const searchPlugins = await api.getSearchPlugins();
+
+ dispatch("getSearchPluginRequestSuccess", searchPlugins);
+ } catch {
+ dispatch("getSearchPluginsRequestFailure");
+ }
+ },
+ getSearchPluginRequestSuccess({ commit }, searchPlugins) {
+ commit("setSearchPlugins", undefined);
+
+ commit("setSearchPlugins", searchPlugins);
+ },
+ getSearchPluginRequestFailure({ commit }) {
+ commit("setSearchPlugins", null);
+ },
+ togglePluginAvailability({ dispatch }, plugin) {
+ dispatch("togglePluginEnableRequest", plugin);
+ },
+ async togglePluginEnableRequest({ dispatch }, plugin: SearchPlugin) {
+ try {
+ await api.enablePlugin(plugin, !plugin.enabled); // switch plugin enable state
+
+ dispatch("enablePluginRequestSuccess", plugin);
+ } catch {
+ // Do nothing
+ }
+ },
+ enablePluginRequestSuccess({ dispatch }) {
+ dispatch('fetchSearchPlugins'); // refresh the plugins
+ }
+ }
+} as Module;
diff --git a/src/store/types.ts b/src/store/types.ts
index 937e37e..262f2db 100644
--- a/src/store/types.ts
+++ b/src/store/types.ts
@@ -1,4 +1,4 @@
-import { MainData } from '@/types';
+import { MainData, SearchPlugin } from '@/types';
import { Config } from './config';
export interface RootState {
@@ -8,6 +8,11 @@ export interface RootState {
pasteUrl: string | null;
}
+export interface SearchEnginePage {
+ searchPlugins: SearchPlugin[] | null | undefined;
+ isPluginManagerOpen: boolean;
+}
+
export interface AddFormState {
isOpen: boolean;
downloadItem: {