-
-
Action
-
+
-
-
Loading...
-
-
+
+
Scripts stored for {{ host }}
+
Scripts
+
+
-
-
-
Scripts stored for {{ host }}
-
Scripts
-
-
+
No actions available on this device
@@ -102,6 +138,7 @@ export default {
scripts: {},
selectedAction: null,
selectedScript: null,
+ selectedCategory: null,
response: null,
error: null,
};
@@ -123,6 +160,32 @@ export default {
}, {});
},
+ actionsByCategory() {
+ if (!(this.host && this.host in this.actionsByHost)) {
+ return {};
+ }
+
+ return Object.entries(this.actionsByHost[this.host]).reduce((obj, [name, action]) => {
+ if (!(action.categories && action.categories.length)) {
+ if (!('' in obj)) {
+ obj[''] = {};
+ }
+
+ obj[''][name] = action;
+ } else {
+ for (const category of action.categories) {
+ if (!(category in obj)) {
+ obj[category] = {};
+ }
+
+ obj[category][name] = action;
+ }
+ }
+
+ return obj;
+ }, {});
+ },
+
actions() {
return this.host ? this.actionsByHost[this.host] || {} : this.actions_;
},
@@ -242,14 +305,30 @@ export default {
form {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
- .head {
+ &:not(.selected):nth-child(even) {
+ .action-head {
+ background: rgba(0, 0, 0, 0.03);
+ }
+ }
+
+ &.selected {
+ .action-head {
+ background: rgba(200, 255, 220, 1);
+ border-radius: 1em;
+ }
+ }
+
+ .action-head {
display: flex;
align-items: center;
position: relative;
padding: 1em;
- border-radius: 1em;
cursor: pointer;
+ &:hover {
+ background: rgba(200, 255, 220, 0.7) !important;
+ }
+
.icon {
font-size: 1.2em;
margin-right: 1.5em;
@@ -267,16 +346,6 @@ form {
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 1em;
}
-
- &:hover {
- background-color: rgba(200, 255, 220, 0.7);
- }
- }
-
- &.selected {
- .head {
- background-color: rgba(200, 255, 220, 1);
- }
}
.body {
@@ -304,6 +373,16 @@ form {
}
}
+.category {
+ border: 1px solid rgba(0, 0, 0, 0.075);
+ margin: 0 -1em;
+ padding: 0 1em;
+
+ .head {
+ padding: 1em 0.25em;
+ }
+}
+
.no-actions {
height: 100%;
display: flex;
diff --git a/src/options/Run.vue b/src/options/Run.vue
index a511595..f35626b 100644
--- a/src/options/Run.vue
+++ b/src/options/Run.vue
@@ -22,7 +22,7 @@
+
+ (selectedCategories = tags)"
+ placeholder="Categories"
+ />
+
+
Install script on these devices
@@ -115,7 +126,8 @@ import 'prismjs/themes/prism.css';
import PrismEditor from 'vue-prism-editor';
import mixins from '../utils';
-import Autocomplete from './Autocomplete';
+import Autocomplete from 'vuejs-auto-complete';
+import VueTagsInput from '@johmun/vue-tags-input';
import MultipleHostSelector from './MultipleHostSelector';
export default {
@@ -140,6 +152,7 @@ export default {
components: {
Autocomplete,
+ VueTagsInput,
MultipleHostSelector,
PrismEditor,
},
@@ -154,6 +167,9 @@ export default {
actionError: null,
hosts: {},
script: this.scriptTemplate,
+ storedActions: {},
+ selectedCategory: '',
+ selectedCategories: [],
actionMode: 'request',
action: {
name: null,
@@ -186,15 +202,13 @@ export default {
return { ...plugins, ...procedures };
},
- filteredActions() {
- if (!(this.action.name && this.action.name.length)) return {};
-
- return Object.entries(this.actions)
- .filter(([name, action]) => name.startsWith(this.action.name))
- .reduce((obj, [name, action]) => {
- obj[name] = action;
- return obj;
- }, {});
+ actionsAutocomplete() {
+ return Object.keys(this.actions).map(action => {
+ return {
+ id: action,
+ name: action,
+ };
+ });
},
actionTemplate() {
@@ -204,6 +218,26 @@ export default {
return this.actions[this.action.name];
},
+
+ categories() {
+ return Object.keys(
+ Object.values(this.storedActions).reduce((obj, action) => {
+ for (const category of action.categories || []) {
+ obj[category] = true;
+ }
+
+ return obj;
+ }, {})
+ );
+ },
+
+ categoriesAutocomplete() {
+ return this.categories.map(cat => {
+ return {
+ text: cat,
+ };
+ });
+ },
},
methods: {
@@ -273,6 +307,10 @@ export default {
}
},
+ async loadActions() {
+ this.storedActions = await this.getActions();
+ },
+
async save(event) {
return this.actionMode === 'request' ? await this.storeAction(event) : await this.storeScript(event);
},
@@ -299,6 +337,7 @@ export default {
iconClass: iconClass,
hosts: hosts,
script: this.script,
+ categories: this.selectedCategories.map(obj => obj.text),
};
await this.saveScript(script);
@@ -327,6 +366,7 @@ export default {
hosts: hosts,
name: this.action.name,
args: this.getActionArgs(),
+ categories: this.selectedCategories.map(obj => obj.text),
};
await this.saveAction(action);
@@ -340,12 +380,17 @@ export default {
this.action.name = action;
this.action.args = [];
},
+
+ onCategoryInput(event) {
+ console.log(event);
+ },
},
created() {
this.clearAction();
this.loadHosts();
this.loadPlugins();
+ this.loadActions();
},
};
diff --git a/src/popup/App.vue b/src/popup/App.vue
index 64d0147..b0cf0fc 100644
--- a/src/popup/App.vue
+++ b/src/popup/App.vue
@@ -28,13 +28,24 @@
No actions available for {{ selectedHost }}. Click
here to configure the device.
-
@@ -52,6 +63,7 @@ export default {
actions_: null,
scripts_: null,
selectedHost: null,
+ selectedCategory: null,
};
},
@@ -76,6 +88,32 @@ export default {
}, {});
},
+ actionsByCategory() {
+ if (!this.selectedHost) {
+ return {};
+ }
+
+ return Object.entries(this.actionsByHost[this.selectedHost]).reduce((obj, [name, action]) => {
+ if (!(action.categories && action.categories.length)) {
+ if (!('' in obj)) {
+ obj[''] = {};
+ }
+
+ obj[''][name] = action;
+ } else {
+ for (const category of action.categories) {
+ if (!(category in obj)) {
+ obj[category] = {};
+ }
+
+ obj[category][name] = action;
+ }
+ }
+
+ return obj;
+ }, {});
+ },
+
actions() {
return this.actionsByHost[this.selectedHost];
},
@@ -108,7 +146,7 @@ export default {
return;
}
- this.notify('', 'Action executed');
+ this.notify('Action ' + action + ' executed on ' + this.host.name);
return ret;
},
},
@@ -132,29 +170,29 @@ export default {
width: 100%;
height: 100%;
position: relative;
-}
-.head {
- width: 100%;
- height: 2.5em;
- background: rgba(0, 0, 0, 0.03);
- display: flex;
- align-items: center;
- border-bottom: 1px solid rgba(0, 0, 0, 0.2);
- box-shadow: 0 2px 4px 1px rgba(0, 0, 0, 0.05);
+ .head {
+ width: 100%;
+ height: 2.5em;
+ background: rgba(0, 0, 0, 0.03);
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px 1px rgba(0, 0, 0, 0.05);
- .host-selector,
- .settings {
- padding: 0.5em;
- }
+ .host-selector,
+ .settings {
+ padding: 0.5em;
+ }
- .host-selector {
- width: 80%;
- }
+ .host-selector {
+ width: 80%;
+ }
- .settings {
- width: 20%;
- text-align: right;
+ .settings {
+ width: 20%;
+ text-align: right;
+ }
}
}
@@ -189,6 +227,7 @@ export default {
.loading {
height: 100%;
margin: auto;
+ padding: 2em;
font-size: 1.3em;
text-align: center;
color: rgba(0, 0, 0, 0.8);