Add AiScript console widget
This commit is contained in:
		
							parent
							
								
									3d73ce63ca
								
							
						
					
					
						commit
						b2fb92cf0f
					
				
					 4 changed files with 176 additions and 3 deletions
				
			
		|  | @ -1067,6 +1067,7 @@ _widgets: | ||||||
|   onlineUsers: "オンラインユーザー" |   onlineUsers: "オンラインユーザー" | ||||||
|   jobQueue: "ジョブキュー" |   jobQueue: "ジョブキュー" | ||||||
|   serverMetric: "サーバーメトリクス" |   serverMetric: "サーバーメトリクス" | ||||||
|  |   aiscript: "AiScriptコンソール" | ||||||
| 
 | 
 | ||||||
| _cw: | _cw: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|  |  | ||||||
							
								
								
									
										164
									
								
								src/client/widgets/aiscript.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/client/widgets/aiscript.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,164 @@ | ||||||
|  | <template> | ||||||
|  | <MkContainer :show-header="props.showHeader"> | ||||||
|  | 	<template #header><Fa :icon="faTerminal"/>{{ $ts._widgets.aiscript }}</template> | ||||||
|  | 
 | ||||||
|  | 	<div class="uylguesu _monospace"> | ||||||
|  | 		<textarea v-model="props.script" placeholder="(1 + 1)"></textarea> | ||||||
|  | 		<button @click="run" class="_buttonPrimary">RUN</button> | ||||||
|  | 		<div class="logs"> | ||||||
|  | 			<div v-for="log in logs" class="log" :key="log.id" :class="{ print: log.print }">{{ log.text }}</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </MkContainer> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import { defineComponent } from 'vue'; | ||||||
|  | import { faTerminal } from '@fortawesome/free-solid-svg-icons'; | ||||||
|  | import MkContainer from '@/components/ui/container.vue'; | ||||||
|  | import define from './define'; | ||||||
|  | import * as os from '@/os'; | ||||||
|  | import { AiScript, parse, utils } from '@syuilo/aiscript'; | ||||||
|  | import { createAiScriptEnv } from '@/scripts/aiscript/api'; | ||||||
|  | 
 | ||||||
