refs #2258 Add edit filter form

This commit is contained in:
AkiraFukushima 2021-05-10 00:49:24 +09:00
parent e56f3b0817
commit 783ddddafe
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
7 changed files with 351 additions and 5 deletions

View File

@ -116,7 +116,31 @@
}
},
"filters": {
"title": "Filters"
"title": "Filters",
"edit": {
"title": "Edit",
"form": {
"phrase": "Keyword or phrase",
"expire": "Expire after",
"context": "Filter contexts",
"irreversible": "Drop instead of hide",
"whole_word": "Whole word",
"submit": "Update",
"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"
}
},
"delete": {
"title": "Delete"
}
}
},
"preferences": {
@ -455,7 +479,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": {

View File

@ -17,6 +17,22 @@
</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>
@ -38,6 +54,14 @@ export default {
},
async created() {
await this.$store.dispatch('Settings/Filters/fetchFilters')
},
methods: {
id() {
return this.$route.params.id
},
deleteFilter(id) {
console.log(id)
}
}
}
</script>

View File

@ -0,0 +1,195 @@
<template>
<div id="edit_filter">
<h2>{{ $t('settings.filters.edit.title') }}</h2>
<el-form ref="form" class="section" label-width="200px" label-position="right" size="medium">
<el-form-item :label="$t('settings.filters.edit.form.phrase')">
<el-input v-model="filterPhrase"></el-input>
</el-form-item>
<el-form-item :label="$t('settings.filters.edit.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.edit.form.context')">
<template>
<el-checkbox-group v-model="filterContexts">
<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.edit.form.irreversible') }}</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="filterWholeWord">{{ $t('settings.filters.edit.form.whole_word') }}</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit" v-loading="loading">{{ $t('settings.filters.edit.form.submit') }}</el-button>
<el-button @click="cancel">{{ $t('settings.filters.edit.form.cancel') }}</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'EditFilter',
props: ['filter_id'],
data() {
return {
expires: [
{
label: this.$t('settings.filters.edit.expires.never'),
value: null
},
{
label: this.$t('settings.filters.edit.expires.30_minutes'),
value: 60 * 30
},
{
label: this.$t('settings.filters.edit.expires.1_hour'),
value: 3600
},
{
label: this.$t('settings.filters.edit.expires.6_hours'),
value: 3600 * 6
},
{
label: this.$t('settings.filters.edit.expires.12_hours'),
value: 3600 * 12
},
{
label: this.$t('settings.filters.edit.expires.1_day'),
value: 3600 * 24
},
{
label: this.$t('settings.filters.edit.expires.1_week'),
value: 3600 * 24 * 7
}
]
}
},
computed: {
...mapState('Settings/Filters/Edit', {
loading: state => state.loading
}),
filterPhrase: {
get() {
if (this.$store.state.Settings.Filters.Edit.filter !== null) {
return this.$store.state.Settings.Filters.Edit.filter.phrase
} else {
return ''
}
},
set(value) {
this.$store.dispatch('Settings/Filters/Edit/editFilter', {
phrase: value
})
}
},
filterExpire: {
get() {
if (this.$store.state.Settings.Filters.Edit.filter !== null) {
return this.$store.state.Settings.Filters.Edit.filter.expires_at
} else {
return null
}
},
set(value) {
this.$store.dispatch('Settings/Filters/Edit/editFilter', {
expires_at: value
})
}
},
filterContexts: {
get() {
if (this.$store.state.Settings.Filters.Edit.filter !== null) {
return this.$store.state.Settings.Filters.Edit.filter.context
} else {
return []
}
},
set(value) {
this.$store.dispatch('Settings/Filters/Edit/editFilter', {
context: value
})
}
},
filterIrreversible: {
get() {
if (this.$store.state.Settings.Filters.Edit.filter !== null) {
return this.$store.state.Settings.Filters.Edit.filter.irreversible
} else {
return false
}
},
set(value) {
this.$store.dispatch('Settings/Filters/Edit/editFilter', {
irreversible: value
})
}
},
filterWholeWord: {
get() {
if (this.$store.state.Settings.Filters.Edit.filter !== null) {
return this.$store.state.Settings.Filters.Edit.filter.whole_word
} else {
return false
}
},
set(value) {
this.$store.dispatch('Settings/Filters/Edit/editFilter', {
whole_word: 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>
<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);
}
}
.notice {
color: #c0c4cc;
font-size: 12px;
}
</style>

View File

@ -15,6 +15,7 @@ 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 TimelineSpace from '@/components/TimelineSpace.vue'
import TimelineSpaceContentsHome from '@/components/TimelineSpace/Contents/Home.vue'
import TimelineSpaceContentsNotifications from '@/components/TimelineSpace/Contents/Notifications.vue'
@ -105,6 +106,11 @@ const router = new Router({
{
path: 'filters',
component: SettingsFilters
},
{
path: 'filters/:filter_id/edit',
component: SettingsFiltersEdit,
props: true
}
]
},

View File

@ -1,6 +1,6 @@
import General, { GeneralState } from './Settings/General'
import Timeline, { TimelineState } from './Settings/Timeline'
import Filters, { FiltersState } from './Settings/Filters'
import Filters, { FiltersModuleState } from './Settings/Filters'
import { Module, MutationTree } from 'vuex'
import { RootState } from '@/store'
@ -25,7 +25,7 @@ const mutations: MutationTree<SettingsState> = {
type SettingsModule = {
General: GeneralState
Timeline: TimelineState
Filter: FiltersState
Filter: FiltersModuleState
}
export type SettingsModuleState = SettingsModule & SettingsState

View File

@ -1,6 +1,7 @@
import { Module, MutationTree, ActionTree } from 'vuex'
import generator, { Entity } from 'megalodon'
import { RootState } from '@/store'
import EditFilters, { EditFiltersState } from './Filters/Edit'
export type FiltersState = {
filters: Array<Entity.Filter>
@ -44,11 +45,20 @@ export const actions: ActionTree<FiltersState, RootState> = {
}
}
type FiltersModule = {
Edit: EditFiltersState
}
export type FiltersModuleState = FiltersModule & FiltersState
const Filters: Module<FiltersState, RootState> = {
namespaced: true,
state: state,
mutations: mutations,
actions: actions
actions: actions,
modules: {
Edit: EditFilters
}
}
export default Filters

View File

@ -0,0 +1,86 @@
import generator, { Entity } from 'megalodon'
import { Module, MutationTree, ActionTree } from 'vuex'
import { RootState } from '@/store'
export type EditFiltersState = {
filter: Entity.Filter | null
loading: boolean
}
const state = (): EditFiltersState => ({
filter: null,
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