summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-02-28 00:11:28 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-02-28 00:11:28 +0900
commitdbc421cb571f69a4c71691c00b094925006b95fe (patch)
tree02a7e77b1545d120494a3b7f0487b45e1078f723 /src
parentv3917 (diff)
downloadsharkey-dbc421cb571f69a4c71691c00b094925006b95fe.tar.gz
sharkey-dbc421cb571f69a4c71691c00b094925006b95fe.tar.bz2
sharkey-dbc421cb571f69a4c71691c00b094925006b95fe.zip
:v:
Diffstat (limited to 'src')
-rw-r--r--src/web/app/auth/script.ts25
-rw-r--r--src/web/app/auth/views/index.vue8
-rw-r--r--src/web/app/dev/script.ts18
-rw-r--r--src/web/app/dev/tags/index.ts5
-rw-r--r--src/web/app/dev/tags/new-app-form.tag252
-rw-r--r--src/web/app/dev/tags/pages/app.tag32
-rw-r--r--src/web/app/dev/tags/pages/apps.tag33
-rw-r--r--src/web/app/dev/tags/pages/index.tag6
-rw-r--r--src/web/app/dev/tags/pages/new-app.tag42
-rw-r--r--src/web/app/dev/views/app.vue43
-rw-r--r--src/web/app/dev/views/apps.vue24
-rw-r--r--src/web/app/dev/views/index.vue10
-rw-r--r--src/web/app/dev/views/new-app.vue145
-rw-r--r--src/web/app/init.ts2
14 files changed, 270 insertions, 375 deletions
diff --git a/src/web/app/auth/script.ts b/src/web/app/auth/script.ts
new file mode 100644
index 0000000000..31c758ebc2
--- /dev/null
+++ b/src/web/app/auth/script.ts
@@ -0,0 +1,25 @@
+/**
+ * Authorize Form
+ */
+
+// Style
+import './style.styl';
+
+import init from '../init';
+
+import Index from './views/index.vue';
+
+/**
+ * init
+ */
+init(async (launch) => {
+ document.title = 'Misskey | アプリの連携';
+
+ // Launch the app
+ const [app] = launch();
+
+ // Routing
+ app.$router.addRoutes([
+ { path: '/:token', component: Index },
+ ]);
+});
diff --git a/src/web/app/auth/views/index.vue b/src/web/app/auth/views/index.vue
index 1e372c0bde..17e5cc6108 100644
--- a/src/web/app/auth/views/index.vue
+++ b/src/web/app/auth/views/index.vue
@@ -42,10 +42,14 @@ export default Vue.extend({
return {
state: null,
session: null,
- fetching: true,
- token: window.location.href.split('/').pop()
+ fetching: true
};
},
+ computed: {
+ token(): string {
+ return this.$route.params.token;
+ }
+ },
mounted() {
if (!this.$root.$data.os.isSignedIn) return;
diff --git a/src/web/app/dev/script.ts b/src/web/app/dev/script.ts
index bb43411195..757bfca490 100644
--- a/src/web/app/dev/script.ts
+++ b/src/web/app/dev/script.ts
@@ -5,11 +5,25 @@
// Style
import './style.styl';
-require('./tags');
import init from '../init';
+import Index from './views/index.vue';
+import Apps from './views/apps.vue';
+import AppNew from './views/new-app.vue';
+import App from './views/app.vue';
+
/**
* init
*/
-init(() => {
+init(launch => {
+ // Launch the app
+ const [app] = launch();
+
+ // Routing
+ app.$router.addRoutes([
+ { path: '/', component: Index },
+ { path: '/app', component: Apps },
+ { path: '/app/new', component: AppNew },
+ { path: '/app/:id', component: App },
+ ]);
});
diff --git a/src/web/app/dev/tags/index.ts b/src/web/app/dev/tags/index.ts
deleted file mode 100644
index 1e0c73697e..0000000000
--- a/src/web/app/dev/tags/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-require('./pages/index.tag');
-require('./pages/apps.tag');
-require('./pages/app.tag');
-require('./pages/new-app.tag');
-require('./new-app-form.tag');
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
deleted file mode 100644
index cf3c440079..0000000000
--- a/src/web/app/dev/tags/new-app-form.tag
+++ /dev/null
@@ -1,252 +0,0 @@
-<mk-new-app-form>
- <form onsubmit={ onsubmit } autocomplete="off">
- <section class="name">
- <label>
- <p class="caption">アプリケーション名</p>
- <input ref="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required="required"/>
- </label>
- </section>
- <section class="nid">
- <label>
- <p class="caption">Named ID</p>
- <input ref="nid" type="text" pattern="^[a-zA-Z0-9-]{3,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required="required" onkeyup={ onChangeNid }/>
- <p class="info" v-if="nidState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%確認しています...</p>
- <p class="info" v-if="nidState == 'ok'" style="color:#3CB7B5">%fa:fw check%利用できます</p>
- <p class="info" v-if="nidState == 'unavailable'" style="color:#FF1161">%fa:fw exclamation-triangle%既に利用されています</p>
- <p class="info" v-if="nidState == 'error'" style="color:#FF1161">%fa:fw exclamation-triangle%通信エラー</p>
- <p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、-(ハイフン)が使えます</p>
- <p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%3文字以上でお願いします!</p>
- <p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p>
- </label>
- </section>
- <section class="description">
- <label>
- <p class="caption">アプリの概要</p>
- <textarea ref="description" placeholder="ex) Misskey iOSクライアント。" autocomplete="off" required="required"></textarea>
- </label>
- </section>
- <section class="callback">
- <label>
- <p class="caption">コールバックURL (オプション)</p>
- <input ref="cb" type="url" placeholder="ex) https://your.app.example.com/callback.php" autocomplete="off"/>
- </label>
- </section>
- <section class="permission">
- <p class="caption">権限</p>
- <div ref="permission">
- <label>
- <input type="checkbox" value="account-read"/>
- <p>アカウントの情報を見る。</p>
- </label>
- <label>
- <input type="checkbox" value="account-write"/>
- <p>アカウントの情報を操作する。</p>
- </label>
- <label>
- <input type="checkbox" value="post-write"/>
- <p>投稿する。</p>
- </label>
- <label>
- <input type="checkbox" value="reaction-write"/>
- <p>リアクションしたりリアクションをキャンセルする。</p>
- </label>
- <label>
- <input type="checkbox" value="following-write"/>
- <p>フォローしたりフォロー解除する。</p>
- </label>
- <label>
- <input type="checkbox" value="drive-read"/>
- <p>ドライブを見る。</p>
- </label>
- <label>
- <input type="checkbox" value="drive-write"/>
- <p>ドライブを操作する。</p>
- </label>
- <label>
- <input type="checkbox" value="notification-read"/>
- <p>通知を見る。</p>
- </label>
- <label>
- <input type="checkbox" value="notification-write"/>
- <p>通知を操作する。</p>
- </label>
- </div>
- <p>%fa:exclamation-triangle%アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。</p>
- </section>
- <button @click="onsubmit">アプリ作成</button>
- </form>
- <style lang="stylus" scoped>
- :scope
- display block
- overflow hidden
-
- > form
-
- section
- display block
- margin 16px 0
-
- .caption
- margin 0 0 4px 0
- color #616161
- font-size 0.95em
-
- > [data-fa]
- margin-right 0.25em
- color #96adac
-
- .info
- display block
- margin 4px 0
- font-size 0.8em
-
- > [data-fa]
- margin-right 0.3em
-
- section.permission
- div
- padding 8px 0
- max-height 160px
- overflow auto
- background #fff
- border solid 1px #cecece
- border-radius 4px
-
- label
- display block
- padding 0 12px
- line-height 32px
- cursor pointer
-
- &:hover
- > p
- color #999
-
- [type='checkbox']:checked + p
- color #000
-
- [type='checkbox']
- margin-right 4px
-
- [type='checkbox']:checked + p
- color #111
-
- > p
- display inline
- color #aaa
- user-select none
-
- > p:last-child
- margin 6px
- font-size 0.8em
- color #999
-
- > [data-fa]
- margin-right 4px
-
- [type=text]
- [type=url]
- textarea
- user-select text
- display inline-block
- cursor auto
- padding 8px 12px
- margin 0
- width 100%
- font-size 1em
- color #333
- background #fff
- outline none
- border solid 1px #cecece
- border-radius 4px
-
- &:hover
- border-color #bbb
-
- &:focus
- border-color $theme-color
-
- &:disabled
- opacity 0.5
-
- > button
- margin 20px 0 32px 0
- width 100%
- font-size 1em
- color #111
- border-radius 3px
-
- </style>
- <script lang="typescript">
- this.mixin('api');
-
- this.nidState = null;
-
- this.onChangeNid = () => {
- const nid = this.$refs.nid.value;
-
- if (nid == '') {
- this.update({
- nidState: null
- });
- return;
- }
-
- const err =
- !nid.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' :
- nid.length < 3 ? 'min-range' :
- nid.length > 30 ? 'max-range' :
- null;
-
- if (err) {
- this.update({
- nidState: err
- });
- return;
- }
-
- this.update({
- nidState: 'wait'
- });
-
- this.$root.$data.os.api('app/name_id/available', {
- name_id: nid
- }).then(result => {
- this.update({
- nidState: result.available ? 'ok' : 'unavailable'
- });
- }).catch(err => {
- this.update({
- nidState: 'error'
- });
- });
- };
-
- this.onsubmit = () => {
- const name = this.$refs.name.value;
- const nid = this.$refs.nid.value;
- const description = this.$refs.description.value;
- const cb = this.$refs.cb.value;
- const permission = [];
-
- this.$refs.permission.querySelectorAll('input').forEach(el => {
- if (el.checked) permission.push(el.value);
- });
-
- const locker = document.body.appendChild(document.createElement('mk-locker'));
-
- this.$root.$data.os.api('app/create', {
- name: name,
- name_id: nid,
- description: description,
- callback_url: cb,
- permission: permission
- }).then(() => {
- location.href = '/apps';
- }).catch(() => {
- alert('アプリの作成に失敗しました。再度お試しください。');
- locker.parentNode.removeChild(locker);
- });
- };
- </script>
-</mk-new-app-form>
diff --git a/src/web/app/dev/tags/pages/app.tag b/src/web/app/dev/tags/pages/app.tag
deleted file mode 100644
index 982549ed2b..0000000000
--- a/src/web/app/dev/tags/pages/app.tag
+++ /dev/null
@@ -1,32 +0,0 @@
-<mk-app-page>
- <p v-if="fetching">読み込み中</p>
- <main v-if="!fetching">
- <header>
- <h1>{ app.name }</h1>
- </header>
- <div class="body">
- <p>App Secret</p>
- <input value={ app.secret } readonly="readonly"/>
- </div>
- </main>
- <style lang="stylus" scoped>
- :scope
- display block
- </style>
- <script lang="typescript">
- this.mixin('api');
-
- this.fetching = true;
-
- this.on('mount', () => {
- this.$root.$data.os.api('app/show', {
- app_id: this.opts.app
- }).then(app => {
- this.update({
- fetching: false,
- app: app
- });
- });
- });
- </script>
-</mk-app-page>
diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag
deleted file mode 100644
index 6ae6031e64..0000000000
--- a/src/web/app/dev/tags/pages/apps.tag
+++ /dev/null
@@ -1,33 +0,0 @@
-<mk-apps-page>
- <h1>アプリを管理</h1><a href="/app/new">アプリ作成</a>
- <div class="apps">
- <p v-if="fetching">読み込み中</p>
- <template v-if="!fetching">
- <p v-if="apps.length == 0">アプリなし</p>
- <ul v-if="apps.length > 0">
- <li each={ app in apps }><a href={ '/app/' + app.id }>
- <p class="name">{ app.name }</p></a></li>
- </ul>
- </template>
- </div>
- <style lang="stylus" scoped>
- :scope
- display block
- </style>
- <script lang="typescript">
- this.mixin('api');
-
- this.fetching = true;
-
- this.on('mount', () => {
- this.$root.$data.os.api('my/apps').then(apps => {
- this.fetching = false
- this.apps = apps
- this.update({
- fetching: false,
- apps: apps
- });
- });
- });
- </script>
-</mk-apps-page>
diff --git a/src/web/app/dev/tags/pages/index.tag b/src/web/app/dev/tags/pages/index.tag
deleted file mode 100644
index ca270b3774..0000000000
--- a/src/web/app/dev/tags/pages/index.tag
+++ /dev/null
@@ -1,6 +0,0 @@
-<mk-index><a href="/apps">アプリ</a>
- <style lang="stylus" scoped>
- :scope
- display block
- </style>
-</mk-index>
diff --git a/src/web/app/dev/tags/pages/new-app.tag b/src/web/app/dev/tags/pages/new-app.tag
deleted file mode 100644
index 26185f278b..0000000000
--- a/src/web/app/dev/tags/pages/new-app.tag
+++ /dev/null
@@ -1,42 +0,0 @@
-<mk-new-app-page>
- <main>
- <header>
- <h1>新しいアプリを作成</h1>
- <p>MisskeyのAPIを利用したアプリケーションを作成できます。</p>
- </header>
- <mk-new-app-form/>
- </main>
- <style lang="stylus" scoped>
- :scope
- display block
- padding 64px 0
-
- > main
- width 100%
- max-width 700px
- margin 0 auto
-
- > header
- margin 0 0 16px 0
- padding 0 0 16px 0
- border-bottom solid 1px #282827
-
- > h1
- margin 0 0 12px 0
- padding 0
- line-height 32px
- font-size 32px
- font-weight normal
- color #000
-
- > p
- margin 0
- line-height 16px
- color #9a9894
-
-
-
-
-
- </style>
-</mk-new-app-page>
diff --git a/src/web/app/dev/views/app.vue b/src/web/app/dev/views/app.vue
new file mode 100644
index 0000000000..9eddabbec2
--- /dev/null
+++ b/src/web/app/dev/views/app.vue
@@ -0,0 +1,43 @@
+<template>
+<div>
+ <p v-if="fetching">読み込み中</p>
+ <main v-if="!fetching">
+ <header>
+ <h1>{{ app.name }}</h1>
+ </header>
+ <div class="body">
+ <p>App Secret</p>
+ <input :value="app.secret" readonly/>
+ </div>
+ </main>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ app: null
+ };
+ },
+ watch: {
+ $route: 'fetch'
+ },
+ mounted() {
+ this.fetch();
+ },
+ methods: {
+ fetch() {
+ this.fetching = true;
+ (this as any).api('app/show', {
+ app_id: this.$route.params.id
+ }).then(app => {
+ this.app = app;
+ this.fetching = false;
+ });
+ }
+ }
+});
+</script>
diff --git a/src/web/app/dev/views/apps.vue b/src/web/app/dev/views/apps.vue
new file mode 100644
index 0000000000..e8adbea2da
--- /dev/null
+++ b/src/web/app/dev/views/apps.vue
@@ -0,0 +1,24 @@
+<template>
+<div>
+ <h1>アプリを管理</h1>
+ <router-link to="/app/new">アプリ作成</router-link>
+ <div class="apps">
+ <p v-if="fetching">読み込み中</p>
+ <template v-if="!fetching">
+ <p v-if="apps.length == 0">アプリなし</p>
+ <ul v-else>
+ <li v-for="app in apps" :key="app.id">
+ <router-link :to="`/app/${app.id}`">
+ <p class="name">{{ app.name }}</p>
+ </router-link>
+ </li>
+ </ul>
+ </template>
+ </div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend();
+</script>
diff --git a/src/web/app/dev/views/index.vue b/src/web/app/dev/views/index.vue
new file mode 100644
index 0000000000..a8429a56dd
--- /dev/null
+++ b/src/web/app/dev/views/index.vue
@@ -0,0 +1,10 @@
+<template>
+<div>
+ <router-link to="/app">アプリ</router-link>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend();
+</script>
diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue
new file mode 100644
index 0000000000..f2e5659a4e
--- /dev/null
+++ b/src/web/app/dev/views/new-app.vue
@@ -0,0 +1,145 @@
+<template>
+<div>
+ <form @submit="onSubmit" autocomplete="off">
+ <section class="name">
+ <label>
+ <p class="caption">アプリケーション名</p>
+ <input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/>
+ </label>
+ </section>
+ <section class="nid">
+ <label>
+ <p class="caption">Named ID</p>
+ <input v-model="nid" type="text" pattern="^[a-zA-Z0-9-]{3,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/>
+ <p class="info" v-if="nidState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%確認しています...</p>
+ <p class="info" v-if="nidState == 'ok'" style="color:#3CB7B5">%fa:fw check%利用できます</p>
+ <p class="info" v-if="nidState == 'unavailable'" style="color:#FF1161">%fa:fw exclamation-triangle%既に利用されています</p>
+ <p class="info" v-if="nidState == 'error'" style="color:#FF1161">%fa:fw exclamation-triangle%通信エラー</p>
+ <p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、-(ハイフン)が使えます</p>
+ <p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%3文字以上でお願いします!</p>
+ <p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p>
+ </label>
+ </section>
+ <section class="description">
+ <label>
+ <p class="caption">アプリの概要</p>
+ <textarea v-model="description" placeholder="ex) Misskey iOSクライアント。" autocomplete="off" required></textarea>
+ </label>
+ </section>
+ <section class="callback">
+ <label>
+ <p class="caption">コールバックURL (オプション)</p>
+ <input v-model="cb" type="url" placeholder="ex) https://your.app.example.com/callback.php" autocomplete="off"/>
+ </label>
+ </section>
+ <section class="permission">
+ <p class="caption">権限</p>
+ <div ref="permission">
+ <label>
+ <input type="checkbox" value="account-read"/>
+ <p>アカウントの情報を見る。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="account-write"/>
+ <p>アカウントの情報を操作する。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="post-write"/>
+ <p>投稿する。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="reaction-write"/>
+ <p>リアクションしたりリアクションをキャンセルする。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="following-write"/>
+ <p>フォローしたりフォロー解除する。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="drive-read"/>
+ <p>ドライブを見る。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="drive-write"/>
+ <p>ドライブを操作する。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="notification-read"/>
+ <p>通知を見る。</p>
+ </label>
+ <label>
+ <input type="checkbox" value="notification-write"/>
+ <p>通知を操作する。</p>
+ </label>
+ </div>
+ <p>%fa:exclamation-triangle%アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。</p>
+ </section>
+ <button type="submit">アプリ作成</button>
+ </form>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ data() {
+ return {
+ name: '',
+ nid: '',
+ description: '',
+ cb: '',
+ nidState: null
+ };
+ },
+ watch: {
+ nid() {
+ if (this.nid == null || this.nid == '') {
+ this.nidState = null;
+ return;
+ }
+
+ const err =
+ !this.nid.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' :
+ this.nid.length < 3 ? 'min-range' :
+ this.nid.length > 30 ? 'max-range' :
+ null;
+
+ if (err) {
+ this.nidState = err;
+ return;
+ }
+
+ this.nidState = 'wait';
+
+ (this as any).api('app/name_id/available', {
+ name_id: this.nid
+ }).then(result => {
+ this.nidState = result.available ? 'ok' : 'unavailable';
+ }).catch(err => {
+ this.nidState = 'error';
+ });
+ }
+ },
+ methods: {
+ onSubmit() {
+ const permission = [];
+
+ (this.$refs.permission as any).querySelectorAll('input').forEach(el => {
+ if (el.checked) permission.push(el.value);
+ });
+
+ (this as any).api('app/create', {
+ name: this.name,
+ name_id: this.nid,
+ description: this.description,
+ callback_url: this.cb,
+ permission: permission
+ }).then(() => {
+ location.href = '/apps';
+ }).catch(() => {
+ alert('アプリの作成に失敗しました。再度お試しください。');
+ });
+ }
+ }
+});
+</script>
diff --git a/src/web/app/init.ts b/src/web/app/init.ts
index 5c0b4c2d39..2e90d62d79 100644
--- a/src/web/app/init.ts
+++ b/src/web/app/init.ts
@@ -77,7 +77,7 @@ if (localStorage.getItem('should-refresh') == 'true') {
}
// MiOSを初期化してコールバックする
-export default (callback: (launch: (api: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => {
+export default (callback: (launch: (api?: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => {
const os = new MiOS(sw);
os.init(() => {