Deckにウィジェットを置けるように
This commit is contained in:
parent
ed8fa59639
commit
b0f989dbac
20 changed files with 417 additions and 179 deletions
|
@ -9,9 +9,9 @@ export default function<T extends object>(data: {
|
||||||
widget: {
|
widget: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
isMobile: {
|
platform: {
|
||||||
type: Boolean,
|
type: String,
|
||||||
default: false
|
required: true
|
||||||
},
|
},
|
||||||
isCustomizeMode: {
|
isCustomizeMode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -66,17 +66,10 @@ export default function<T extends object>(data: {
|
||||||
|
|
||||||
this.bakeProps();
|
this.bakeProps();
|
||||||
|
|
||||||
if (this.isMobile) {
|
(this as any).api('i/update_widget', {
|
||||||
(this as any).api('i/update_mobile_home', {
|
id: this.id,
|
||||||
id: this.id,
|
data: this.props
|
||||||
data: this.props
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
(this as any).api('i/update_home', {
|
|
||||||
id: this.id,
|
|
||||||
data: this.props
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -58,25 +58,18 @@ export class HomeStream extends Stream {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('home_updated', x => {
|
this.on('home_updated', x => {
|
||||||
if (x.home) {
|
os.store.commit('settings/setHome', x);
|
||||||
os.store.commit('settings/setHome', x.home);
|
|
||||||
} else {
|
|
||||||
os.store.commit('settings/setHomeWidget', {
|
|
||||||
id: x.id,
|
|
||||||
data: x.data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('mobile_home_updated', x => {
|
this.on('mobile_home_updated', x => {
|
||||||
if (x.home) {
|
os.store.commit('settings/setMobileHome', x);
|
||||||
os.store.commit('settings/setMobileHome', x.home);
|
});
|
||||||
} else {
|
|
||||||
os.store.commit('settings/setMobileHomeWidget', {
|
this.on('widgetUpdated', x => {
|
||||||
id: x.id,
|
os.store.commit('settings/setWidget', {
|
||||||
data: x.data
|
id: x.id,
|
||||||
});
|
data: x.data
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// トークンが再生成されたとき
|
// トークンが再生成されたとき
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
<div class="mk-menu">
|
<div class="mk-menu">
|
||||||
<div class="backdrop" ref="backdrop" @click="close"></div>
|
<div class="backdrop" ref="backdrop" @click="close"></div>
|
||||||
<div class="popover" :class="{ compact }" ref="popover">
|
<div class="popover" :class="{ compact }" ref="popover">
|
||||||
<button v-for="item in items" @click="clicked(item.onClick)" v-html="item.content"></button>
|
<template v-for="item in items">
|
||||||
|
<div v-if="item == null"></div>
|
||||||
|
<button v-else @click="clicked(item.onClick)" v-html="item.content"></button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -150,4 +153,9 @@ $border-color = rgba(27, 31, 35, 0.15)
|
||||||
color $theme-color-foreground
|
color $theme-color-foreground
|
||||||
background darken($theme-color, 10%)
|
background darken($theme-color, 10%)
|
||||||
|
|
||||||
|
> div
|
||||||
|
margin 8px 0
|
||||||
|
height 1px
|
||||||
|
background #eee
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="mkw-broadcast"
|
<div class="mkw-broadcast"
|
||||||
:data-found="broadcasts.length != 0"
|
:data-found="broadcasts.length != 0"
|
||||||
:data-melt="props.design == 1"
|
:data-melt="props.design == 1"
|
||||||
:data-mobile="isMobile"
|
:data-mobile="platform == 'mobile'"
|
||||||
>
|
>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<svg height="32" version="1.1" viewBox="0 0 32 32" width="32">
|
<svg height="32" version="1.1" viewBox="0 0 32 32" width="32">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mkw-calendar" :data-special="special" :data-mobile="isMobile">
|
<div class="mkw-calendar" :data-special="special" :data-mobile="platform == 'mobile'">
|
||||||
<mk-widget-container :naked="props.design == 1" :show-header="false">
|
<mk-widget-container :naked="props.design == 1" :show-header="false">
|
||||||
<div class="mkw-calendar--body">
|
<div class="mkw-calendar--body">
|
||||||
<div class="calendar" :data-is-holiday="isHoliday">
|
<div class="calendar" :data-is-holiday="isHoliday">
|
||||||
|
@ -67,7 +67,7 @@ export default define({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
func() {
|
func() {
|
||||||
if (this.isMobile) return;
|
if (this.platform == 'mobile') return;
|
||||||
if (this.props.design == 2) {
|
if (this.props.design == 2) {
|
||||||
this.props.design = 0;
|
this.props.design = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mkw-donation" :data-mobile="isMobile">
|
<div class="mkw-donation" :data-mobile="platform == 'mobile'">
|
||||||
<article>
|
<article>
|
||||||
<h1>%fa:heart%%i18n:@title%</h1>
|
<h1>%fa:heart%%i18n:@title%</h1>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<template slot="header">%fa:rss-square%RSS</template>
|
<template slot="header">%fa:rss-square%RSS</template>
|
||||||
<button slot="func" title="設定" @click="setting">%fa:cog%</button>
|
<button slot="func" title="設定" @click="setting">%fa:cog%</button>
|
||||||
|
|
||||||
<div class="mkw-rss--body" :data-mobile="isMobile">
|
<div class="mkw-rss--body" :data-mobile="platform == 'mobile'">
|
||||||
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
|
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
|
||||||
<div class="feed" v-else>
|
<div class="feed" v-else>
|
||||||
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
|
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mkw-slideshow" :data-mobile="isMobile">
|
<div class="mkw-slideshow" :data-mobile="platform == 'mobile'">
|
||||||
<div @click="choose">
|
<div @click="choose">
|
||||||
<p v-if="props.folder === undefined">
|
<p v-if="props.folder === undefined">
|
||||||
<template v-if="isCustomizeMode">フォルダを指定するには、カスタマイズモードを終了してください</template>
|
<template v-if="isCustomizeMode">フォルダを指定するには、カスタマイズモードを終了してください</template>
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
:key="place"
|
:key="place"
|
||||||
>
|
>
|
||||||
<div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
<div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
||||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true"/>
|
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
|
||||||
</div>
|
</div>
|
||||||
</x-draggable>
|
</x-draggable>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-for="place in ['left', 'right']" :class="place">
|
<div v-for="place in ['left', 'right']" :class="place">
|
||||||
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
|
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp" platform="desktop"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>
|
<mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default Vue.extend({
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
root(isDark)
|
root(isDark)
|
||||||
background isDark ? #282C37 : #fff
|
background isDark ? #282C37 : #fff
|
||||||
border solid 1px rgba(#000, 0.075)
|
border solid 1px rgba(#000, isDark ? 0.2 : 0.075)
|
||||||
border-radius 6px
|
border-radius 6px
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs">
|
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow }">
|
||||||
<header :class="{ indicate }">
|
<header :class="{ indicate }">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
<button ref="menu" @click="menu">%fa:caret-down%</button>
|
<button ref="menu" @click="showMenu">%fa:caret-down%</button>
|
||||||
</header>
|
</header>
|
||||||
<div ref="body">
|
<div ref="body">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
@ -19,6 +19,20 @@ export default Vue.extend({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
type: Array,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
naked: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
narrow: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -59,26 +73,33 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
menu() {
|
showMenu() {
|
||||||
|
const items = [{
|
||||||
|
content: '%fa:arrow-left% %i18n:@swap-left%',
|
||||||
|
onClick: () => {
|
||||||
|
this.$store.dispatch('settings/swapLeftDeckColumn', this.id);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
content: '%fa:arrow-right% %i18n:@swap-right%',
|
||||||
|
onClick: () => {
|
||||||
|
this.$store.dispatch('settings/swapRightDeckColumn', this.id);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
content: '%fa:trash-alt R% %i18n:@remove%',
|
||||||
|
onClick: () => {
|
||||||
|
this.$store.dispatch('settings/removeDeckColumn', this.id);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (this.menu) {
|
||||||
|
items.unshift(null);
|
||||||
|
this.menu.reverse().forEach(i => items.unshift(i));
|
||||||
|
}
|
||||||
|
|
||||||
this.os.new(Menu, {
|
this.os.new(Menu, {
|
||||||
source: this.$refs.menu,
|
source: this.$refs.menu,
|
||||||
compact: false,
|
compact: false,
|
||||||
items: [{
|
items
|
||||||
content: '%fa:arrow-left% %i18n:@swap-left%',
|
|
||||||
onClick: () => {
|
|
||||||
this.$store.dispatch('settings/swapLeftDeckColumn', this.id);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
content: '%fa:arrow-right% %i18n:@swap-right%',
|
|
||||||
onClick: () => {
|
|
||||||
this.$store.dispatch('settings/swapRightDeckColumn', this.id);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
content: '%fa:trash-alt R% %i18n:@remove%',
|
|
||||||
onClick: () => {
|
|
||||||
this.$store.dispatch('settings/removeDeckColumn', this.id);
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +121,21 @@ root(isDark)
|
||||||
box-shadow 0 2px 16px rgba(#000, 0.1)
|
box-shadow 0 2px 16px rgba(#000, 0.1)
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
|
&.narrow
|
||||||
|
min-width 285px
|
||||||
|
max-width 285px
|
||||||
|
|
||||||
|
&.naked
|
||||||
|
background rgba(#000, isDark ? 0.25 : 0.1)
|
||||||
|
|
||||||
|
> header
|
||||||
|
background transparent
|
||||||
|
box-shadow none
|
||||||
|
|
||||||
|
if !isDark
|
||||||
|
> button
|
||||||
|
color #bbb
|
||||||
|
|
||||||
> header
|
> header
|
||||||
z-index 1
|
z-index 1
|
||||||
line-height $header-height
|
line-height $header-height
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<x-column :id="id">
|
<x-column :id="id">
|
||||||
<span slot="header">%fa:bell R% %i18n:@notifications%</span>
|
<span slot="header">%fa:bell R%%i18n:@notifications%</span>
|
||||||
|
|
||||||
<x-notifications/>
|
<x-notifications/>
|
||||||
</x-column>
|
</x-column>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<mk-ui :class="$style.root">
|
<mk-ui :class="$style.root">
|
||||||
<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode">
|
<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode">
|
||||||
<template v-for="column in columns">
|
<template v-for="column in columns">
|
||||||
|
<x-widgets-column v-if="column.type == 'widgets'" :key="column.id" :column="column"/>
|
||||||
<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :id="column.id"/>
|
<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :id="column.id"/>
|
||||||
<x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/>
|
<x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/>
|
||||||
<x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/>
|
<x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/>
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import XTlColumn from './deck.tl-column.vue';
|
import XTlColumn from './deck.tl-column.vue';
|
||||||
import XNotificationsColumn from './deck.notifications-column.vue';
|
import XNotificationsColumn from './deck.notifications-column.vue';
|
||||||
|
import XWidgetsColumn from './deck.widgets-column.vue';
|
||||||
import Menu from '../../../../common/views/components/menu.vue';
|
import Menu from '../../../../common/views/components/menu.vue';
|
||||||
import MkUserListsWindow from '../../components/user-lists-window.vue';
|
import MkUserListsWindow from '../../components/user-lists-window.vue';
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
|
@ -24,7 +26,8 @@ import * as uuid from 'uuid';
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XTlColumn,
|
XTlColumn,
|
||||||
XNotificationsColumn
|
XNotificationsColumn,
|
||||||
|
XWidgetsColumn
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
columns() {
|
columns() {
|
||||||
|
@ -110,6 +113,15 @@ export default Vue.extend({
|
||||||
type: 'notifications'
|
type: 'notifications'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
content: '%i18n:@widgets%',
|
||||||
|
onClick: () => {
|
||||||
|
this.$store.dispatch('settings/addDeckColumn', {
|
||||||
|
id: uuid(),
|
||||||
|
type: 'widgets',
|
||||||
|
widgets: []
|
||||||
|
});
|
||||||
|
}
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
152
src/client/app/desktop/views/pages/deck/deck.widgets-column.vue
Normal file
152
src/client/app/desktop/views/pages/deck/deck.widgets-column.vue
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<template>
|
||||||
|
<div class="wtdtxvecapixsepjtcupubtsmometobz">
|
||||||
|
<x-column :id="column.id" :menu="menu" :naked="true" :narrow="true">
|
||||||
|
<span slot="header">%fa:calculator%%i18n:@widgets%</span>
|
||||||
|
|
||||||
|
<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
|
||||||
|
<template v-if="edit">
|
||||||
|
<header>
|
||||||
|
<select v-model="widgetAdderSelected">
|
||||||
|
<option value="profile">%i18n:common.widgets.profile%</option>
|
||||||
|
<option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
|
||||||
|
<option value="calendar">%i18n:common.widgets.calendar%</option>
|
||||||
|
<option value="timemachine">%i18n:common.widgets.timemachine%</option>
|
||||||
|
<option value="activity">%i18n:common.widgets.activity%</option>
|
||||||
|
<option value="rss">%i18n:common.widgets.rss%</option>
|
||||||
|
<option value="trends">%i18n:common.widgets.trends%</option>
|
||||||
|
<option value="photo-stream">%i18n:common.widgets.photo-stream%</option>
|
||||||
|
<option value="slideshow">%i18n:common.widgets.slideshow%</option>
|
||||||
|
<option value="version">%i18n:common.widgets.version%</option>
|
||||||
|
<option value="broadcast">%i18n:common.widgets.broadcast%</option>
|
||||||
|
<option value="notifications">%i18n:common.widgets.notifications%</option>
|
||||||
|
<option value="users">%i18n:common.widgets.users%</option>
|
||||||
|
<option value="polls">%i18n:common.widgets.polls%</option>
|
||||||
|
<option value="post-form">%i18n:common.widgets.post-form%</option>
|
||||||
|
<option value="messaging">%i18n:common.widgets.messaging%</option>
|
||||||
|
<option value="memo">%i18n:common.widgets.memo%</option>
|
||||||
|
<option value="server">%i18n:common.widgets.server%</option>
|
||||||
|
<option value="donation">%i18n:common.widgets.donation%</option>
|
||||||
|
<option value="nav">%i18n:common.widgets.nav%</option>
|
||||||
|
<option value="tips">%i18n:common.widgets.tips%</option>
|
||||||
|
</select>
|
||||||
|
<button @click="addWidget">追加</button>
|
||||||
|
</header>
|
||||||
|
<x-draggable
|
||||||
|
:list="column.widgets"
|
||||||
|
:options="{ handle: '.handle', animation: 150 }"
|
||||||
|
@sort="onWidgetSort"
|
||||||
|
>
|
||||||
|
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id">
|
||||||
|
<header>
|
||||||
|
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
|
||||||
|
</header>
|
||||||
|
<div @click="widgetFunc(widget.id)">
|
||||||
|
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-draggable>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<component class="widget" v-for="widget in column.widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="deck"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import * as XDraggable from 'vuedraggable';
|
||||||
|
import * as uuid from 'uuid';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XDraggable
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
column: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
edit: false,
|
||||||
|
menu: null,
|
||||||
|
widgetAdderSelected: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.menu = [{
|
||||||
|
content: '%fa:cog% %i18n:@edit%',
|
||||||
|
onClick: () => {
|
||||||
|
this.edit = !this.edit;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
widgetFunc(id) {
|
||||||
|
const w = this.$refs[id][0];
|
||||||
|
if (w.func) w.func();
|
||||||
|
},
|
||||||
|
|
||||||
|
onWidgetSort() {
|
||||||
|
this.saveWidgets();
|
||||||
|
},
|
||||||
|
|
||||||
|
addWidget() {
|
||||||
|
this.$store.dispatch('settings/addDeckWidget', {
|
||||||
|
id: this.column.id,
|
||||||
|
widget: {
|
||||||
|
name: this.widgetAdderSelected,
|
||||||
|
id: uuid(),
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeWidget(widget) {
|
||||||
|
this.$store.dispatch('settings/removeDeckWidget', {
|
||||||
|
id: this.column.id,
|
||||||
|
widget
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
saveWidgets() {
|
||||||
|
this.$store.dispatch('settings/saveDeck');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
@import '~const.styl'
|
||||||
|
|
||||||
|
root(isDark)
|
||||||
|
.gqpwvtwtprsbmnssnbicggtwqhmylhnq
|
||||||
|
.widget, .customize-container
|
||||||
|
margin 8px
|
||||||
|
|
||||||
|
&:first-of-type
|
||||||
|
margin-top 0
|
||||||
|
|
||||||
|
.customize-container
|
||||||
|
background #fff
|
||||||
|
|
||||||
|
> header
|
||||||
|
color isDark ? #fff : #000
|
||||||
|
|
||||||
|
.wtdtxvecapixsepjtcupubtsmometobz[data-darkmode]
|
||||||
|
root(true)
|
||||||
|
|
||||||
|
.wtdtxvecapixsepjtcupubtsmometobz:not([data-darkmode])
|
||||||
|
root(false)
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
@ -35,13 +35,13 @@
|
||||||
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
|
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
|
||||||
</header>
|
</header>
|
||||||
<div @click="widgetFunc(widget.id)">
|
<div @click="widgetFunc(widget.id)">
|
||||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" :is-mobile="true"/>
|
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="mobile"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-draggable>
|
</x-draggable>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" :is-mobile="true"/>
|
<component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="mobile"/>
|
||||||
</template>
|
</template>
|
||||||
</main>
|
</main>
|
||||||
</mk-ui>
|
</mk-ui>
|
||||||
|
|
|
@ -124,13 +124,6 @@ export default (os: MiOS) => new Vuex.Store({
|
||||||
state.home = data;
|
state.home = data;
|
||||||
},
|
},
|
||||||
|
|
||||||
setHomeWidget(state, x) {
|
|
||||||
const w = state.home.find(w => w.id == x.id);
|
|
||||||
if (w) {
|
|
||||||
w.data = x.data;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addHomeWidget(state, widget) {
|
addHomeWidget(state, widget) {
|
||||||
state.home.unshift(widget);
|
state.home.unshift(widget);
|
||||||
},
|
},
|
||||||
|
@ -139,11 +132,36 @@ export default (os: MiOS) => new Vuex.Store({
|
||||||
state.mobileHome = data;
|
state.mobileHome = data;
|
||||||
},
|
},
|
||||||
|
|
||||||
setMobileHomeWidget(state, x) {
|
setWidget(state, x) {
|
||||||
const w = state.mobileHome.find(w => w.id == x.id);
|
let w;
|
||||||
if (w) {
|
|
||||||
w.data = x.data;
|
//#region Decktop home
|
||||||
|
if (state.home) {
|
||||||
|
w = state.home.find(w => w.id == x.id);
|
||||||
|
if (w) {
|
||||||
|
w.data = x.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Mobile home
|
||||||
|
if (state.mobileHome) {
|
||||||
|
w = state.mobileHome.find(w => w.id == x.id);
|
||||||
|
if (w) {
|
||||||
|
w.data = x.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Deck
|
||||||
|
if (state.deck && state.deck.columns) {
|
||||||
|
state.deck.columns.filter(c => c.type == 'widgets').forEach(c => {
|
||||||
|
c.widgets.forEach(w => {
|
||||||
|
if (w.id == x.id) w.data = x.data;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
},
|
},
|
||||||
|
|
||||||
addMobileHomeWidget(state, widget) {
|
addMobileHomeWidget(state, widget) {
|
||||||
|
@ -190,6 +208,20 @@ export default (os: MiOS) => new Vuex.Store({
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addDeckWidget(state, x) {
|
||||||
|
if (state.deck.columns == null) return;
|
||||||
|
const column = state.deck.columns.find(c => c.id == x.id);
|
||||||
|
if (column == null) return;
|
||||||
|
column.widgets.unshift(x.widget);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeDeckWidget(state, x) {
|
||||||
|
if (state.deck.columns == null) return;
|
||||||
|
const column = state.deck.columns.find(c => c.id == x.id);
|
||||||
|
if (column == null) return;
|
||||||
|
column.widgets = column.widgets.filter(w => w.id != x.widget.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -212,40 +244,41 @@ export default (os: MiOS) => new Vuex.Store({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addDeckColumn(ctx, column) {
|
saveDeck(ctx) {
|
||||||
ctx.commit('addDeckColumn', column);
|
|
||||||
|
|
||||||
os.api('i/update_client_setting', {
|
os.api('i/update_client_setting', {
|
||||||
name: 'deck',
|
name: 'deck',
|
||||||
value: ctx.state.deck
|
value: ctx.state.deck
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addDeckColumn(ctx, column) {
|
||||||
|
ctx.commit('addDeckColumn', column);
|
||||||
|
ctx.dispatch('saveDeck');
|
||||||
|
},
|
||||||
|
|
||||||
removeDeckColumn(ctx, id) {
|
removeDeckColumn(ctx, id) {
|
||||||
ctx.commit('removeDeckColumn', id);
|
ctx.commit('removeDeckColumn', id);
|
||||||
|
ctx.dispatch('saveDeck');
|
||||||
os.api('i/update_client_setting', {
|
|
||||||
name: 'deck',
|
|
||||||
value: ctx.state.deck
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
swapLeftDeckColumn(ctx, id) {
|
swapLeftDeckColumn(ctx, id) {
|
||||||
ctx.commit('swapLeftDeckColumn', id);
|
ctx.commit('swapLeftDeckColumn', id);
|
||||||
|
ctx.dispatch('saveDeck');
|
||||||
os.api('i/update_client_setting', {
|
|
||||||
name: 'deck',
|
|
||||||
value: ctx.state.deck
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
swapRightDeckColumn(ctx, id) {
|
swapRightDeckColumn(ctx, id) {
|
||||||
ctx.commit('swapRightDeckColumn', id);
|
ctx.commit('swapRightDeckColumn', id);
|
||||||
|
ctx.dispatch('saveDeck');
|
||||||
|
},
|
||||||
|
|
||||||
os.api('i/update_client_setting', {
|
addDeckWidget(ctx, x) {
|
||||||
name: 'deck',
|
ctx.commit('addDeckWidget', x);
|
||||||
value: ctx.state.deck
|
ctx.dispatch('saveDeck');
|
||||||
});
|
},
|
||||||
|
|
||||||
|
removeDeckWidget(ctx, x) {
|
||||||
|
ctx.commit('removeDeckWidget', x);
|
||||||
|
ctx.dispatch('saveDeck');
|
||||||
},
|
},
|
||||||
|
|
||||||
addHomeWidget(ctx, widget) {
|
addHomeWidget(ctx, widget) {
|
||||||
|
|
|
@ -189,6 +189,11 @@ const endpoints: Endpoint[] = [
|
||||||
withCredential: true,
|
withCredential: true,
|
||||||
secure: true
|
secure: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'i/update_widget',
|
||||||
|
withCredential: true,
|
||||||
|
secure: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'i/change_password',
|
name: 'i/change_password',
|
||||||
withCredential: true,
|
withCredential: true,
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
import event from '../../../../publishers/stream';
|
import event from '../../../../publishers/stream';
|
||||||
|
@ -13,50 +10,16 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||||
.have('id', $.str)
|
.have('id', $.str)
|
||||||
.have('place', $.str)
|
.have('place', $.str)
|
||||||
.have('data', $.obj))
|
.have('data', $.obj))
|
||||||
.optional()
|
|
||||||
.get(params.home);
|
.get(params.home);
|
||||||
if (homeErr) return rej('invalid home param');
|
if (homeErr) return rej('invalid home param');
|
||||||
|
|
||||||
// Get 'id' parameter
|
await User.update(user._id, {
|
||||||
const [id, idErr] = $.str.optional().get(params.id);
|
$set: {
|
||||||
if (idErr) return rej('invalid id param');
|
'clientSettings.home': home
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get 'data' parameter
|
res();
|
||||||
const [data, dataErr] = $.obj.optional().get(params.data);
|
|
||||||
if (dataErr) return rej('invalid data param');
|
|
||||||
|
|
||||||
if (home) {
|
event(user._id, 'home_updated', home);
|
||||||
await User.update(user._id, {
|
|
||||||
$set: {
|
|
||||||
'clientSettings.home': home
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res();
|
|
||||||
|
|
||||||
event(user._id, 'home_updated', {
|
|
||||||
home
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
|
|
||||||
|
|
||||||
const _home = user.clientSettings.home;
|
|
||||||
const widget = _home.find(w => w.id == id);
|
|
||||||
|
|
||||||
if (widget == null) return rej('widget not found');
|
|
||||||
|
|
||||||
widget.data = data;
|
|
||||||
|
|
||||||
await User.update(user._id, {
|
|
||||||
$set: {
|
|
||||||
'clientSettings.home': _home
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res();
|
|
||||||
|
|
||||||
event(user._id, 'home_updated', {
|
|
||||||
id, data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
import event from '../../../../publishers/stream';
|
import event from '../../../../publishers/stream';
|
||||||
|
@ -12,49 +9,16 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||||
.have('name', $.str)
|
.have('name', $.str)
|
||||||
.have('id', $.str)
|
.have('id', $.str)
|
||||||
.have('data', $.obj))
|
.have('data', $.obj))
|
||||||
.optional().get(params.home);
|
.get(params.home);
|
||||||
if (homeErr) return rej('invalid home param');
|
if (homeErr) return rej('invalid home param');
|
||||||
|
|
||||||
// Get 'id' parameter
|
await User.update(user._id, {
|
||||||
const [id, idErr] = $.str.optional().get(params.id);
|
$set: {
|
||||||
if (idErr) return rej('invalid id param');
|
'clientSettings.mobileHome': home
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get 'data' parameter
|
res();
|
||||||
const [data, dataErr] = $.obj.optional().get(params.data);
|
|
||||||
if (dataErr) return rej('invalid data param');
|
|
||||||
|
|
||||||
if (home) {
|
event(user._id, 'mobile_home_updated', home);
|
||||||
await User.update(user._id, {
|
|
||||||
$set: {
|
|
||||||
'clientSettings.mobileHome': home
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res();
|
|
||||||
|
|
||||||
event(user._id, 'mobile_home_updated', {
|
|
||||||
home
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
|
|
||||||
|
|
||||||
const _home = user.clientSettings.mobileHome || [];
|
|
||||||
const widget = _home.find(w => w.id == id);
|
|
||||||
|
|
||||||
if (widget == null) return rej('widget not found');
|
|
||||||
|
|
||||||
widget.data = data;
|
|
||||||
|
|
||||||
await User.update(user._id, {
|
|
||||||
$set: {
|
|
||||||
'clientSettings.mobileHome': _home
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res();
|
|
||||||
|
|
||||||
event(user._id, 'mobile_home_updated', {
|
|
||||||
id, data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
79
src/server/api/endpoints/i/update_widget.ts
Normal file
79
src/server/api/endpoints/i/update_widget.ts
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import User from '../../../../models/user';
|
||||||
|
import event from '../../../../publishers/stream';
|
||||||
|
|
||||||
|
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||||
|
// Get 'id' parameter
|
||||||
|
const [id, idErr] = $.str.get(params.id);
|
||||||
|
if (idErr) return rej('invalid id param');
|
||||||
|
|
||||||
|
// Get 'data' parameter
|
||||||
|
const [data, dataErr] = $.obj.get(params.data);
|
||||||
|
if (dataErr) return rej('invalid data param');
|
||||||
|
|
||||||
|
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
|
||||||
|
|
||||||
|
let widget;
|
||||||
|
|
||||||
|
//#region Desktop home
|
||||||
|
if (widget == null && user.clientSettings.home) {
|
||||||
|
const desktopHome = user.clientSettings.home;
|
||||||
|
widget = desktopHome.find(w => w.id == id);
|
||||||
|
if (widget) {
|
||||||
|
widget.data = data;
|
||||||
|
|
||||||
|
await User.update(user._id, {
|
||||||
|
$set: {
|
||||||
|
'clientSettings.home': desktopHome
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Mobile home
|
||||||
|
if (widget == null && user.clientSettings.mobileHome) {
|
||||||
|
const mobileHome = user.clientSettings.mobileHome;
|
||||||
|
widget = mobileHome.find(w => w.id == id);
|
||||||
|
if (widget) {
|
||||||
|
widget.data = data;
|
||||||
|
|
||||||
|
await User.update(user._id, {
|
||||||
|
$set: {
|
||||||
|
'clientSettings.mobileHome': mobileHome
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Deck
|
||||||
|
if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
|
||||||
|
const deck = user.clientSettings.deck;
|
||||||
|
deck.columns.filter(c => c.type == 'widgets').forEach(c => {
|
||||||
|
c.widgets.forEach(w => {
|
||||||
|
if (w.id == id) widget = w;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (widget) {
|
||||||
|
widget.data = data;
|
||||||
|
|
||||||
|
await User.update(user._id, {
|
||||||
|
$set: {
|
||||||
|
'clientSettings.deck': deck
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
if (widget) {
|
||||||
|
event(user._id, 'widgetUpdated', {
|
||||||
|
id, data
|
||||||
|
});
|
||||||
|
|
||||||
|
res();
|
||||||
|
} else {
|
||||||
|
rej('widget not found');
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue