commit: bfd802ad046886230574cf2262f9c2e5f1b03a3f
parent 4d23d31fecf480abfccc4db3ac79c6640078dc3b
Author: Henry Jameson <me@hjkos.com>
Date: Thu, 16 Mar 2023 23:18:55 +0200
setting admin settings works now. also now we have draftable settings
Diffstat:
14 files changed, 284 insertions(+), 45 deletions(-)
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -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>
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
@@ -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
+ }
+ }
}
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -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>
diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
@@ -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 {
+ ...Setting,
components: {
- Select,
- ModifiedIndicator,
- ProfileSettingIndicator
+ ...Setting.components,
+ Select
},
- ...Setting,
props: {
...Setting.props,
options: {
diff --git a/src/components/settings_modal/helpers/draft_buttons.vue b/src/components/settings_modal/helpers/draft_buttons.vue
@@ -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>
diff --git a/src/components/settings_modal/helpers/integer_setting.js b/src/components/settings_modal/helpers/integer_setting.js
@@ -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)
}
}
}
diff --git a/src/components/settings_modal/helpers/integer_setting.vue b/src/components/settings_modal/helpers/integer_setting.vue
@@ -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>
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
@@ -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!')
+ }
}
}
}
diff --git a/src/components/settings_modal/helpers/size_setting.js b/src/components/settings_modal/helpers/size_setting.js
@@ -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,
diff --git a/src/components/settings_modal/helpers/string_setting.js b/src/components/settings_modal/helpers/string_setting.js
@@ -1,9 +1,5 @@
-import ModifiedIndicator from './modified_indicator.vue'
import Setting from './setting.js'
export default {
- components: {
- ModifiedIndicator
- },
...Setting
}
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
@@ -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>
diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js
@@ -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 }))
}
}
}
diff --git a/src/modules/users.js b/src/modules/users.js
@@ -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 }))
}
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
@@ -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