Merge pull request #2405 from h3poteto/iss-2258
refs #2258 Display filters in settings
This commit is contained in:
commit
131438a421
|
@ -114,6 +114,39 @@
|
|||
"local": "Local Timeline",
|
||||
"public": "Public Timeline"
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"title": "Filters",
|
||||
"form": {
|
||||
"phrase": "Keyword or phrase",
|
||||
"expire": "Expire after",
|
||||
"context": "Filter contexts",
|
||||
"irreversible": "Drop instead of hide",
|
||||
"whole_word": "Whole word",
|
||||
"submit": "Submit",
|
||||
"cancel": "Cancel"
|
||||
},
|
||||
"expires": {
|
||||
"never": "Never",
|
||||
"30_minutes": "30 minutes",
|
||||
"1_hour": "1 hour",
|
||||
"6_hours": "6 hours",
|
||||
"12_hours": "12 hours",
|
||||
"1_day": "1 day",
|
||||
"1_week": "1 week"
|
||||
},
|
||||
"new": {
|
||||
"title": "New"
|
||||
},
|
||||
"edit": {
|
||||
"title": "Edit"
|
||||
},
|
||||
"delete": {
|
||||
"title": "Delete",
|
||||
"confirm": "Are you sure to delete this filter?",
|
||||
"confirm_ok": "Delete",
|
||||
"confirm_cancel": "Cancel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
|
@ -452,7 +485,8 @@
|
|||
"domain_confirmed": "{{domain}} is confirmed, please login",
|
||||
"domain_doesnt_exist": "Failed to connect {{domain}}, make sure the server URL",
|
||||
"loading": "Loading...",
|
||||
"language_not_support_spellchecker_error": "This language is not supported by Spellchecker"
|
||||
"language_not_support_spellchecker_error": "This language is not supported by Spellchecker",
|
||||
"update_filter_error": "Failed to update the filter"
|
||||
},
|
||||
"validation": {
|
||||
"login": {
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
<icon name="align-left" class="icon" scale="1.3"></icon>
|
||||
<span>{{ $t('settings.timeline.title') }}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="`/${id()}/settings/filters`">
|
||||
<icon name="filter" class="icon" scale="1.3"></icon>
|
||||
<span>{{ $t('settings.filters.title') }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-main>
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div id="filters">
|
||||
<h2>{{ $t('settings.filters.title') }}</h2>
|
||||
<div class="new-filter">
|
||||
<el-button type="primary">
|
||||
<router-link tag="span" :to="`/${id()}/settings/filters/new`">
|
||||
{{ $t('settings.filters.new.title') }}
|
||||
</router-link>
|
||||
</el-button>
|
||||
</div>
|
||||
<template>
|
||||
<el-table
|
||||
:data="filters"
|
||||
tooltip-effect="dark"
|
||||
empty-text="No filters"
|
||||
style="width: 100%"
|
||||
v-loading="filtersLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
>
|
||||
<el-table-column prop="phrase" label="Keyword" width="180"> </el-table-column>
|
||||
<el-table-column label="Context">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ filters[scope.$index].context.join(',') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expires_at" label="Expires" width="180"> </el-table-column>
|
||||
<el-table-column width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text">
|
||||
<router-link tag="span" :to="`/${id()}/settings/filters/${filters[scope.$index].id}/edit`">
|
||||
{{ $t('settings.filters.edit.title') }}
|
||||
</router-link>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="deleteFilter(filters[scope.$index].id)">
|
||||
{{ $t('settings.filters.delete.title') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Filters',
|
||||
computed: {
|
||||
...mapState('Settings/Filters', {
|
||||
filters: state => state.filters,
|
||||
filtersLoading: state => state.filtersLoading
|
||||
}),
|
||||
...mapState({
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
})
|
||||
},
|
||||
async created() {
|
||||
await this.$store.dispatch('Settings/Filters/fetchFilters')
|
||||
},
|
||||
methods: {
|
||||
id() {
|
||||
return this.$route.params.id
|
||||
},
|
||||
deleteFilter(id) {
|
||||
this.$confirm(this.$t('settings.filters.delete.confirm'), 'Warning', {
|
||||
confirmButtonText: this.$t('settings.filters.delete.confirm_ok'),
|
||||
cancelButtonText: this.$t('settings.filters.delete.confirm_cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return this.$store.dispatch('Settings/Filters/deleteFilter', id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#filters {
|
||||
.new-filter {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.el-table /deep/ {
|
||||
tr,
|
||||
th,
|
||||
td,
|
||||
.el-table__empty-block {
|
||||
background-color: var(--theme-background-color);
|
||||
color: var(--theme-primary-color);
|
||||
border-bottom: 1px solid var(--theme-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
.el-table::before {
|
||||
background-color: var(--theme-border-color);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<div id="edit_filter">
|
||||
<h2>{{ $t('settings.filters.edit.title') }}</h2>
|
||||
<FilterForm v-model="filter" @cancel="cancel" @onSubmit="onSubmit" :loading="loading"> </FilterForm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import FilterForm from './form'
|
||||
|
||||
export default {
|
||||
name: 'EditFilter',
|
||||
props: ['filter_id'],
|
||||
components: { FilterForm },
|
||||
computed: {
|
||||
...mapState('Settings/Filters/Edit', {
|
||||
loading: state => state.loading
|
||||
}),
|
||||
filter: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Filters.Edit.filter
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Filters/Edit/editFilter', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.$store.dispatch('Settings/Filters/Edit/fetchFilter', this.filter_id)
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.$router.go(-1)
|
||||
},
|
||||
onSubmit() {
|
||||
this.$store
|
||||
.dispatch('Settings/Filters/Edit/updateFilter')
|
||||
.then(() => {
|
||||
this.$router.go(-1)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.update_filter_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<div id="new_filter">
|
||||
<h2>{{ $t('settings.filters.new.title') }}</h2>
|
||||
<FilterForm v-model="filter" @cancel="cancel" @onSubmit="onSubmit" :loading="loading"> </FilterForm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import FilterForm from './form'
|
||||
|
||||
export default {
|
||||
name: 'NewFilter',
|
||||
components: { FilterForm },
|
||||
computed: {
|
||||
...mapState('Settings/Filters/New', {
|
||||
loading: state => state.loading
|
||||
}),
|
||||
filter: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Filters.New.filter
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Filters/New/editFilter', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.$router.go(-1)
|
||||
},
|
||||
onSubmit() {
|
||||
this.$store
|
||||
.dispatch('Settings/Filters/New/createFilter')
|
||||
.then(() => {
|
||||
this.$router.go(-1)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.create_filter_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<el-form ref="form" class="section" label-width="200px" label-position="right" size="medium">
|
||||
<el-form-item :label="$t('settings.filters.form.phrase')">
|
||||
<el-input v-model="filterPhrase"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('settings.filters.form.expire')">
|
||||
<el-select v-model="filterExpire" value-key="value">
|
||||
<el-option v-for="exp in expires" :key="exp.value" :label="exp.label" :value="exp"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('settings.filters.form.context')">
|
||||
<template>
|
||||
<el-checkbox-group v-model="filterContext">
|
||||
<el-checkbox label="home"></el-checkbox>
|
||||
<el-checkbox label="notifications"></el-checkbox>
|
||||
<el-checkbox label="public"></el-checkbox>
|
||||
<el-checkbox label="thread"></el-checkbox>
|
||||
<el-checkbox label="account"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="filterIrreversible">{{ $t('settings.filters.form.irreversible') }}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="filterWholeWord">{{ $t('settings.filters.form.whole_word') }}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit" v-loading="loading">{{ $t('settings.filters.form.submit') }}</el-button>
|
||||
<el-button @click="cancel">{{ $t('settings.filters.form.cancel') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FilterForm',
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expires: [
|
||||
{
|
||||
label: this.$t('settings.filters.expires.never'),
|
||||
value: null
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.30_minutes'),
|
||||
value: 60 * 30
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_hour'),
|
||||
value: 3600
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.6_hours'),
|
||||
value: 3600 * 6
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.12_hours'),
|
||||
value: 3600 * 12
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_week'),
|
||||
value: 3600 * 24 * 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filter: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
filterPhrase: {
|
||||
get() {
|
||||
return this.filter.phrase
|
||||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
phrase: value
|
||||
})
|
||||
}
|
||||
},
|
||||
filterExpire: {
|
||||
get() {
|
||||
return this.filter.expires_at
|
||||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
expires_at: value
|
||||
})
|
||||
}
|
||||
},
|
||||
filterContext: {
|
||||
get() {
|
||||
return this.filter.context
|
||||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
context: value
|
||||
})
|
||||
}
|
||||
},
|
||||
filterIrreversible: {
|
||||
get() {
|
||||
return this.filter.irreversible
|
||||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
irreversible: value
|
||||
})
|
||||
}
|
||||
},
|
||||
filterWholeWord: {
|
||||
get() {
|
||||
return this.filter.whole_word
|
||||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
whole_word: value
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.$emit('cancel')
|
||||
},
|
||||
onSubmit() {
|
||||
this.$emit('onSubmit')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.section /deep/ {
|
||||
margin-bottom: 40px;
|
||||
|
||||
.el-form-item__label {
|
||||
color: var(--theme-primary-color);
|
||||
}
|
||||
|
||||
.el-checkbox__label {
|
||||
color: var(--theme-primary-color);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -14,6 +14,9 @@ import GlobalHeader from '@/components/GlobalHeader.vue'
|
|||
import Settings from '@/components/Settings.vue'
|
||||
import SettingsGeneral from '@/components/Settings/General.vue'
|
||||
import SettingsTimeline from '@/components/Settings/Timeline.vue'
|
||||
import SettingsFilters from '@/components/Settings/Filters.vue'
|
||||
import SettingsFiltersEdit from '@/components/Settings/Filters/Edit.vue'
|
||||
import SettingsFiltersNew from '@/components/Settings/Filters/New.vue'
|
||||
import TimelineSpace from '@/components/TimelineSpace.vue'
|
||||
import TimelineSpaceContentsHome from '@/components/TimelineSpace/Contents/Home.vue'
|
||||
import TimelineSpaceContentsNotifications from '@/components/TimelineSpace/Contents/Notifications.vue'
|
||||
|
@ -100,6 +103,19 @@ const router = new Router({
|
|||
{
|
||||
path: 'timeline',
|
||||
component: SettingsTimeline
|
||||
},
|
||||
{
|
||||
path: 'filters',
|
||||
component: SettingsFilters
|
||||
},
|
||||
{
|
||||
path: 'filters/new',
|
||||
component: SettingsFiltersNew
|
||||
},
|
||||
{
|
||||
path: 'filters/:filter_id/edit',
|
||||
component: SettingsFiltersEdit,
|
||||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import General, { GeneralState } from './Settings/General'
|
||||
import Timeline, { TimelineState } from './Settings/Timeline'
|
||||
import Filters, { FiltersModuleState } from './Settings/Filters'
|
||||
import { Module, MutationTree } from 'vuex'
|
||||
import { RootState } from '@/store'
|
||||
|
||||
|
@ -24,6 +25,7 @@ const mutations: MutationTree<SettingsState> = {
|
|||
type SettingsModule = {
|
||||
General: GeneralState
|
||||
Timeline: TimelineState
|
||||
Filter: FiltersModuleState
|
||||
}
|
||||
|
||||
export type SettingsModuleState = SettingsModule & SettingsState
|
||||
|
@ -32,7 +34,8 @@ const Settings: Module<SettingsState, RootState> = {
|
|||
namespaced: true,
|
||||
modules: {
|
||||
General,
|
||||
Timeline
|
||||
Timeline,
|
||||
Filters
|
||||
},
|
||||
state: state,
|
||||
mutations: mutations
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import { Module, MutationTree, ActionTree } from 'vuex'
|
||||
import generator, { Entity } from 'megalodon'
|
||||
import { RootState } from '@/store'
|
||||
import EditFilters, { EditFiltersState } from './Filters/Edit'
|
||||
import NewFilters, { NewFiltersState } from './Filters/New'
|
||||
|
||||
export type FiltersState = {
|
||||
filters: Array<Entity.Filter>
|
||||
filtersLoading: boolean
|
||||
}
|
||||
|
||||
const state = (): FiltersState => ({
|
||||
filters: [],
|
||||
filtersLoading: false
|
||||
})
|
||||
|
||||
export const MUTATION_TYPES = {
|
||||
UPDATE_FILTERS: 'updateFilters',
|
||||
CHANGE_LOADING: 'changeLoading'
|
||||
}
|
||||
|
||||
export const mutations: MutationTree<FiltersState> = {
|
||||
[MUTATION_TYPES.UPDATE_FILTERS]: (state, filters: Array<Entity.Filter>) => {
|
||||
state.filters = filters
|
||||
},
|
||||
[MUTATION_TYPES.CHANGE_LOADING]: (state, loading: boolean) => {
|
||||
state.filtersLoading = loading
|
||||
}
|
||||
}
|
||||
export const actions: ActionTree<FiltersState, RootState> = {
|
||||
fetchFilters: async ({ commit, rootState }): Promise<Array<Entity.Filter>> => {
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
rootState.TimelineSpace.account.accessToken,
|
||||
rootState.App.userAgent
|
||||
)
|
||||
try {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
const res = await client.getFilters()
|
||||
commit(MUTATION_TYPES.UPDATE_FILTERS, res.data)
|
||||
return res.data
|
||||
} finally {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
},
|
||||
deleteFilter: async ({ commit, dispatch, rootState }, id: string) => {
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
rootState.TimelineSpace.account.accessToken,
|
||||
rootState.App.userAgent
|
||||
)
|
||||
try {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
await client.deleteFilter(id)
|
||||
await dispatch('fetchFilters')
|
||||
} finally {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type FiltersModule = {
|
||||
Edit: EditFiltersState
|
||||
New: NewFiltersState
|
||||
}
|
||||
|
||||
export type FiltersModuleState = FiltersModule & FiltersState
|
||||
|
||||
const Filters: Module<FiltersState, RootState> = {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
mutations: mutations,
|
||||
actions: actions,
|
||||
modules: {
|
||||
Edit: EditFilters,
|
||||
New: NewFilters
|
||||
}
|
||||
}
|
||||
|
||||
export default Filters
|
|
@ -0,0 +1,93 @@
|
|||
import generator, { Entity } from 'megalodon'
|
||||
import { Module, MutationTree, ActionTree } from 'vuex'
|
||||
import { RootState } from '@/store'
|
||||
|
||||
export type EditFiltersState = {
|
||||
filter: Entity.Filter
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
const state = (): EditFiltersState => ({
|
||||
filter: {
|
||||
id: '',
|
||||
phrase: '',
|
||||
expires_at: null,
|
||||
context: [],
|
||||
irreversible: false,
|
||||
whole_word: true
|
||||
} as Entity.Filter,
|
||||
loading: false
|
||||
})
|
||||
|
||||
export const MUTATION_TYPES = {
|
||||
UPDATE_FILTER: 'updateFilter',
|
||||
CHANGE_LOADING: 'changeLoading'
|
||||
}
|
||||
|
||||
export const mutations: MutationTree<EditFiltersState> = {
|
||||
[MUTATION_TYPES.UPDATE_FILTER]: (state, filter: Entity.Filter) => {
|
||||
state.filter = filter
|
||||
},
|
||||
[MUTATION_TYPES.CHANGE_LOADING]: (state, loading: boolean) => {
|
||||
state.loading = loading
|
||||
}
|
||||
}
|
||||
|
||||
export const actions: ActionTree<EditFiltersState, RootState> = {
|
||||
fetchFilter: async ({ commit, rootState }, id: string): Promise<Entity.Filter> => {
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
rootState.TimelineSpace.account.accessToken,
|
||||
rootState.App.userAgent
|
||||
)
|
||||
try {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
const res = await client.getFilter(id)
|
||||
commit(MUTATION_TYPES.UPDATE_FILTER, res.data)
|
||||
return res.data
|
||||
} finally {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
},
|
||||
editFilter: ({ commit, state }, filter: any) => {
|
||||
const newFilter = Object.assign({}, state.filter, filter)
|
||||
commit(MUTATION_TYPES.UPDATE_FILTER, newFilter)
|
||||
},
|
||||
updateFilter: async ({ commit, state, rootState }): Promise<Entity.Filter> => {
|
||||
if (state.filter === null) {
|
||||
throw new Error('filter is not set')
|
||||
}
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
rootState.TimelineSpace.account.accessToken,
|
||||
rootState.App.userAgent
|
||||
)
|
||||
try {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
let options = {
|
||||
irreversible: state.filter.irreversible,
|
||||
whole_word: state.filter.whole_word
|
||||
}
|
||||
if (state.filter.expires_at !== null) {
|
||||
options = Object.assign({}, options, {
|
||||
expires_in: state.filter.expires_at
|
||||
})
|
||||
}
|
||||
const res = await client.updateFilter(state.filter.id, state.filter.phrase, state.filter.context, options)
|
||||
return res.data
|
||||
} finally {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EditFilters: Module<EditFiltersState, RootState> = {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
mutations: mutations,
|
||||
actions: actions
|
||||
}
|
||||
|
||||
export default EditFilters
|
|
@ -0,0 +1,83 @@
|
|||
import generator, { Entity } from 'megalodon'
|
||||
import { Module, MutationTree, ActionTree } from 'vuex'
|
||||
import { RootState } from '@/store'
|
||||
|
||||
export type NewFiltersState = {
|
||||
filter: Entity.Filter
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
const defaultFilter: Entity.Filter = {
|
||||
id: '',
|
||||
phrase: '',
|
||||
expires_at: null,
|
||||
context: [],
|
||||
irreversible: false,
|
||||
whole_word: true
|
||||
}
|
||||
|
||||
const state = (): NewFiltersState => ({
|
||||
filter: defaultFilter,
|
||||
loading: false
|
||||
})
|
||||
|
||||
export const MUTATION_TYPES = {
|
||||
UPDATE_FILTER: 'updateFilter',
|
||||
CHANGE_LOADING: 'changeLoading'
|
||||
}
|
||||
|
||||
export const mutations: MutationTree<NewFiltersState> = {
|
||||
[MUTATION_TYPES.UPDATE_FILTER]: (state, filter: Entity.Filter) => {
|
||||
state.filter = filter
|
||||
},
|
||||
[MUTATION_TYPES.CHANGE_LOADING]: (state, loading: boolean) => {
|
||||
state.loading = loading
|
||||
}
|
||||
}
|
||||
|
||||
export const actions: ActionTree<NewFiltersState, RootState> = {
|
||||
editFilter: ({ commit, state }, filter: any) => {
|
||||
const newFilter = Object.assign({}, state.filter, filter)
|
||||
commit(MUTATION_TYPES.UPDATE_FILTER, newFilter)
|
||||
},
|
||||
resetFilter: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.UPDATE_FILTER, defaultFilter)
|
||||
},
|
||||
createFilter: async ({ commit, state, dispatch, rootState }): Promise<Entity.Filter> => {
|
||||
if (state.filter === null) {
|
||||
throw new Error('filter is not set')
|
||||
}
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
rootState.TimelineSpace.account.accessToken,
|
||||
rootState.App.userAgent
|
||||
)
|
||||
try {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
let options = {
|
||||
irreversible: state.filter.irreversible,
|
||||
whole_word: state.filter.whole_word
|
||||
}
|
||||
if (state.filter.expires_at !== null) {
|
||||
options = Object.assign({}, options, {
|
||||
expires_in: state.filter.expires_at
|
||||
})
|
||||
}
|
||||
const res = await client.createFilter(state.filter.phrase, state.filter.context, options)
|
||||
dispatch('resetFilter')
|
||||
return res.data
|
||||
} finally {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NewFilters: Module<NewFiltersState, RootState> = {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
mutations: mutations,
|
||||
actions: actions
|
||||
}
|
||||
|
||||
export default NewFilters
|
Loading…
Reference in New Issue