setting admin settings works now. also now we have draftable settings
This commit is contained in:
parent
4d23d31fec
commit
bfd802ad04
@ -1,18 +1,35 @@
|
||||
<template>
|
||||
<div :label="$t('settings.general')">
|
||||
<div :label="$t('admin_dash.instance')">
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('admin_dash.instance') }}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<StringSetting source="admin" path=":pleroma.:instance.:name">
|
||||
<StringSetting
|
||||
source="admin"
|
||||
path=":pleroma.:instance.:name"
|
||||
draft-mode
|
||||
>
|
||||
NAME
|
||||
</StringSetting>
|
||||
</li>
|
||||
<li>
|
||||
<StringSetting source="admin" path=":pleroma.:instance.:description">
|
||||
<StringSetting
|
||||
source="admin"
|
||||
path=":pleroma.:instance.:description"
|
||||
draft-mode
|
||||
>
|
||||
DESCRIPTION
|
||||
</StringSetting>
|
||||
</li>
|
||||
<li>
|
||||
<IntegerSetting
|
||||
source="admin"
|
||||
path=":pleroma.:instance.:limit"
|
||||
draft-mode
|
||||
>
|
||||
POST LIMIT
|
||||
</IntegerSetting>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,13 +1,16 @@
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import ProfileSettingIndicator from './profile_setting_indicator.vue'
|
||||
import Setting from './setting.js'
|
||||
|
||||
export default {
|
||||
...Setting,
|
||||
components: {
|
||||
Checkbox,
|
||||
ModifiedIndicator,
|
||||
ProfileSettingIndicator
|
||||
...Setting.components,
|
||||
Checkbox
|
||||
},
|
||||
...Setting
|
||||
methods: {
|
||||
...Setting.methods,
|
||||
getValue (e) {
|
||||
return e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
class="BooleanSetting"
|
||||
>
|
||||
<Checkbox
|
||||
:model-value="state"
|
||||
:model-value="draftMode ? draft :state"
|
||||
:disabled="shouldBeDisabled"
|
||||
@update:modelValue="update"
|
||||
>
|
||||
@ -20,6 +20,7 @@
|
||||
:onclick="reset"
|
||||
/>
|
||||
<ProfileSettingIndicator :is-profile="isProfileSetting" />
|
||||
<DraftButtons />
|
||||
</Checkbox>
|
||||
</label>
|
||||
</template>
|
||||
|
@ -1,15 +1,12 @@
|
||||
import Select from 'src/components/select/select.vue'
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import ProfileSettingIndicator from './profile_setting_indicator.vue'
|
||||
import Setting from './setting.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Select,
|
||||
ModifiedIndicator,
|
||||
ProfileSettingIndicator
|
||||
},
|
||||
...Setting,
|
||||
components: {
|
||||
...Setting.components,
|
||||
Select
|
||||
},
|
||||
props: {
|
||||
...Setting.props,
|
||||
options: {
|
||||
|
102
src/components/settings_modal/helpers/draft_buttons.vue
Normal file
102
src/components/settings_modal/helpers/draft_buttons.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<!-- this is a helper exclusive to Setting components -->
|
||||
<!-- TODO make it reusable -->
|
||||
<template>
|
||||
<span
|
||||
class="DraftButtons"
|
||||
>
|
||||
<Popover
|
||||
trigger="hover"
|
||||
:trigger-attrs="{ 'aria-label': $t('settings.commit_value_tooltip') }"
|
||||
>
|
||||
<template #trigger>
|
||||
|
||||
<button
|
||||
v-if="$parent.isDirty"
|
||||
class="button button-default btn"
|
||||
type="button"
|
||||
:title="$t('settings.commit_value')"
|
||||
@click="$parent.commitDraft"
|
||||
>
|
||||
{{ $t('settings.commit_value') }}
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="modified-tooltip">
|
||||
{{ $t('settings.commit_value_tooltip') }}
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
<Popover
|
||||
trigger="hover"
|
||||
:trigger-attrs="{ 'aria-label': $t('settings.reset_value_tooltip') }"
|
||||
>
|
||||
<template #trigger>
|
||||
|
||||
<button
|
||||
v-if="$parent.isDirty"
|
||||
class="button button-default btn"
|
||||
type="button"
|
||||
:title="$t('settings.reset_value')"
|
||||
@click="$parent.reset"
|
||||
>
|
||||
{{ $t('settings.reset_value') }}
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="modified-tooltip">
|
||||
{{ $t('settings.reset_value_tooltip') }}
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
<Popover
|
||||
trigger="hover"
|
||||
:trigger-attrs="{ 'aria-label': $t('settings.hard_reset_value_tooltip') }"
|
||||
>
|
||||
<template #trigger>
|
||||
|
||||
<button
|
||||
v-if="$parent.canHardReset"
|
||||
class="button button-default btn"
|
||||
type="button"
|
||||
:title="$t('settings.hard_reset_value')"
|
||||
@click="$parent.hardReset"
|
||||
>
|
||||
{{ $t('settings.hard_reset_value') }}
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="modified-tooltip">
|
||||
{{ $t('settings.hard_reset_value_tooltip') }}
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Popover from 'src/components/popover/popover.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { faWrench } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faWrench
|
||||
)
|
||||
|
||||
export default {
|
||||
components: { Popover },
|
||||
props: ['changed']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.DraftButtons {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.draft-tooltip {
|
||||
margin: 0.5em 1em;
|
||||
min-width: 10em;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
@ -1,15 +1,11 @@
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import Setting from './setting.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModifiedIndicator
|
||||
},
|
||||
...Setting,
|
||||
methods: {
|
||||
...Setting.methods,
|
||||
update (e) {
|
||||
this.configSink(this.path, parseInt(e.target.value))
|
||||
getValue (e) {
|
||||
return parseInt(e.target.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
step="1"
|
||||
:disabled="disabled"
|
||||
:min="min || 0"
|
||||
:value="state"
|
||||
:value="draftMode ? draft :state"
|
||||
@change="update"
|
||||
>
|
||||
{{ ' ' }}
|
||||
@ -21,6 +21,8 @@
|
||||
:changed="isChanged"
|
||||
:onclick="reset"
|
||||
/>
|
||||
<ProfileSettingIndicator :is-profile="isProfileSetting" />
|
||||
<DraftButtons />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import ProfileSettingIndicator from './profile_setting_indicator.vue'
|
||||
import DraftButtons from './draft_buttons.vue'
|
||||
import { get, set } from 'lodash'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Checkbox,
|
||||
ModifiedIndicator,
|
||||
DraftButtons,
|
||||
ProfileSettingIndicator
|
||||
},
|
||||
props: {
|
||||
path: {
|
||||
type: String,
|
||||
@ -23,6 +34,20 @@ export default {
|
||||
source: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
draftMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
draft: null
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.draftMode) {
|
||||
this.draft = this.state
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -53,7 +78,7 @@ export default {
|
||||
case 'profile':
|
||||
return (k, v) => this.$store.dispatch('setProfileOption', { name: k, value: v })
|
||||
case 'admin':
|
||||
return (k, v) => console.log(this.path, k, v)
|
||||
return (k, v) => this.$store.dispatch('pushAdminSetting', { path: k, value: v })
|
||||
default:
|
||||
return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
|
||||
}
|
||||
@ -72,25 +97,56 @@ export default {
|
||||
isChanged () {
|
||||
switch (this.source) {
|
||||
case 'profile':
|
||||
return false
|
||||
case 'admin':
|
||||
console.log(this.$store.state.adminSettings.modifiedPaths)
|
||||
return this.$store.state.adminSettings.modifiedPaths.has(this.path)
|
||||
return false
|
||||
default:
|
||||
return this.state !== this.defaultState
|
||||
}
|
||||
},
|
||||
isDirty () {
|
||||
return this.draftMode && this.draft !== this.state
|
||||
},
|
||||
canHardReset () {
|
||||
return this.source === 'admin' && this.$store.state.adminSettings.modifiedPaths.has(this.path)
|
||||
},
|
||||
matchesExpertLevel () {
|
||||
return (this.expert || 0) <= this.$store.state.config.expertLevel > 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getValue (e) {
|
||||
return e.target.value
|
||||
},
|
||||
update (e) {
|
||||
console.log('U', this.path, e)
|
||||
this.configSink(this.path, e)
|
||||
if (this.draftMode) {
|
||||
this.draft = this.getValue(e)
|
||||
} else {
|
||||
this.configSink(this.path, this.getValue(e))
|
||||
}
|
||||
},
|
||||
commitDraft () {
|
||||
if (this.draftMode) {
|
||||
this.configSink(this.path, this.draft)
|
||||
}
|
||||
},
|
||||
reset () {
|
||||
set(this.$store.getters.mergedConfig, this.path, this.defaultState)
|
||||
console.log('reset')
|
||||
if (this.draftMode) {
|
||||
console.log(this.draft)
|
||||
console.log(this.state)
|
||||
this.draft = this.state
|
||||
} else {
|
||||
set(this.$store.getters.mergedConfig, this.path, this.defaultState)
|
||||
}
|
||||
},
|
||||
hardReset () {
|
||||
switch (this.source) {
|
||||
case 'admin':
|
||||
return this.$store.dispatch('resetAdminSetting', { path: this.path })
|
||||
.then(() => { this.draft = this.state })
|
||||
default:
|
||||
console.warn('Hard reset not implemented yet!')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import Select from 'src/components/select/select.vue'
|
||||
import Setting from './setting.js'
|
||||
|
||||
@ -7,11 +6,11 @@ export const defaultHorizontalUnits = ['px', 'rem', 'vw']
|
||||
export const defaultVerticalUnits = ['px', 'rem', 'vh']
|
||||
|
||||
export default {
|
||||
...Setting,
|
||||
components: {
|
||||
ModifiedIndicator,
|
||||
...Setting.components,
|
||||
Select
|
||||
},
|
||||
...Setting,
|
||||
props: {
|
||||
...Setting.props,
|
||||
min: Number,
|
||||
|
@ -1,9 +1,5 @@
|
||||
import ModifiedIndicator from './modified_indicator.vue'
|
||||
import Setting from './setting.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModifiedIndicator
|
||||
},
|
||||
...Setting
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
class="string-input"
|
||||
step="1"
|
||||
:disabled="disabled"
|
||||
:value="state"
|
||||
:value="draftMode ? draft :state"
|
||||
@change="update"
|
||||
>
|
||||
{{ ' ' }}
|
||||
@ -19,7 +19,9 @@
|
||||
:changed="isChanged"
|
||||
:onclick="reset"
|
||||
/>
|
||||
<ProfileSettingIndicator :is-profile="isProfileSetting" />
|
||||
<DraftButtons />
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script src="./boolean_setting.js"></script>
|
||||
<script src="./string_setting.js"></script>
|
||||
|
@ -22,8 +22,8 @@ const adminSettingsStorage = {
|
||||
},
|
||||
actions: {
|
||||
setInstanceAdminSettings ({ state, commit, dispatch }, { backendDbConfig }) {
|
||||
const config = {}
|
||||
const modifiedPaths = new Set()
|
||||
const config = state.config || {}
|
||||
const modifiedPaths = state.modifiedPaths || new Set()
|
||||
backendDbConfig.configs.forEach(c => {
|
||||
const path = c.group + '.' + c.key
|
||||
if (c.db) {
|
||||
@ -40,8 +40,54 @@ const adminSettingsStorage = {
|
||||
}
|
||||
set(config, path, convert(c.value))
|
||||
})
|
||||
console.log(config)
|
||||
commit('updateAdminSettings', { config, modifiedPaths })
|
||||
},
|
||||
pushAdminSetting ({ rootState, state, commit, dispatch }, { path, value }) {
|
||||
const [group, key, ...rest] = path.split(/\./g)
|
||||
const clone = {} // not actually cloning the entire thing to avoid excessive writes
|
||||
set(clone, rest.join('.'), value)
|
||||
|
||||
// TODO cleanup paths in modifiedPaths
|
||||
const convert = (value) => {
|
||||
if (typeof value !== 'object') {
|
||||
return value
|
||||
} else if (Array.isArray(value)) {
|
||||
return value.map(convert)
|
||||
} else {
|
||||
return Object.entries(value).map(([k, v]) => ({ tuple: [k, v] }))
|
||||
}
|
||||
}
|
||||
|
||||
rootState.api.backendInteractor.pushInstanceDBConfig({
|
||||
payload: {
|
||||
configs: [{
|
||||
group,
|
||||
key,
|
||||
value: convert(clone)
|
||||
}]
|
||||
}
|
||||
})
|
||||
.then(() => rootState.api.backendInteractor.fetchInstanceDBConfig())
|
||||
.then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
|
||||
},
|
||||
resetAdminSetting ({ rootState, state, commit, dispatch }, { path }) {
|
||||
console.log('ASS')
|
||||
const [group, key, subkey] = path.split(/\./g)
|
||||
|
||||
state.modifiedPaths.delete(path)
|
||||
|
||||
return rootState.api.backendInteractor.pushInstanceDBConfig({
|
||||
payload: {
|
||||
configs: [{
|
||||
group,
|
||||
key,
|
||||
delete: true,
|
||||
subkeys: [subkey]
|
||||
}]
|
||||
}
|
||||
})
|
||||
.then(() => rootState.api.backendInteractor.fetchInstanceDBConfig())
|
||||
.then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ const users = {
|
||||
user.domainMutes = []
|
||||
commit('setCurrentUser', user)
|
||||
commit('setServerSideStorage', user)
|
||||
if (user.rights.moderator || user.rights.admin) {
|
||||
if (user.rights.admin) {
|
||||
store.rootState.api.backendInteractor.fetchInstanceDBConfig()
|
||||
.then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements'
|
||||
const PLEROMA_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
|
||||
const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
|
||||
|
||||
const PLEROMA_ADMIN_CONFIG_URL = '/api/v1/pleroma/admin/config'
|
||||
const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config'
|
||||
|
||||
const oldfetch = window.fetch
|
||||
|
||||
@ -1677,6 +1677,27 @@ const fetchInstanceDBConfig = ({ credentials }) => {
|
||||
})
|
||||
}
|
||||
|
||||
const pushInstanceDBConfig = ({ credentials, payload }) => {
|
||||
return fetch(PLEROMA_ADMIN_CONFIG_URL, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...authHeaders(credentials)
|
||||
},
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
} else {
|
||||
return {
|
||||
error: response
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const apiService = {
|
||||
verifyCredentials,
|
||||
fetchTimeline,
|
||||
@ -1791,7 +1812,8 @@ const apiService = {
|
||||
editAnnouncement,
|
||||
deleteAnnouncement,
|
||||
adminFetchAnnouncements,
|
||||
fetchInstanceDBConfig
|
||||
fetchInstanceDBConfig,
|
||||
pushInstanceDBConfig
|
||||
}
|
||||
|
||||
export default apiService
|
||||
|
Loading…
Reference in New Issue
Block a user