From 759719d1249f8f8a5644dff3abf26278c77355c7 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Tue, 30 Apr 2019 12:15:41 +0900 Subject: [PATCH] Improve MisskeyPages --- locales/ja-JP.yml | 35 ++++++++-- src/client/app/common/scripts/aiscript.ts | 4 +- .../app/common/scripts/collect-page-vars.ts | 16 ++++- .../page-editor/els/page-editor.el.if.vue | 2 +- .../page-editor/els/page-editor.el.input.vue | 61 ----------------- .../els/page-editor.el.number-input.vue | 42 ++++++++++++ .../page-editor/els/page-editor.el.post.vue | 44 ++++++++++++ .../els/page-editor.el.section.vue | 2 +- .../els/page-editor.el.text-input.vue | 42 ++++++++++++ .../els/page-editor.el.textarea-input.vue | 42 ++++++++++++ .../els/page-editor.el.textarea.vue | 58 ++++++++++++++++ .../page-editor/page-editor.block.vue | 8 ++- .../components/page-editor/page-editor.vue | 33 +++++---- .../common/views/pages/page/page.block.vue | 8 ++- .../{page.input.vue => page.number-input.vue} | 6 +- .../app/common/views/pages/page/page.post.vue | 68 +++++++++++++++++++ .../views/pages/page/page.text-input.vue | 41 +++++++++++ .../views/pages/page/page.textarea-input.vue | 36 ++++++++++ .../common/views/pages/page/page.textarea.vue | 33 +++++++++ .../app/common/views/pages/page/page.vue | 5 +- src/models/repositories/page.ts | 27 ++++++++ 21 files changed, 520 insertions(+), 93 deletions(-) delete mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue rename src/client/app/common/views/pages/page/{page.input.vue => page.number-input.vue} (63%) create mode 100644 src/client/app/common/views/pages/page/page.post.vue create mode 100644 src/client/app/common/views/pages/page/page.text-input.vue create mode 100644 src/client/app/common/views/pages/page/page.textarea-input.vue create mode 100644 src/client/app/common/views/pages/page/page.textarea.vue diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index c732f841e0..cd29135bdb 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1867,28 +1867,50 @@ pages: select-type: "種類を選択" enter-variable-name: "変数名を決めてください" the-variable-name-is-already-used: "その変数名は既に使われています" + content-blocks: "コンテンツ" + input-blocks: "入力" + special-blocks: "特殊" + post-from-post-form: "この内容を投稿" + posted-from-post-form: "投稿しました" blocks: text: "テキスト" + textarea: "テキストエリア" section: "セクション" image: "画像" button: "ボタン" + if: "もし" _if: variable: "変数" - input: "ユーザー入力" - _input: + + post: "投稿フォーム" + _post: + text: "内容" + + textInput: "テキスト入力" + _textInput: name: "変数名" text: "タイトル" default: "デフォルト値" - inputType: "入力の種類" - _inputType: - string: "テキスト" - number: "数値" + + textareaInput: "複数行テキスト入力" + _textareaInput: + name: "変数名" + text: "タイトル" + default: "デフォルト値" + + numberInput: "数値入力" + _numberInput: + name: "変数名" + text: "タイトル" + default: "デフォルト値" + switch: "スイッチ" _switch: name: "変数名" text: "タイトル" default: "デフォルト値" + _button: text: "タイトル" action: "ボタンを押したときの動作" @@ -1897,6 +1919,7 @@ pages: _dialog: content: "内容" resetRandom: "乱数をリセット" + script: categories: flow: "制御" diff --git a/src/client/app/common/scripts/aiscript.ts b/src/client/app/common/scripts/aiscript.ts index 50c73421e1..99caec8c15 100644 --- a/src/client/app/common/scripts/aiscript.ts +++ b/src/client/app/common/scripts/aiscript.ts @@ -97,6 +97,7 @@ type PageVar = { name: string; value: any; type: Type; }; const envVarsDef = { AI: 'string', + URL: 'string', VERSION: 'string', LOGIN: 'boolean', NAME: 'string', @@ -120,7 +121,7 @@ export class AiScript { public static blockDefs = blockDefs; public static funcDefs = funcDefs; private opts: { - randomSeed?: string; user?: any; visitor?: any; + randomSeed?: string; user?: any; visitor?: any; page?: any; url?: string; }; constructor(variables: Variable[] = [], pageVars: PageVar[] = [], opts: AiScript['opts'] = {}) { @@ -131,6 +132,7 @@ export class AiScript { this.envVars = { AI: 'kawaii', VERSION: version, + URL: opts.page ? `${opts.url}/@${opts.page.user.username}/pages/${opts.page.name}` : '', LOGIN: opts.visitor != null, NAME: opts.visitor ? opts.visitor.name : '', USERNAME: opts.visitor ? opts.visitor.username : '', diff --git a/src/client/app/common/scripts/collect-page-vars.ts b/src/client/app/common/scripts/collect-page-vars.ts index 86687e21f4..92727ce6db 100644 --- a/src/client/app/common/scripts/collect-page-vars.ts +++ b/src/client/app/common/scripts/collect-page-vars.ts @@ -2,10 +2,22 @@ export function collectPageVars(content) { const pageVars = []; const collect = (xs: any[]) => { for (const x of xs) { - if (x.type === 'input') { + if (x.type === 'textInput') { pageVars.push({ name: x.name, - type: x.inputType, + type: 'string', + value: x.default + }); + } else if (x.type === 'textareaInput') { + pageVars.push({ + name: x.name, + type: 'string', + value: x.default + }); + } else if (x.type === 'numberInput') { + pageVars.push({ + name: x.name, + type: 'number', value: x.default }); } else if (x.type === 'switch') { diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue index 46920fafdc..87fc9e6faf 100644 --- a/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue @@ -72,7 +72,7 @@ export default Vue.extend({ type: null, title: this.$t('choose-block'), select: { - items: this.getPageBlockList() + groupedItems: this.getPageBlockList() }, showCancelButton: true }); diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue deleted file mode 100644 index b2bcb33c3d..0000000000 --- a/src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue +++ /dev/null @@ -1,61 +0,0 @@ -<template> -<x-container @remove="() => $emit('remove')"> - <template #header><fa :icon="faBolt"/> {{ $t('blocks.input') }}</template> - - <section class="dnvasjon"> - <ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._input.name') }}</span></ui-input> - <ui-input v-model="value.text"><span>{{ $t('blocks._input.text') }}</span></ui-input> - <ui-select v-model="value.inputType"> - <template #label>{{ $t('blocks._input.inputType') }}</template> - <option value="string">{{ $t('blocks._input._inputType.string') }}</option> - <option value="number">{{ $t('blocks._input._inputType.number') }}</option> - </ui-select> - <ui-input v-model="value.default" :type="value.inputType"><span>{{ $t('blocks._input.default') }}</span></ui-input> - </section> -</x-container> -</template> - -<script lang="ts"> -import Vue from 'vue'; -import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; -import i18n from '../../../../../i18n'; -import XContainer from '../page-editor.container.vue'; - -export default Vue.extend({ - i18n: i18n('pages'), - - components: { - XContainer - }, - - props: { - value: { - required: true - }, - }, - - data() { - return { - faBolt, faSquareRootAlt - }; - }, - - created() { - if (this.value.name == null) Vue.set(this.value, 'name', ''); - if (this.value.inputType == null) Vue.set(this.value, 'inputType', 'string'); - - this.$watch('value.inputType', t => { - if (this.value.default != null) { - if (t === 'number') this.value.default = parseInt(this.value.default, 10); - if (t === 'string') this.value.default = this.value.default.toString(); - } - }); - }, -}); -</script> - -<style lang="stylus" scoped> -.dnvasjon - padding 0 16px 0 16px - -</style> diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue new file mode 100644 index 0000000000..aff6cf6b6b --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue @@ -0,0 +1,42 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faBolt"/> {{ $t('blocks.numberInput') }}</template> + + <section style="padding: 0 16px 0 16px;"> + <ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._numberInput.name') }}</span></ui-input> + <ui-input v-model="value.text"><span>{{ $t('blocks._numberInput.text') }}</span></ui-input> + <ui-input v-model="value.default" type="number"><span>{{ $t('blocks._numberInput.default') }}</span></ui-input> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; + +export default Vue.extend({ + i18n: i18n('pages'), + + components: { + XContainer + }, + + props: { + value: { + required: true + }, + }, + + data() { + return { + faBolt, faSquareRootAlt + }; + }, + + created() { + if (this.value.name == null) Vue.set(this.value, 'name', ''); + }, +}); +</script> diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue new file mode 100644 index 0000000000..477d2c8ec5 --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue @@ -0,0 +1,44 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faPaperPlane"/> {{ $t('blocks.post') }}</template> + + <section> + <textarea v-model="value.text"></textarea> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faPaperPlane } from '@fortawesome/free-regular-svg-icons'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; + +export default Vue.extend({ + i18n: i18n('pages'), + + components: { + XContainer + }, + + props: { + value: { + required: true + }, + }, + + data() { + return { + faPaperPlane + }; + }, + + beforeCreate() { + this.$options.components.XBlock = require('../page-editor.block.vue').default + }, + + created() { + if (this.value.text == null) Vue.set(this.value, 'text', ''); + }, +}); +</script> diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue index 6133faf666..747de481a6 100644 --- a/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue @@ -84,7 +84,7 @@ export default Vue.extend({ type: null, title: this.$t('choose-block'), select: { - items: this.getPageBlockList() + groupedItems: this.getPageBlockList() }, showCancelButton: true }); diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue new file mode 100644 index 0000000000..6c4783fd7e --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue @@ -0,0 +1,42 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faBolt"/> {{ $t('blocks.textInput') }}</template> + + <section style="padding: 0 16px 0 16px;"> + <ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._textInput.name') }}</span></ui-input> + <ui-input v-model="value.text"><span>{{ $t('blocks._textInput.text') }}</span></ui-input> + <ui-input v-model="value.default" type="text"><span>{{ $t('blocks._textInput.default') }}</span></ui-input> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; + +export default Vue.extend({ + i18n: i18n('pages'), + + components: { + XContainer + }, + + props: { + value: { + required: true + }, + }, + + data() { + return { + faBolt, faSquareRootAlt + }; + }, + + created() { + if (this.value.name == null) Vue.set(this.value, 'name', ''); + }, +}); +</script> diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue new file mode 100644 index 0000000000..68edf13824 --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue @@ -0,0 +1,42 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faBolt"/> {{ $t('blocks.textareaInput') }}</template> + + <section style="padding: 0 16px 16px 16px;"> + <ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._textareaInput.name') }}</span></ui-input> + <ui-input v-model="value.text"><span>{{ $t('blocks._textareaInput.text') }}</span></ui-input> + <ui-textarea v-model="value.default"><span>{{ $t('blocks._textareaInput.default') }}</span></ui-textarea> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; + +export default Vue.extend({ + i18n: i18n('pages'), + + components: { + XContainer + }, + + props: { + value: { + required: true + }, + }, + + data() { + return { + faBolt, faSquareRootAlt + }; + }, + + created() { + if (this.value.name == null) Vue.set(this.value, 'name', ''); + }, +}); +</script> diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue new file mode 100644 index 0000000000..4fbe497960 --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue @@ -0,0 +1,58 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faAlignLeft"/> {{ $t('blocks.textarea') }}</template> + + <section class="ihymsbbe"> + <textarea v-model="value.text"></textarea> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faAlignLeft } from '@fortawesome/free-solid-svg-icons'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; + +export default Vue.extend({ + i18n: i18n('pages'), + + components: { + XContainer + }, + + props: { + value: { + required: true + }, + }, + + data() { + return { + faAlignLeft, + }; + }, + + created() { + if (this.value.text == null) Vue.set(this.value, 'text', ''); + }, +}); +</script> + +<style lang="stylus" scoped> +.ihymsbbe + > textarea + display block + -webkit-appearance none + -moz-appearance none + appearance none + width 100% + min-width 100% + min-height 150px + border none + box-shadow none + padding 16px + background transparent + color var(--text) + font-size 14px +</style> diff --git a/src/client/app/common/views/components/page-editor/page-editor.block.vue b/src/client/app/common/views/components/page-editor/page-editor.block.vue index 86ee3f6888..7d4505fca8 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.block.vue +++ b/src/client/app/common/views/components/page-editor/page-editor.block.vue @@ -6,15 +6,19 @@ import Vue from 'vue'; import XSection from './els/page-editor.el.section.vue'; import XText from './els/page-editor.el.text.vue'; +import XTextarea from './els/page-editor.el.textarea.vue'; import XImage from './els/page-editor.el.image.vue'; import XButton from './els/page-editor.el.button.vue'; -import XInput from './els/page-editor.el.input.vue'; +import XTextInput from './els/page-editor.el.text-input.vue'; +import XTextareaInput from './els/page-editor.el.textarea-input.vue'; +import XNumberInput from './els/page-editor.el.text-input.vue'; import XSwitch from './els/page-editor.el.switch.vue'; import XIf from './els/page-editor.el.if.vue'; +import XPost from './els/page-editor.el.post.vue'; export default Vue.extend({ components: { - XSection, XText, XImage, XButton, XInput, XSwitch, XIf + XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost }, props: { diff --git a/src/client/app/common/views/components/page-editor/page-editor.vue b/src/client/app/common/views/components/page-editor/page-editor.vue index f39985952b..f8959fb0f1 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.vue +++ b/src/client/app/common/views/components/page-editor/page-editor.vue @@ -259,7 +259,7 @@ export default Vue.extend({ type: null, title: this.$t('choose-block'), select: { - items: this.getPageBlockList() + groupedItems: this.getPageBlockList() }, showCancelButton: true }); @@ -323,19 +323,28 @@ export default Vue.extend({ getPageBlockList() { return [{ - value: 'section', text: this.$t('blocks.section') + label: this.$t('content-blocks'), + items: [ + { value: 'section', text: this.$t('blocks.section') }, + { value: 'text', text: this.$t('blocks.text') }, + { value: 'image', text: this.$t('blocks.image') }, + { value: 'textarea', text: this.$t('blocks.textarea') }, + ] }, { - value: 'text', text: this.$t('blocks.text') + label: this.$t('input-blocks'), + items: [ + { value: 'button', text: this.$t('blocks.button') }, + { value: 'textInput', text: this.$t('blocks.textInput') }, + { value: 'textareaInput', text: this.$t('blocks.textareaInput') }, + { value: 'numberInput', text: this.$t('blocks.numberInput') }, + { value: 'switch', text: this.$t('blocks.switch') } + ] }, { - value: 'image', text: this.$t('blocks.image') - }, { - value: 'button', text: this.$t('blocks.button') - }, { - value: 'input', text: this.$t('blocks.input') - }, { - value: 'switch', text: this.$t('blocks.switch') - }, { - value: 'if', text: this.$t('blocks.if') + label: this.$t('special-blocks'), + items: [ + { value: 'if', text: this.$t('blocks.if') }, + { value: 'post', text: this.$t('blocks.post') } + ] }]; }, diff --git a/src/client/app/common/views/pages/page/page.block.vue b/src/client/app/common/views/pages/page/page.block.vue index e3a758ed4e..f348107cc7 100644 --- a/src/client/app/common/views/pages/page/page.block.vue +++ b/src/client/app/common/views/pages/page/page.block.vue @@ -8,13 +8,17 @@ import XText from './page.text.vue'; import XSection from './page.section.vue'; import XImage from './page.image.vue'; import XButton from './page.button.vue'; -import XInput from './page.input.vue'; +import XNumberInput from './page.number-input.vue'; +import XTextInput from './page.text-input.vue'; +import XTextareaInput from './page.textarea-input.vue'; import XSwitch from './page.switch.vue'; import XIf from './page.if.vue'; +import XTextarea from './page.textarea.vue'; +import XPost from './page.post.vue'; export default Vue.extend({ components: { - XText, XSection, XImage, XButton, XInput, XSwitch, XIf + XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf }, props: { diff --git a/src/client/app/common/views/pages/page/page.input.vue b/src/client/app/common/views/pages/page/page.number-input.vue similarity index 63% rename from src/client/app/common/views/pages/page/page.input.vue rename to src/client/app/common/views/pages/page/page.number-input.vue index 9f4cfd91f3..51d538c369 100644 --- a/src/client/app/common/views/pages/page/page.input.vue +++ b/src/client/app/common/views/pages/page/page.number-input.vue @@ -1,6 +1,6 @@ <template> <div> - <ui-input class="kudkigyw" v-model="v" :type="value.inputType">{{ script.interpolate(value.text) }}</ui-input> + <ui-input class="kudkigyw" v-model="v" type="number">{{ script.interpolate(value.text) }}</ui-input> </div> </template> @@ -25,9 +25,7 @@ export default Vue.extend({ watch: { v() { - let v = this.v; - if (this.value.inputType === 'number') v = parseInt(v, 10); - this.script.aiScript.updatePageVar(this.value.name, v); + this.script.aiScript.updatePageVar(this.value.name, this.v); this.script.reEval(); } } diff --git a/src/client/app/common/views/pages/page/page.post.vue b/src/client/app/common/views/pages/page/page.post.vue new file mode 100644 index 0000000000..cb695e21e9 --- /dev/null +++ b/src/client/app/common/views/pages/page/page.post.vue @@ -0,0 +1,68 @@ +<template> +<div class="ngbfujlo"> + <ui-textarea class="textarea" :value="text" readonly></ui-textarea> + <ui-button primary @click="post()" :disabled="posting || posted">{{ posted ? $t('posted-from-post-form') : $t('post-from-post-form') }}</ui-button> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../../i18n'; + +export default Vue.extend({ + i18n: i18n('pages'), + + props: { + value: { + required: true + }, + script: { + required: true + } + }, + + data() { + return { + text: this.script.interpolate(this.value.text), + posted: false, + posting: false, + }; + }, + + created() { + this.$watch('script.vars', () => { + this.text = this.script.interpolate(this.value.text); + }, { deep: true }); + }, + + methods: { + post() { + this.posting = true; + this.$root.api('notes/create', { + text: this.text, + }).then(() => { + this.posted = true; + this.$root.dialog({ + type: 'success', + splash: true + }); + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.ngbfujlo + padding 0 32px 32px 32px + border solid 2px var(--pageBlockBorder) + border-radius 6px + + @media (max-width 600px) + padding 0 16px 16px 16px + + > .textarea + margin-top 16px + margin-bottom 16px + +</style> diff --git a/src/client/app/common/views/pages/page/page.text-input.vue b/src/client/app/common/views/pages/page/page.text-input.vue new file mode 100644 index 0000000000..3d659edd5e --- /dev/null +++ b/src/client/app/common/views/pages/page/page.text-input.vue @@ -0,0 +1,41 @@ +<template> +<div> + <ui-input class="kudkigyw" v-model="v" type="text">{{ script.interpolate(value.text) }}</ui-input> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: { + value: { + required: true + }, + script: { + required: true + } + }, + + data() { + return { + v: this.value.default, + }; + }, + + watch: { + v() { + this.script.aiScript.updatePageVar(this.value.name, this.v); + this.script.reEval(); + } + } +}); +</script> + +<style lang="stylus" scoped> +.kudkigyw + display inline-block + min-width 300px + max-width 450px + margin 8px 0 +</style> diff --git a/src/client/app/common/views/pages/page/page.textarea-input.vue b/src/client/app/common/views/pages/page/page.textarea-input.vue new file mode 100644 index 0000000000..fd8174c273 --- /dev/null +++ b/src/client/app/common/views/pages/page/page.textarea-input.vue @@ -0,0 +1,36 @@ +<template> +<div> + <ui-textarea class="" v-model="v">{{ script.interpolate(value.text) }}</ui-textarea> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: { + value: { + required: true + }, + script: { + required: true + } + }, + + data() { + return { + v: this.value.default, + }; + }, + + watch: { + v() { + this.script.aiScript.updatePageVar(this.value.name, this.v); + this.script.reEval(); + } + } +}); +</script> + +<style lang="stylus" scoped> +</style> diff --git a/src/client/app/common/views/pages/page/page.textarea.vue b/src/client/app/common/views/pages/page/page.textarea.vue new file mode 100644 index 0000000000..03c8542cb0 --- /dev/null +++ b/src/client/app/common/views/pages/page/page.textarea.vue @@ -0,0 +1,33 @@ +<template> +<ui-textarea class="" :value="text" readonly></ui-textarea> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: { + value: { + required: true + }, + script: { + required: true + } + }, + + data() { + return { + text: this.script.interpolate(this.value.text), + }; + }, + + created() { + this.$watch('script.vars', () => { + this.text = this.script.interpolate(this.value.text); + }, { deep: true }); + } +}); +</script> + +<style lang="stylus" scoped> +</style> diff --git a/src/client/app/common/views/pages/page/page.vue b/src/client/app/common/views/pages/page/page.vue index 7cbd3ed81b..88598d3527 100644 --- a/src/client/app/common/views/pages/page/page.vue +++ b/src/client/app/common/views/pages/page/page.vue @@ -23,6 +23,7 @@ import { faSave, faStickyNote } from '@fortawesome/free-regular-svg-icons'; import XBlock from './page.block.vue'; import { AiScript } from '../../../scripts/aiscript'; import { collectPageVars } from '../../../scripts/collect-page-vars'; +import { url } from '../../../../config'; class Script { public aiScript: AiScript; @@ -82,7 +83,9 @@ export default Vue.extend({ this.script = new Script(new AiScript(this.page.variables, pageVars, { randomSeed: Math.random(), user: page.user, - visitor: this.$store.state.i + visitor: this.$store.state.i, + page: page, + url: url })); }); }, diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts index 4c1b4cc793..cbe385568e 100644 --- a/src/models/repositories/page.ts +++ b/src/models/repositories/page.ts @@ -27,6 +27,33 @@ export class PageRepository extends Repository<Page> { } }; collectFile(src.content); + + // 後方互換性のため + let migrated = false; + const migrate = (xs: any[]) => { + for (const x of xs) { + if (x.type === 'input') { + if (x.inputType === 'text') { + x.type = 'textInput'; + } + if (x.inputType === 'number') { + x.type = 'numberInput'; + if (x.default) x.default = parseInt(x.default, 10); + } + migrated = true; + } + if (x.children) { + migrate(x.children); + } + } + }; + migrate(src.content); + if (migrated) { + this.update(src.id, { + content: src.content + }); + } + return await awaitAll({ id: src.id, createdAt: src.createdAt.toISOString(),