|  | const widget = define({ | ||||||
|  | 	name: 'aiscript', | ||||||
|  | 	props: () => ({ | ||||||
|  | 		showHeader: { | ||||||
|  | 			type: 'boolean', | ||||||
|  | 			default: true, | ||||||
|  | 		}, | ||||||
|  | 		script: { | ||||||
|  | 			type: 'string', | ||||||
|  | 			multiline: true, | ||||||
|  | 			default: '(1 + 1)', | ||||||
|  | 			hidden: true, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | export default defineComponent({ | ||||||
|  | 	extends: widget, | ||||||
|  | 	components: { | ||||||
|  | 		MkContainer | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			logs: [], | ||||||
|  | 			faTerminal | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	methods: { | ||||||
|  | 		async run() { | ||||||
|  | 			this.logs = []; | ||||||
|  | 			const aiscript = new AiScript(createAiScriptEnv({ | ||||||
|  | 				storageKey: 'widget' | ||||||
|  | 			}), { | ||||||
|  | 				in: (q) => { | ||||||
|  | 					return new Promise(ok => { | ||||||
|  | 						os.dialog({ | ||||||
|  | 							title: q, | ||||||
|  | 							input: {} | ||||||
|  | 						}).then(({ canceled, result: a }) => { | ||||||
|  | 							ok(a); | ||||||
|  | 						}); | ||||||
|  | 					}); | ||||||
|  | 				}, | ||||||
|  | 				out: (value) => { | ||||||
|  | 					this.logs.push({ | ||||||
|  | 						id: Math.random(), | ||||||
|  | 						text: value.type === 'str' ? value.value : utils.valToString(value), | ||||||
|  | 						print: true | ||||||
|  | 					}); | ||||||
|  | 				}, | ||||||
|  | 				log: (type, params) => { | ||||||
|  | 					switch (type) { | ||||||
|  | 						case 'end': this.logs.push({ | ||||||
|  | 							id: Math.random(), | ||||||
|  | 							text: utils.valToString(params.val, true), | ||||||
|  | 							print: false | ||||||
|  | 						}); break; | ||||||
|  | 						default: break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			let ast; | ||||||
|  | 			try { | ||||||
|  | 				ast = parse(this.props.script); | ||||||
|  | 			} catch (e) { | ||||||
|  | 				os.dialog({ | ||||||
|  | 					type: 'error', | ||||||
|  | 					text: 'Syntax error :(' | ||||||
|  | 				}); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			try { | ||||||
|  | 				await aiscript.exec(ast); | ||||||
|  | 			} catch (e) { | ||||||
|  | 				os.dialog({ | ||||||
|  | 					type: 'error', | ||||||
|  | 					text: e | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .uylguesu { | ||||||
|  | 	text-align: right; | ||||||
|  | 
 | ||||||
|  | 	> textarea { | ||||||
|  | 		display: block; | ||||||
|  | 		width: 100%; | ||||||
|  | 		max-width: 100%; | ||||||
|  | 		min-width: 100%; | ||||||
|  | 		padding: 16px; | ||||||
|  | 		color: var(--fg); | ||||||
|  | 		background: transparent; | ||||||
|  | 		border: none; | ||||||
|  | 		border-bottom: solid 1px var(--divider); | ||||||
|  | 		border-radius: 0; | ||||||
|  | 		box-sizing: border-box; | ||||||
|  | 		font: inherit; | ||||||
|  | 
 | ||||||
|  | 		&:focus { | ||||||
|  | 			outline: none; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	> button { | ||||||
|  | 		display: inline-block; | ||||||
|  | 		margin: 8px; | ||||||
|  | 		padding: 0 10px; | ||||||
|  | 		height: 28px; | ||||||
|  | 		outline: none; | ||||||
|  | 		border-radius: 4px; | ||||||
|  | 
 | ||||||
|  | 		&:disabled { | ||||||
|  | 			opacity: 0.7; | ||||||
|  | 			cursor: default; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	> .logs { | ||||||
|  | 		border-top: solid 1px var(--divider); | ||||||
|  | 		text-align: left; | ||||||
|  | 		padding: 16px; | ||||||
|  | 
 | ||||||
|  | 		&:empty { | ||||||
|  | 			display: none; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		> .log { | ||||||
|  | 			&:not(.print) { | ||||||
|  | 				opacity: 0.7; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -18,6 +18,7 @@ export default function(app: App) { | ||||||
| 	app.component('MkwOnlineUsers', defineAsyncComponent(() => import('./online-users.vue'))); | 	app.component('MkwOnlineUsers', defineAsyncComponent(() => import('./online-users.vue'))); | ||||||
| 	app.component('MkwJobQueue', defineAsyncComponent(() => import('./job-queue.vue'))); | 	app.component('MkwJobQueue', defineAsyncComponent(() => import('./job-queue.vue'))); | ||||||
| 	app.component('MkwButton', defineAsyncComponent(() => import('./button.vue'))); | 	app.component('MkwButton', defineAsyncComponent(() => import('./button.vue'))); | ||||||
|  | 	app.component('MkwAiscript', defineAsyncComponent(() => import('./aiscript.vue'))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const widgets = [ | export const widgets = [ | ||||||
|  | @ -38,4 +39,5 @@ export const widgets = [ | ||||||
| 	'onlineUsers', | 	'onlineUsers', | ||||||
| 	'jobQueue', | 	'jobQueue', | ||||||
| 	'button', | 	'button', | ||||||
|  | 	'aiscript', | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
|  | @ -74,12 +74,18 @@ export default defineComponent({ | ||||||
| 		max-width: 100%; | 		max-width: 100%; | ||||||
| 		min-width: 100%; | 		min-width: 100%; | ||||||
| 		padding: 16px; | 		padding: 16px; | ||||||
| 		color: var(--inputText); | 		color: var(--fg); | ||||||
| 		background: var(--face); | 		background: transparent; | ||||||
| 		border: none; | 		border: none; | ||||||
| 		border-bottom: solid var(--lineWidth) var(--faceDivider); | 		border-bottom: solid 1px var(--divider); | ||||||
| 		border-radius: 0; | 		border-radius: 0; | ||||||
| 		box-sizing: border-box; | 		box-sizing: border-box; | ||||||
|  | 		font: inherit; | ||||||
|  | 		font-size: 0.9em; | ||||||
|  | 
 | ||||||
|  | 		&:focus { | ||||||
|  | 			outline: none; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	> button { | 	> button { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue