mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-12 12:40:54 +01:00
Merge branch 'develop'
This commit is contained in:
commit
dc072d4706
33 changed files with 767 additions and 144 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -42,6 +42,20 @@ mongodb:
|
||||||
8. master ブランチに戻す
|
8. master ブランチに戻す
|
||||||
9. enjoy
|
9. enjoy
|
||||||
|
|
||||||
|
11.7.0 (2019/04/30)
|
||||||
|
-------------------
|
||||||
|
### Improvements
|
||||||
|
* MisskeyPagesに ifブロック を追加
|
||||||
|
* MisskeyPagesに テキストエリア を追加
|
||||||
|
* MisskeyPagesに 複数行テキスト入力 を追加
|
||||||
|
* MisskeyPagesに 投稿フォーム を追加
|
||||||
|
* MisskeyPagesに 変換系関数 を追加
|
||||||
|
* MisskeyPagesでボタンやスイッチなどのテキストに変数使えるように
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* OGPのサイト名を修正
|
||||||
|
* デザインの調整
|
||||||
|
|
||||||
11.6.0 (2019/04/29)
|
11.6.0 (2019/04/29)
|
||||||
-------------------
|
-------------------
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
|
@ -1842,6 +1842,7 @@ dev/views/new-app.vue:
|
||||||
pages:
|
pages:
|
||||||
new-page: "ページの作成"
|
new-page: "ページの作成"
|
||||||
edit-page: "ページの編集"
|
edit-page: "ページの編集"
|
||||||
|
read-page: "ソースを表示中"
|
||||||
page-created: "ページを作成しました"
|
page-created: "ページを作成しました"
|
||||||
page-updated: "ページを更新しました"
|
page-updated: "ページを更新しました"
|
||||||
are-you-sure-delete: "このページを削除しますか?"
|
are-you-sure-delete: "このページを削除しますか?"
|
||||||
|
@ -1866,25 +1867,50 @@ pages:
|
||||||
select-type: "種類を選択"
|
select-type: "種類を選択"
|
||||||
enter-variable-name: "変数名を決めてください"
|
enter-variable-name: "変数名を決めてください"
|
||||||
the-variable-name-is-already-used: "その変数名は既に使われています"
|
the-variable-name-is-already-used: "その変数名は既に使われています"
|
||||||
|
content-blocks: "コンテンツ"
|
||||||
|
input-blocks: "入力"
|
||||||
|
special-blocks: "特殊"
|
||||||
|
post-from-post-form: "この内容を投稿"
|
||||||
|
posted-from-post-form: "投稿しました"
|
||||||
blocks:
|
blocks:
|
||||||
text: "テキスト"
|
text: "テキスト"
|
||||||
|
textarea: "テキストエリア"
|
||||||
section: "セクション"
|
section: "セクション"
|
||||||
image: "画像"
|
image: "画像"
|
||||||
button: "ボタン"
|
button: "ボタン"
|
||||||
input: "ユーザー入力"
|
|
||||||
_input:
|
if: "もし"
|
||||||
|
_if:
|
||||||
|
variable: "変数"
|
||||||
|
|
||||||
|
post: "投稿フォーム"
|
||||||
|
_post:
|
||||||
|
text: "内容"
|
||||||
|
|
||||||
|
textInput: "テキスト入力"
|
||||||
|
_textInput:
|
||||||
name: "変数名"
|
name: "変数名"
|
||||||
text: "タイトル"
|
text: "タイトル"
|
||||||
default: "デフォルト値"
|
default: "デフォルト値"
|
||||||
inputType: "入力の種類"
|
|
||||||
_inputType:
|
textareaInput: "複数行テキスト入力"
|
||||||
string: "テキスト"
|
_textareaInput:
|
||||||
number: "数値"
|
name: "変数名"
|
||||||
|
text: "タイトル"
|
||||||
|
default: "デフォルト値"
|
||||||
|
|
||||||
|
numberInput: "数値入力"
|
||||||
|
_numberInput:
|
||||||
|
name: "変数名"
|
||||||
|
text: "タイトル"
|
||||||
|
default: "デフォルト値"
|
||||||
|
|
||||||
switch: "スイッチ"
|
switch: "スイッチ"
|
||||||
_switch:
|
_switch:
|
||||||
name: "変数名"
|
name: "変数名"
|
||||||
text: "タイトル"
|
text: "タイトル"
|
||||||
default: "デフォルト値"
|
default: "デフォルト値"
|
||||||
|
|
||||||
_button:
|
_button:
|
||||||
text: "タイトル"
|
text: "タイトル"
|
||||||
action: "ボタンを押したときの動作"
|
action: "ボタンを押したときの動作"
|
||||||
|
@ -1893,6 +1919,7 @@ pages:
|
||||||
_dialog:
|
_dialog:
|
||||||
content: "内容"
|
content: "内容"
|
||||||
resetRandom: "乱数をリセット"
|
resetRandom: "乱数をリセット"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
categories:
|
categories:
|
||||||
flow: "制御"
|
flow: "制御"
|
||||||
|
@ -1903,6 +1930,7 @@ pages:
|
||||||
value: "値"
|
value: "値"
|
||||||
fn: "関数"
|
fn: "関数"
|
||||||
text: "テキスト操作"
|
text: "テキスト操作"
|
||||||
|
convert: "変換"
|
||||||
blocks:
|
blocks:
|
||||||
text: "テキスト"
|
text: "テキスト"
|
||||||
multiLineText: "テキスト(複数行)"
|
multiLineText: "テキスト(複数行)"
|
||||||
|
@ -2001,8 +2029,14 @@ pages:
|
||||||
_dailyRandomPick:
|
_dailyRandomPick:
|
||||||
arg1: "リスト"
|
arg1: "リスト"
|
||||||
number: "数"
|
number: "数"
|
||||||
|
stringToNumber: "テキストを数値に"
|
||||||
|
_stringToNumber:
|
||||||
|
arg1: "テキスト"
|
||||||
|
numberToString: "数値をテキストに"
|
||||||
|
_numberToString:
|
||||||
|
arg1: "数値"
|
||||||
ref: "変数"
|
ref: "変数"
|
||||||
in: "入力"
|
in: "引数"
|
||||||
_in:
|
_in:
|
||||||
arg1: "スロット番号"
|
arg1: "スロット番号"
|
||||||
fn: "関数"
|
fn: "関数"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "11.6.0",
|
"version": "11.7.0",
|
||||||
"codename": "daybreak",
|
"codename": "daybreak",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
faNotEqual,
|
faNotEqual,
|
||||||
faDice,
|
faDice,
|
||||||
faSortNumericUp,
|
faSortNumericUp,
|
||||||
|
faExchangeAlt,
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faFlag } from '@fortawesome/free-regular-svg-icons';
|
import { faFlag } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
|
@ -69,11 +70,13 @@ const funcDefs = {
|
||||||
strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: faQuoteRight, },
|
strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: faQuoteRight, },
|
||||||
strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: faQuoteRight, },
|
strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: faQuoteRight, },
|
||||||
strReverse: { in: ['string'], out: 'string', category: 'text', icon: faQuoteRight, },
|
strReverse: { in: ['string'], out: 'string', category: 'text', icon: faQuoteRight, },
|
||||||
|
stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: faExchangeAlt, },
|
||||||
|
numberToString: { in: ['number'], out: 'string', category: 'convert', icon: faExchangeAlt, },
|
||||||
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
||||||
random: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, },
|
|
||||||
randomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
|
||||||
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
||||||
|
random: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, },
|
||||||
dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, },
|
dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, },
|
||||||
|
randomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
||||||
dailyRandomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
dailyRandomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,6 +97,7 @@ type PageVar = { name: string; value: any; type: Type; };
|
||||||
|
|
||||||
const envVarsDef = {
|
const envVarsDef = {
|
||||||
AI: 'string',
|
AI: 'string',
|
||||||
|
URL: 'string',
|
||||||
VERSION: 'string',
|
VERSION: 'string',
|
||||||
LOGIN: 'boolean',
|
LOGIN: 'boolean',
|
||||||
NAME: 'string',
|
NAME: 'string',
|
||||||
|
@ -117,7 +121,7 @@ export class AiScript {
|
||||||
public static blockDefs = blockDefs;
|
public static blockDefs = blockDefs;
|
||||||
public static funcDefs = funcDefs;
|
public static funcDefs = funcDefs;
|
||||||
private opts: {
|
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'] = {}) {
|
constructor(variables: Variable[] = [], pageVars: PageVar[] = [], opts: AiScript['opts'] = {}) {
|
||||||
|
@ -128,6 +132,7 @@ export class AiScript {
|
||||||
this.envVars = {
|
this.envVars = {
|
||||||
AI: 'kawaii',
|
AI: 'kawaii',
|
||||||
VERSION: version,
|
VERSION: version,
|
||||||
|
URL: opts.page ? `${opts.url}/@${opts.page.user.username}/pages/${opts.page.name}` : '',
|
||||||
LOGIN: opts.visitor != null,
|
LOGIN: opts.visitor != null,
|
||||||
NAME: opts.visitor ? opts.visitor.name : '',
|
NAME: opts.visitor ? opts.visitor.name : '',
|
||||||
USERNAME: opts.visitor ? opts.visitor.username : '',
|
USERNAME: opts.visitor ? opts.visitor.username : '',
|
||||||
|
@ -421,6 +426,8 @@ export class AiScript {
|
||||||
strPick: (a, b) => a[b - 1],
|
strPick: (a, b) => a[b - 1],
|
||||||
strReplace: (a, b, c) => a.split(b).join(c),
|
strReplace: (a, b, c) => a.split(b).join(c),
|
||||||
strReverse: (a) => a.split('').reverse().join(''),
|
strReverse: (a) => a.split('').reverse().join(''),
|
||||||
|
stringToNumber: (a) => parseInt(a),
|
||||||
|
numberToString: (a) => a.toString(),
|
||||||
random: (probability) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
|
random: (probability) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
|
||||||
rannum: (min, max) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
|
rannum: (min, max) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
|
||||||
randomPick: (list) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],
|
randomPick: (list) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],
|
||||||
|
|
|
@ -2,10 +2,22 @@ export function collectPageVars(content) {
|
||||||
const pageVars = [];
|
const pageVars = [];
|
||||||
const collect = (xs: any[]) => {
|
const collect = (xs: any[]) => {
|
||||||
for (const x of xs) {
|
for (const x of xs) {
|
||||||
if (x.type === 'input') {
|
if (x.type === 'textInput') {
|
||||||
pageVars.push({
|
pageVars.push({
|
||||||
name: x.name,
|
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
|
value: x.default
|
||||||
});
|
});
|
||||||
} else if (x.type === 'switch') {
|
} else if (x.type === 'switch') {
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
|
||||||
import { faBolt } from '@fortawesome/free-solid-svg-icons';
|
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({
|
export default Vue.extend({
|
||||||
i18n: i18n('pages'),
|
i18n: i18n('pages'),
|
|
@ -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: {
|
||||||
|
groupedItems: 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>
|
|
@ -15,11 +15,11 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
|
||||||
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
|
import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
|
||||||
import XContainer from './page-editor.container.vue';
|
import i18n from '../../../../../i18n';
|
||||||
import XFileThumbnail from '../drive-file-thumbnail.vue';
|
import XContainer from '../page-editor.container.vue';
|
||||||
|
import XFileThumbnail from '../../drive-file-thumbnail.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('pages'),
|
i18n: i18n('pages'),
|
|
@ -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>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<x-container @remove="() => $emit('remove')">
|
||||||
|
<template #header><fa :icon="faPaperPlane"/> {{ $t('blocks.post') }}</template>
|
||||||
|
|
||||||
|
<section style="padding: 0 16px 16px 16px;">
|
||||||
|
<ui-textarea v-model="value.text">{{ $t('blocks._post.text') }}</ui-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>
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<section class="ilrvjyvi">
|
<section class="ilrvjyvi">
|
||||||
<div class="children">
|
<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>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import * as uuid from 'uuid';
|
||||||
import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
|
import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
|
||||||
import XContainer from './page-editor.container.vue';
|
import i18n from '../../../../../i18n';
|
||||||
import * as uuid from 'uuid';
|
import XContainer from '../page-editor.container.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('pages'),
|
i18n: i18n('pages'),
|
||||||
|
@ -33,10 +33,15 @@ export default Vue.extend({
|
||||||
XContainer
|
XContainer
|
||||||
},
|
},
|
||||||
|
|
||||||
|
inject: ['getPageBlockList'],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
aiScript: {
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
@ -46,7 +51,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.$options.components.XBlock = require('./page-editor.block.vue').default
|
this.$options.components.XBlock = require('../page-editor.block.vue').default
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
|
@ -79,19 +84,7 @@ export default Vue.extend({
|
||||||
type: null,
|
type: null,
|
||||||
title: this.$t('choose-block'),
|
title: this.$t('choose-block'),
|
||||||
select: {
|
select: {
|
||||||
items: [{
|
groupedItems: this.getPageBlockList()
|
||||||
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')
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
showCancelButton: true
|
showCancelButton: true
|
||||||
});
|
});
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
|
||||||
import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
|
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({
|
export default Vue.extend({
|
||||||
i18n: i18n('pages'),
|
i18n: i18n('pages'),
|
|
@ -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>
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
|
||||||
import { faAlignLeft } from '@fortawesome/free-solid-svg-icons';
|
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({
|
export default Vue.extend({
|
||||||
i18n: i18n('pages'),
|
i18n: i18n('pages'),
|
||||||
|
@ -54,4 +54,5 @@ export default Vue.extend({
|
||||||
padding 16px
|
padding 16px
|
||||||
background transparent
|
background transparent
|
||||||
color var(--text)
|
color var(--text)
|
||||||
|
font-size 14px
|
||||||
</style>
|
</style>
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,25 +1,33 @@
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import XSection from './page-editor.section.vue';
|
import XSection from './els/page-editor.el.section.vue';
|
||||||
import XText from './page-editor.text.vue';
|
import XText from './els/page-editor.el.text.vue';
|
||||||
import XImage from './page-editor.image.vue';
|
import XTextarea from './els/page-editor.el.textarea.vue';
|
||||||
import XButton from './page-editor.button.vue';
|
import XImage from './els/page-editor.el.image.vue';
|
||||||
import XInput from './page-editor.input.vue';
|
import XButton from './els/page-editor.el.button.vue';
|
||||||
import XSwitch from './page-editor.switch.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({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XSection, XText, XImage, XButton, XInput, XSwitch
|
XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
required: true
|
required: true
|
||||||
}
|
},
|
||||||
|
aiScript: {
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -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 i18n from '../../../../i18n';
|
|
||||||
import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
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>
|
|
|
@ -2,16 +2,16 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="gwbmwxkm" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners }">
|
<div class="gwbmwxkm" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners }">
|
||||||
<header>
|
<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">
|
<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="() => showOptions = !showOptions"><fa :icon="faCog"/></button>
|
||||||
<button @click="save()"><fa :icon="faSave"/></button>
|
<button @click="save()" v-if="!readonly"><fa :icon="faSave"/></button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section>
|
<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">
|
<ui-input v-model="title">
|
||||||
<span>{{ $t('title') }}</span>
|
<span>{{ $t('title') }}</span>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
</ui-input>
|
</ui-input>
|
||||||
|
|
||||||
<ui-input v-model="name">
|
<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>
|
<span>{{ $t('url') }}</span>
|
||||||
</ui-input>
|
</ui-input>
|
||||||
|
|
||||||
|
@ -45,10 +45,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="content" v-for="child in content">
|
<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>
|
</div>
|
||||||
|
|
||||||
<ui-button @click="add()"><fa :icon="faPlus"/></ui-button>
|
<ui-button @click="add()" v-if="!readonly"><fa :icon="faPlus"/></ui-button>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</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>
|
<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: {
|
page: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false
|
||||||
}
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
author: this.$store.state.i,
|
||||||
pageId: null,
|
pageId: null,
|
||||||
currentName: null,
|
currentName: null,
|
||||||
title: '',
|
title: '',
|
||||||
|
@ -157,6 +163,7 @@ export default Vue.extend({
|
||||||
this.$root.api('pages/show', {
|
this.$root.api('pages/show', {
|
||||||
pageId: this.page,
|
pageId: this.page,
|
||||||
}).then(page => {
|
}).then(page => {
|
||||||
|
this.author = page.user;
|
||||||
this.pageId = page.id;
|
this.pageId = page.id;
|
||||||
this.title = page.title;
|
this.title = page.title;
|
||||||
this.name = page.name;
|
this.name = page.name;
|
||||||
|
@ -180,7 +187,9 @@ export default Vue.extend({
|
||||||
|
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
getScriptBlockList: this.getScriptBlockList
|
readonly: this.readonly,
|
||||||
|
getScriptBlockList: this.getScriptBlockList,
|
||||||
|
getPageBlockList: this.getPageBlockList
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -250,19 +259,7 @@ export default Vue.extend({
|
||||||
type: null,
|
type: null,
|
||||||
title: this.$t('choose-block'),
|
title: this.$t('choose-block'),
|
||||||
select: {
|
select: {
|
||||||
items: [{
|
groupedItems: this.getPageBlockList()
|
||||||
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')
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
showCancelButton: true
|
showCancelButton: true
|
||||||
});
|
});
|
||||||
|
@ -324,6 +321,33 @@ export default Vue.extend({
|
||||||
this.variables = newValue;
|
this.variables = newValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getPageBlockList() {
|
||||||
|
return [{
|
||||||
|
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') },
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
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') }
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: this.$t('special-blocks'),
|
||||||
|
items: [
|
||||||
|
{ value: 'if', text: this.$t('blocks.if') },
|
||||||
|
{ value: 'post', text: this.$t('blocks.post') }
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
|
||||||
getScriptBlockList(type: string = null) {
|
getScriptBlockList(type: string = null) {
|
||||||
const list = [];
|
const list = [];
|
||||||
|
|
||||||
|
@ -436,6 +460,7 @@ export default Vue.extend({
|
||||||
> .view
|
> .view
|
||||||
display inline-block
|
display inline-block
|
||||||
margin 16px 0 0 0
|
margin 16px 0 0 0
|
||||||
|
font-size 14px
|
||||||
|
|
||||||
> .content
|
> .content
|
||||||
margin-bottom 16px
|
margin-bottom 16px
|
||||||
|
|
|
@ -8,12 +8,17 @@ import XText from './page.text.vue';
|
||||||
import XSection from './page.section.vue';
|
import XSection from './page.section.vue';
|
||||||
import XImage from './page.image.vue';
|
import XImage from './page.image.vue';
|
||||||
import XButton from './page.button.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 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({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XText, XSection, XImage, XButton, XInput, XSwitch
|
XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<ui-button class="kudkigyw" @click="click()">{{ value.text }}</ui-button>
|
<ui-button class="kudkigyw" @click="click()">{{ script.interpolate(value.text) }}</ui-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
30
src/client/app/common/views/pages/page/page.if.vue
Normal file
30
src/client/app/common/views/pages/page/page.if.vue
Normal file
|
@ -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>
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<ui-input class="kudkigyw" v-model="v" :type="value.inputType">{{ value.text }}</ui-input>
|
<ui-input class="kudkigyw" v-model="v" type="number">{{ script.interpolate(value.text) }}</ui-input>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -25,9 +25,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
let v = this.v;
|
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
||||||
if (this.value.inputType === 'number') v = parseInt(v, 10);
|
|
||||||
this.script.aiScript.updatePageVar(this.value.name, v);
|
|
||||||
this.script.reEval();
|
this.script.reEval();
|
||||||
}
|
}
|
||||||
}
|
}
|
68
src/client/app/common/views/pages/page/page.post.vue
Normal file
68
src/client/app/common/views/pages/page/page.post.vue
Normal file
|
@ -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>
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="hkcxmtwj">
|
<div class="hkcxmtwj">
|
||||||
<ui-switch v-model="v">{{ value.text }}</ui-switch>
|
<ui-switch v-model="v">{{ script.interpolate(value.text) }}</ui-switch>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -36,4 +36,8 @@ export default Vue.extend({
|
||||||
.hkcxmtwj
|
.hkcxmtwj
|
||||||
display inline-block
|
display inline-block
|
||||||
margin 16px auto
|
margin 16px auto
|
||||||
|
|
||||||
|
& + .hkcxmtwj
|
||||||
|
margin-left 16px
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
41
src/client/app/common/views/pages/page/page.text-input.vue
Normal file
41
src/client/app/common/views/pages/page/page.text-input.vue
Normal file
|
@ -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>
|
|
@ -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>
|
33
src/client/app/common/views/pages/page/page.textarea.vue
Normal file
33
src/client/app/common/views/pages/page/page.textarea.vue
Normal file
|
@ -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>
|
|
@ -23,6 +23,7 @@ import { faSave, faStickyNote } from '@fortawesome/free-regular-svg-icons';
|
||||||
import XBlock from './page.block.vue';
|
import XBlock from './page.block.vue';
|
||||||
import { AiScript } from '../../../scripts/aiscript';
|
import { AiScript } from '../../../scripts/aiscript';
|
||||||
import { collectPageVars } from '../../../scripts/collect-page-vars';
|
import { collectPageVars } from '../../../scripts/collect-page-vars';
|
||||||
|
import { url } from '../../../../config';
|
||||||
|
|
||||||
class Script {
|
class Script {
|
||||||
public aiScript: AiScript;
|
public aiScript: AiScript;
|
||||||
|
@ -38,6 +39,7 @@ class Script {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interpolate(str: string) {
|
public interpolate(str: string) {
|
||||||
|
if (str == null) return null;
|
||||||
return str.replace(/\{(.+?)\}/g, match => {
|
return str.replace(/\{(.+?)\}/g, match => {
|
||||||
const v = this.vars.find(x => x.name === match.slice(1, -1).trim()).value;
|
const v = this.vars.find(x => x.name === match.slice(1, -1).trim()).value;
|
||||||
return v == null ? 'NULL' : v.toString();
|
return v == null ? 'NULL' : v.toString();
|
||||||
|
@ -81,7 +83,9 @@ export default Vue.extend({
|
||||||
this.script = new Script(new AiScript(this.page.variables, pageVars, {
|
this.script = new Script(new AiScript(this.page.variables, pageVars, {
|
||||||
randomSeed: Math.random(),
|
randomSeed: Math.random(),
|
||||||
user: page.user,
|
user: page.user,
|
||||||
visitor: this.$store.state.i
|
visitor: this.$store.state.i,
|
||||||
|
page: page,
|
||||||
|
url: url
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,4 +33,7 @@ main
|
||||||
padding 16px
|
padding 16px
|
||||||
max-width 1000px
|
max-width 1000px
|
||||||
|
|
||||||
|
@media (min-width 600px)
|
||||||
|
padding 32px
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -71,7 +71,7 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* ドライブ使用量
|
* ドライブ使用量
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column('bigint', {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public driveUsage: number;
|
public driveUsage: number;
|
||||||
|
|
|
@ -27,6 +27,33 @@ export class PageRepository extends Repository<Page> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
collectFile(src.content);
|
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({
|
return await awaitAll({
|
||||||
id: src.id,
|
id: src.id,
|
||||||
createdAt: src.createdAt.toISOString(),
|
createdAt: src.createdAt.toISOString(),
|
||||||
|
|
|
@ -11,7 +11,7 @@ html
|
||||||
meta(name='application-name' content='Misskey')
|
meta(name='application-name' content='Misskey')
|
||||||
meta(name='referrer' content='origin')
|
meta(name='referrer' content='origin')
|
||||||
meta(name='theme-color' content='#105779')
|
meta(name='theme-color' content='#105779')
|
||||||
meta(property='og:site_name' content= title || 'Misskey')
|
meta(property='og:site_name' content= instanceName || 'Misskey')
|
||||||
link(rel='icon' href= icon || '/favicon.ico')
|
link(rel='icon' href= icon || '/favicon.ico')
|
||||||
link(rel='manifest' href='/manifest.json')
|
link(rel='manifest' href='/manifest.json')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue