Support for custom scripts
This commit is contained in:
parent
52c643e4c8
commit
5d5ff69318
4 changed files with 156 additions and 27 deletions
101
package-lock.json
generated
101
package-lock.json
generated
|
@ -2333,6 +2333,17 @@
|
|||
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
|
||||
"dev": true
|
||||
},
|
||||
"clipboard": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
|
||||
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"good-listener": "^1.2.2",
|
||||
"select": "^1.1.2",
|
||||
"tiny-emitter": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
|
@ -2450,6 +2461,16 @@
|
|||
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
|
||||
"dev": true
|
||||
},
|
||||
"component-props": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/component-props/-/component-props-1.1.1.tgz",
|
||||
"integrity": "sha1-+bffm5kntubZfJvScqqGdnDzSUQ="
|
||||
},
|
||||
"component-xor": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/component-xor/-/component-xor-0.0.4.tgz",
|
||||
"integrity": "sha1-xV2DzMG5TNUImk6T+niRxyY+Wao="
|
||||
},
|
||||
"compress-commons": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz",
|
||||
|
@ -2952,6 +2973,12 @@
|
|||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"delegate": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
|
||||
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
|
||||
"optional": true
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
|
@ -3011,6 +3038,15 @@
|
|||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-iterator": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-iterator/-/dom-iterator-1.0.0.tgz",
|
||||
"integrity": "sha512-7dsMOQI07EMU98gQM8NSB3GsAiIeBYIPKpnxR3c9xOvdvBjChAcOM0iJ222I3p5xyiZO9e5oggkNaCusuTdYig==",
|
||||
"requires": {
|
||||
"component-props": "1.1.1",
|
||||
"component-xor": "0.0.4"
|
||||
}
|
||||
},
|
||||
"domain-browser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
|
||||
|
@ -3198,6 +3234,11 @@
|
|||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
|
@ -4330,6 +4371,15 @@
|
|||
"minimatch": "~3.0.2"
|
||||
}
|
||||
},
|
||||
"good-listener": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
|
||||
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delegate": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
|
@ -4987,8 +5037,7 @@
|
|||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
||||
"dev": true
|
||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
|
@ -6833,6 +6882,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"prismjs": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.20.0.tgz",
|
||||
"integrity": "sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ==",
|
||||
"requires": {
|
||||
"clipboard": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"private": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
|
||||
|
@ -7422,6 +7479,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
|
||||
"optional": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
|
@ -8226,6 +8289,12 @@
|
|||
"setimmediate": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
||||
"optional": true
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
|
@ -8385,6 +8454,24 @@
|
|||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||
"dev": true
|
||||
},
|
||||
"unescape": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz",
|
||||
"integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==",
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||
|
@ -8686,6 +8773,16 @@
|
|||
"vue-style-loader": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"vue-prism-editor": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-0.6.1.tgz",
|
||||
"integrity": "sha512-UyFLZ242eAplU0C1Tx/ZHSKFTPODQDMBuW9qqgMJyZqHFL2iuIbfT8EWmKtoNUn8w9VWS9IIicPs2odz2eni4Q==",
|
||||
"requires": {
|
||||
"dom-iterator": "^1.0.0",
|
||||
"escape-html": "^1.0.3",
|
||||
"unescape": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"vue-style-loader": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"prismjs": "^1.20.0",
|
||||
"vue": "^2.6.10",
|
||||
"vue-prism-editor": "^0.6.1",
|
||||
"webextension-polyfill": "^0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -71,21 +71,19 @@
|
|||
</div>
|
||||
|
||||
<div v-else>
|
||||
<form ref="runForm" @submit.prevent="runScript">
|
||||
<textarea v-model="script" />
|
||||
<form ref="runForm" @submit.prevent="runAction">
|
||||
<PrismEditor v-model="script" language="js" />
|
||||
|
||||
<div class="row buttons">
|
||||
<button type="button" @click="saveMode = true" :disabled="loading || !(action.name && action.name.length && action.name in actions)" v-if="!saveMode">
|
||||
<i class="fas fa-save" /> Save Action
|
||||
</button>
|
||||
<button type="button" @click="saveMode = true" :disabled="loading || script === scriptTemplate" v-if="!saveMode"><i class="fas fa-save" /> Save Script</button>
|
||||
<button type="submit" :disabled="loading"><i class="fas fa-play" /> Run</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form class="save-form" ref="scriptForm" @submit.prevent="storeAction" v-if="saveMode">
|
||||
<form class="save-form" ref="scriptForm" @submit.prevent="storeScript" v-if="saveMode">
|
||||
<div class="row">
|
||||
<input type="text" name="displayName" placeholder="Action display name" />
|
||||
<input type="text" name="displayName" placeholder="Script display name" />
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
@ -94,14 +92,14 @@
|
|||
|
||||
<div class="row multiple-host-selector">
|
||||
<div class="desc">
|
||||
Install action on these devices
|
||||
Install script on these devices
|
||||
</div>
|
||||
|
||||
<MultipleHostSelector :hosts="hosts" :selected="[host.name]" />
|
||||
</div>
|
||||
|
||||
<div class="row buttons">
|
||||
<button type="submit" :disabled="loading"><i class="fas fa-save" /> Save Action</button>
|
||||
<button type="submit" :disabled="loading"><i class="fas fa-save" /> Save Script</button>
|
||||
<button type="button" @click="saveMode = false" :disabled="loading"><i class="fas fa-times" /> Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -112,6 +110,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import 'prismjs';
|
||||
import 'prismjs/themes/prism.css';
|
||||
import PrismEditor from 'vue-prism-editor';
|
||||
|
||||
import mixins from '../utils';
|
||||
import Autocomplete from './Autocomplete';
|
||||
import MultipleHostSelector from './MultipleHostSelector';
|
||||
|
@ -121,11 +123,25 @@ export default {
|
|||
mixins: [mixins],
|
||||
props: {
|
||||
host: Object,
|
||||
scriptTemplate: {
|
||||
type: String,
|
||||
default: `async (app, host, browser, window) => {
|
||||
// Run some action on the host
|
||||
const status = await app.run({ name: 'music.mpd.pause' }, host);
|
||||
|
||||
// Send notifications to the browser
|
||||
app.notify(status.state, 'Music status changed');
|
||||
|
||||
// Return values back to the app
|
||||
return status;
|
||||
}`,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
Autocomplete,
|
||||
MultipleHostSelector,
|
||||
PrismEditor,
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -137,13 +153,10 @@ export default {
|
|||
actionResponse: null,
|
||||
actionError: null,
|
||||
hosts: {},
|
||||
script: `(browser, window, document) => {
|
||||
// Do something
|
||||
}`,
|
||||
script: this.scriptTemplate,
|
||||
actionMode: 'request',
|
||||
action: {
|
||||
name: null,
|
||||
script: null,
|
||||
args: [],
|
||||
},
|
||||
};
|
||||
|
@ -212,13 +225,17 @@ export default {
|
|||
this.loading = true;
|
||||
|
||||
try {
|
||||
this.actionResponse = await this.run(
|
||||
{
|
||||
name: this.action.name,
|
||||
args: this.getActionArgs(),
|
||||
},
|
||||
this.host
|
||||
);
|
||||
if (this.actionMode === 'request') {
|
||||
this.actionResponse = await this.run(
|
||||
{
|
||||
name: this.action.name,
|
||||
args: this.getActionArgs(),
|
||||
},
|
||||
this.host
|
||||
);
|
||||
} else {
|
||||
this.actionResponse = await this.runScript(this.script, this.host);
|
||||
}
|
||||
|
||||
this.actionError = null;
|
||||
} catch (e) {
|
||||
|
@ -229,11 +246,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async runScript() {
|
||||
this.loading = true;
|
||||
console.log(this.script);
|
||||
},
|
||||
|
||||
addActionArgument() {
|
||||
this.action.args.push({
|
||||
name: '',
|
||||
|
|
18
src/utils.js
18
src/utils.js
|
@ -65,6 +65,24 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async runScript(script, host) {
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
if (typeof script === 'string') {
|
||||
/* eslint no-eval: "off" */
|
||||
script = eval(this.script);
|
||||
}
|
||||
|
||||
return await script(this, host, browser, window);
|
||||
} catch (e) {
|
||||
this.notify(e.message, 'Script error');
|
||||
throw e;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async getHosts() {
|
||||
this.loading = true;
|
||||
|
||||
|
|
Loading…
Reference in a new issue