From 2e8e5c2751aba86a03c564dc7aa2dc7e595caac5 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Tue, 30 Apr 2019 06:40:02 +0900 Subject: [PATCH] Improve MisskeyPages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ifブロック を追加 * ボタンやスイッチなどのテキストに変数使えるようにした --- locales/ja-JP.yml | 4 + .../page-editor.el.button.vue} | 4 +- .../page-editor/els/page-editor.el.if.vue | 113 ++++++++++++++++++ .../page-editor.el.image.vue} | 6 +- .../page-editor.el.input.vue} | 4 +- .../page-editor.el.section.vue} | 29 ++--- .../page-editor.el.switch.vue} | 4 +- .../page-editor.el.text.vue} | 4 +- .../page-editor/page-editor.block.vue | 22 ++-- .../components/page-editor/page-editor.vue | 62 ++++++---- .../common/views/pages/page/page.block.vue | 3 +- .../common/views/pages/page/page.button.vue | 2 +- .../app/common/views/pages/page/page.if.vue | 30 +++++ .../common/views/pages/page/page.input.vue | 2 +- .../common/views/pages/page/page.switch.vue | 2 +- .../app/common/views/pages/page/page.vue | 1 + 16 files changed, 227 insertions(+), 65 deletions(-) rename src/client/app/common/views/components/page-editor/{page-editor.button.vue => els/page-editor.el.button.vue} (93%) create mode 100644 src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue rename src/client/app/common/views/components/page-editor/{page-editor.image.vue => els/page-editor.el.image.vue} (89%) rename src/client/app/common/views/components/page-editor/{page-editor.input.vue => els/page-editor.el.input.vue} (94%) rename src/client/app/common/views/components/page-editor/{page-editor.section.vue => els/page-editor.el.section.vue} (80%) rename src/client/app/common/views/components/page-editor/{page-editor.switch.vue => els/page-editor.el.switch.vue} (91%) rename src/client/app/common/views/components/page-editor/{page-editor.text.vue => els/page-editor.el.text.vue} (90%) create mode 100644 src/client/app/common/views/pages/page/page.if.vue diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e2bfb2e896..343d9cfc39 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1842,6 +1842,7 @@ dev/views/new-app.vue: pages: new-page: "ページの作成" edit-page: "ページの編集" + read-page: "ソースを表示中" page-created: "ページを作成しました" page-updated: "ページを更新しました" are-you-sure-delete: "このページを削除しますか?" @@ -1871,6 +1872,9 @@ pages: section: "セクション" image: "画像" button: "ボタン" + if: "もし" + _if: + variable: "変数" input: "ユーザー入力" _input: name: "変数名" diff --git a/src/client/app/common/views/components/page-editor/page-editor.button.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue similarity index 93% rename from src/client/app/common/views/components/page-editor/page-editor.button.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue index d5fc243818..3e2d3fe19d 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.button.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue @@ -16,9 +16,9 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; import { faBolt } from '@fortawesome/free-solid-svg-icons'; -import XContainer from './page-editor.container.vue'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; export default Vue.extend({ i18n: i18n('pages'), 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 new file mode 100644 index 0000000000..46920fafdc --- /dev/null +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue @@ -0,0 +1,113 @@ +<template> +<x-container @remove="() => $emit('remove')"> + <template #header><fa :icon="faQuestion"/> {{ $t('blocks.if') }}</template> + <template #func> + <button @click="add()"> + <fa :icon="faPlus"/> + </button> + </template> + + <section class="romcojzs"> + <ui-select v-model="value.var"> + <template #label>{{ $t('blocks._if.variable') }}</template> + <option v-for="v in aiScript.getVarsByType('boolean')" :value="v.name">{{ v.name }}</option> + <optgroup :label="$t('script.pageVariables')"> + <option v-for="v in aiScript.getPageVarsByType('boolean')" :value="v">{{ v }}</option> + </optgroup> + <optgroup :label="$t('script.enviromentVariables')"> + <option v-for="v in aiScript.getEnvVarsByType('boolean')" :value="v">{{ v }}</option> + </optgroup> + </ui-select> + + <div class="children"> + <x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/> + </div> + </section> +</x-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import * as uuid from 'uuid'; +import { faPlus, faQuestion } 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 + }, + + inject: ['getPageBlockList'], + + props: { + value: { + required: true + }, + aiScript: { + required: true, + }, + }, + + data() { + return { + faPlus, faQuestion + }; + }, + + beforeCreate() { + this.$options.components.XBlock = require('../page-editor.block.vue').default + }, + + created() { + if (this.value.children == null) Vue.set(this.value, 'children', []); + if (this.value.var === undefined) Vue.set(this.value, 'var', null); + }, + + methods: { + async add() { + const { canceled, result: type } = await this.$root.dialog({ + type: null, + title: this.$t('choose-block'), + select: { + items: this.getPageBlockList() + }, + showCancelButton: true + }); + if (canceled) return; + + const id = uuid.v4(); + this.value.children.push({ id, type }); + }, + + updateItem(v) { + const i = this.value.children.findIndex(x => x.id === v.id); + const newValue = [ + ...this.value.children.slice(0, i), + v, + ...this.value.children.slice(i + 1) + ]; + this.value.children = newValue; + this.$emit('input', this.value); + }, + + remove(el) { + const i = this.value.children.findIndex(x => x.id === el.id); + const newValue = [ + ...this.value.children.slice(0, i), + ...this.value.children.slice(i + 1) + ]; + this.value.children = newValue; + this.$emit('input', this.value); + } + } +}); +</script> + +<style lang="stylus" scoped> +.romcojzs + padding 0 16px 16px 16px + +</style> diff --git a/src/client/app/common/views/components/page-editor/page-editor.image.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue similarity index 89% rename from src/client/app/common/views/components/page-editor/page-editor.image.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue index 0bc1816e8d..5ada8c77ba 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.image.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue @@ -15,11 +15,11 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; import { faPencilAlt } from '@fortawesome/free-solid-svg-icons'; import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons'; -import XContainer from './page-editor.container.vue'; -import XFileThumbnail from '../drive-file-thumbnail.vue'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; +import XFileThumbnail from '../../drive-file-thumbnail.vue'; export default Vue.extend({ i18n: i18n('pages'), diff --git a/src/client/app/common/views/components/page-editor/page-editor.input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue similarity index 94% rename from src/client/app/common/views/components/page-editor/page-editor.input.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue index 4e13840439..b2bcb33c3d 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.input.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.input.vue @@ -17,9 +17,9 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; -import XContainer from './page-editor.container.vue'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; export default Vue.extend({ i18n: i18n('pages'), diff --git a/src/client/app/common/views/components/page-editor/page-editor.section.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue similarity index 80% rename from src/client/app/common/views/components/page-editor/page-editor.section.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue index d7a247b0b1..6133faf666 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.section.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue @@ -12,7 +12,7 @@ <section class="ilrvjyvi"> <div class="children"> - <x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id"/> + <x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/> </div> </section> </x-container> @@ -20,11 +20,11 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; +import * as uuid from 'uuid'; import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; import { faStickyNote } from '@fortawesome/free-regular-svg-icons'; -import XContainer from './page-editor.container.vue'; -import * as uuid from 'uuid'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; export default Vue.extend({ i18n: i18n('pages'), @@ -33,10 +33,15 @@ export default Vue.extend({ XContainer }, + inject: ['getPageBlockList'], + props: { value: { required: true }, + aiScript: { + required: true, + }, }, data() { @@ -46,7 +51,7 @@ export default Vue.extend({ }, beforeCreate() { - this.$options.components.XBlock = require('./page-editor.block.vue').default + this.$options.components.XBlock = require('../page-editor.block.vue').default }, created() { @@ -79,19 +84,7 @@ export default Vue.extend({ type: null, title: this.$t('choose-block'), select: { - items: [{ - value: 'section', text: this.$t('blocks.section') - }, { - value: 'text', text: this.$t('blocks.text') - }, { - 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') - }] + items: this.getPageBlockList() }, showCancelButton: true }); diff --git a/src/client/app/common/views/components/page-editor/page-editor.switch.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue similarity index 91% rename from src/client/app/common/views/components/page-editor/page-editor.switch.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue index a9cfa2844f..3404404d99 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.switch.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue @@ -12,9 +12,9 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons'; -import XContainer from './page-editor.container.vue'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; export default Vue.extend({ i18n: i18n('pages'), diff --git a/src/client/app/common/views/components/page-editor/page-editor.text.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue similarity index 90% rename from src/client/app/common/views/components/page-editor/page-editor.text.vue rename to src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue index 7368931b2f..b6b56a29fd 100644 --- a/src/client/app/common/views/components/page-editor/page-editor.text.vue +++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue @@ -10,9 +10,9 @@ <script lang="ts"> import Vue from 'vue'; -import i18n from '../../../../i18n'; import { faAlignLeft } from '@fortawesome/free-solid-svg-icons'; -import XContainer from './page-editor.container.vue'; +import i18n from '../../../../../i18n'; +import XContainer from '../page-editor.container.vue'; export default Vue.extend({ i18n: i18n('pages'), 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 a3e1488d1b..86ee3f6888 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 @@ -1,25 +1,29 @@ <template> -<component :is="'x-' + value.type" :value="value" @input="v => updateItem(v)" @remove="() => $emit('remove', value)" :key="value.id"/> +<component :is="'x-' + value.type" :value="value" @input="v => updateItem(v)" @remove="() => $emit('remove', value)" :key="value.id" :ai-script="aiScript"/> </template> <script lang="ts"> import Vue from 'vue'; -import XSection from './page-editor.section.vue'; -import XText from './page-editor.text.vue'; -import XImage from './page-editor.image.vue'; -import XButton from './page-editor.button.vue'; -import XInput from './page-editor.input.vue'; -import XSwitch from './page-editor.switch.vue'; +import XSection from './els/page-editor.el.section.vue'; +import XText from './els/page-editor.el.text.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 XSwitch from './els/page-editor.el.switch.vue'; +import XIf from './els/page-editor.el.if.vue'; export default Vue.extend({ components: { - XSection, XText, XImage, XButton, XInput, XSwitch + XSection, XText, XImage, XButton, XInput, XSwitch, XIf }, props: { value: { required: true - } + }, + aiScript: { + required: true, + }, }, }); </script> 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 8b25828515..f39985952b 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 @@ -2,16 +2,16 @@ <div> <div class="gwbmwxkm" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners }"> <header> - <div class="title"><fa :icon="faStickyNote"/> {{ pageId ? $t('edit-page') : $t('new-page') }}</div> + <div class="title"><fa :icon="faStickyNote"/> {{ readonly ? $t('read-page') : pageId ? $t('edit-page') : $t('new-page') }}</div> <div class="buttons"> - <button @click="del()"><fa :icon="faTrashAlt"/></button> + <button @click="del()" v-if="!readonly"><fa :icon="faTrashAlt"/></button> <button @click="() => showOptions = !showOptions"><fa :icon="faCog"/></button> - <button @click="save()"><fa :icon="faSave"/></button> + <button @click="save()" v-if="!readonly"><fa :icon="faSave"/></button> </div> </header> <section> - <a class="view" v-if="pageId" :href="`/@${ $store.state.i.username }/pages/${ currentName }`" target="_blank"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</a> + <a class="view" v-if="pageId" :href="`/@${ author.username }/pages/${ currentName }`" target="_blank"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</a> <ui-input v-model="title"> <span>{{ $t('title') }}</span> @@ -23,7 +23,7 @@ </ui-input> <ui-input v-model="name"> - <template #prefix>{{ url }}/@{{ $store.state.i.username }}/pages/</template> + <template #prefix>{{ url }}/@{{ author.username }}/pages/</template> <span>{{ $t('url') }}</span> </ui-input> @@ -45,10 +45,10 @@ </template> <div class="content" v-for="child in content"> - <x-block :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id"/> + <x-block :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/> </div> - <ui-button @click="add()"><fa :icon="faPlus"/></ui-button> + <ui-button @click="add()" v-if="!readonly"><fa :icon="faPlus"/></ui-button> </section> </div> @@ -70,7 +70,7 @@ </template> </div> - <ui-button @click="addVariable()" class="add"><fa :icon="faPlus"/></ui-button> + <ui-button @click="addVariable()" class="add" v-if="!readonly"><fa :icon="faPlus"/></ui-button> <ui-info><span v-html="$t('variables-info')"></span><a @click="() => moreDetails = true" style="display:block;">{{ $t('more-details') }}</a></ui-info> @@ -106,11 +106,17 @@ export default Vue.extend({ page: { type: String, required: false - } + }, + readonly: { + type: Boolean, + required: false, + default: false + }, }, data() { return { + author: this.$store.state.i, pageId: null, currentName: null, title: '', @@ -157,6 +163,7 @@ export default Vue.extend({ this.$root.api('pages/show', { pageId: this.page, }).then(page => { + this.author = page.user; this.pageId = page.id; this.title = page.title; this.name = page.name; @@ -180,7 +187,9 @@ export default Vue.extend({ provide() { return { - getScriptBlockList: this.getScriptBlockList + readonly: this.readonly, + getScriptBlockList: this.getScriptBlockList, + getPageBlockList: this.getPageBlockList } }, @@ -250,19 +259,7 @@ export default Vue.extend({ type: null, title: this.$t('choose-block'), select: { - items: [{ - value: 'section', text: this.$t('blocks.section') - }, { - value: 'text', text: this.$t('blocks.text') - }, { - 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') - }] + items: this.getPageBlockList() }, showCancelButton: true }); @@ -324,6 +321,24 @@ export default Vue.extend({ this.variables = newValue; }, + getPageBlockList() { + return [{ + value: 'section', text: this.$t('blocks.section') + }, { + value: 'text', text: this.$t('blocks.text') + }, { + 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') + }]; + }, + getScriptBlockList(type: string = null) { const list = []; @@ -436,6 +451,7 @@ export default Vue.extend({ > .view display inline-block margin 16px 0 0 0 + font-size 14px > .content margin-bottom 16px 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 48a89f9de7..e3a758ed4e 100644 --- a/src/client/app/common/views/pages/page/page.block.vue +++ b/src/client/app/common/views/pages/page/page.block.vue @@ -10,10 +10,11 @@ import XImage from './page.image.vue'; import XButton from './page.button.vue'; import XInput from './page.input.vue'; import XSwitch from './page.switch.vue'; +import XIf from './page.if.vue'; export default Vue.extend({ components: { - XText, XSection, XImage, XButton, XInput, XSwitch + XText, XSection, XImage, XButton, XInput, XSwitch, XIf }, props: { diff --git a/src/client/app/common/views/pages/page/page.button.vue b/src/client/app/common/views/pages/page/page.button.vue index 5063d27122..b77d856d5d 100644 --- a/src/client/app/common/views/pages/page/page.button.vue +++ b/src/client/app/common/views/pages/page/page.button.vue @@ -1,6 +1,6 @@ <template> <div> - <ui-button class="kudkigyw" @click="click()">{{ value.text }}</ui-button> + <ui-button class="kudkigyw" @click="click()">{{ script.interpolate(value.text) }}</ui-button> </div> </template> diff --git a/src/client/app/common/views/pages/page/page.if.vue b/src/client/app/common/views/pages/page/page.if.vue new file mode 100644 index 0000000000..9dbeaf64fb --- /dev/null +++ b/src/client/app/common/views/pages/page/page.if.vue @@ -0,0 +1,30 @@ +<template> +<div v-show="script.vars.find(x => x.name === value.var).value"> + <x-block v-for="child in value.children" :value="child" :page="page" :script="script" :key="child.id" :h="h"/> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: { + value: { + required: true + }, + script: { + required: true + }, + page: { + required: true + }, + h: { + required: true + } + }, + + beforeCreate() { + this.$options.components.XBlock = require('./page.block.vue').default + }, +}); +</script> diff --git a/src/client/app/common/views/pages/page/page.input.vue b/src/client/app/common/views/pages/page/page.input.vue index cda5550337..9f4cfd91f3 100644 --- a/src/client/app/common/views/pages/page/page.input.vue +++ b/src/client/app/common/views/pages/page/page.input.vue @@ -1,6 +1,6 @@ <template> <div> - <ui-input class="kudkigyw" v-model="v" :type="value.inputType">{{ value.text }}</ui-input> + <ui-input class="kudkigyw" v-model="v" :type="value.inputType">{{ script.interpolate(value.text) }}</ui-input> </div> </template> diff --git a/src/client/app/common/views/pages/page/page.switch.vue b/src/client/app/common/views/pages/page/page.switch.vue index 962ab84bb5..d36ecbfba1 100644 --- a/src/client/app/common/views/pages/page/page.switch.vue +++ b/src/client/app/common/views/pages/page/page.switch.vue @@ -1,6 +1,6 @@ <template> <div class="hkcxmtwj"> - <ui-switch v-model="v">{{ value.text }}</ui-switch> + <ui-switch v-model="v">{{ script.interpolate(value.text) }}</ui-switch> </div> </template> diff --git a/src/client/app/common/views/pages/page/page.vue b/src/client/app/common/views/pages/page/page.vue index e7e8f76d53..7cbd3ed81b 100644 --- a/src/client/app/common/views/pages/page/page.vue +++ b/src/client/app/common/views/pages/page/page.vue @@ -38,6 +38,7 @@ class Script { } public interpolate(str: string) { + if (str == null) return null; return str.replace(/\{(.+?)\}/g, match => { const v = this.vars.find(x => x.name === match.slice(1, -1).trim()).value; return v == null ? 'NULL' : v.toString();