aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/desktop_nav/desktop_nav.js5
-rw-r--r--src/components/desktop_nav/desktop_nav.vue9
-rw-r--r--src/components/interface_language_switcher/interface_language_switcher.vue4
-rw-r--r--src/components/notification/notification.vue2
-rw-r--r--src/components/settings_modal/admin_tabs/instance_tab.js29
-rw-r--r--src/components/settings_modal/admin_tabs/instance_tab.vue119
-rw-r--r--src/components/settings_modal/admin_tabs/limits_tab.js29
-rw-r--r--src/components/settings_modal/admin_tabs/limits_tab.vue152
-rw-r--r--src/components/settings_modal/helpers/boolean_setting.js56
-rw-r--r--src/components/settings_modal/helpers/boolean_setting.vue20
-rw-r--r--src/components/settings_modal/helpers/choice_setting.js54
-rw-r--r--src/components/settings_modal/helpers/choice_setting.vue2
-rw-r--r--src/components/settings_modal/helpers/draft_buttons.vue102
-rw-r--r--src/components/settings_modal/helpers/number_setting.js62
-rw-r--r--src/components/settings_modal/helpers/number_setting.vue2
-rw-r--r--src/components/settings_modal/helpers/profile_setting_indicator.vue (renamed from src/components/settings_modal/helpers/server_side_indicator.vue)12
-rw-r--r--src/components/settings_modal/helpers/setting.js161
-rw-r--r--src/components/settings_modal/helpers/shared_computed_object.js50
-rw-r--r--src/components/settings_modal/helpers/size_setting.js51
-rw-r--r--src/components/settings_modal/helpers/string_setting.js5
-rw-r--r--src/components/settings_modal/helpers/string_setting.vue38
-rw-r--r--src/components/settings_modal/settings_modal.js23
-rw-r--r--src/components/settings_modal/settings_modal.scss6
-rw-r--r--src/components/settings_modal/settings_modal.vue3
-rw-r--r--src/components/settings_modal/settings_modal_admin_content.js78
-rw-r--r--src/components/settings_modal/settings_modal_admin_content.scss (renamed from src/components/settings_modal/settings_modal_content.scss)0
-rw-r--r--src/components/settings_modal/settings_modal_admin_content.vue28
-rw-r--r--src/components/settings_modal/settings_modal_user_content.js (renamed from src/components/settings_modal/settings_modal_content.js)0
-rw-r--r--src/components/settings_modal/settings_modal_user_content.scss56
-rw-r--r--src/components/settings_modal/settings_modal_user_content.vue (renamed from src/components/settings_modal/settings_modal_content.vue)4
-rw-r--r--src/components/settings_modal/tabs/filtering_tab.vue14
-rw-r--r--src/components/settings_modal/tabs/general_tab.js6
-rw-r--r--src/components/settings_modal/tabs/general_tab.vue32
-rw-r--r--src/components/settings_modal/tabs/notifications_tab.vue8
-rw-r--r--src/components/settings_modal/tabs/profile_tab.vue50
-rw-r--r--src/components/settings_modal/tabs/security_tab/security_tab.vue22
-rw-r--r--src/components/tab_switcher/tab_switcher.jsx8
-rw-r--r--src/main.js6
-rw-r--r--src/modules/adminSettings.js115
-rw-r--r--src/modules/config.js75
-rw-r--r--src/modules/interface.js21
-rw-r--r--src/modules/profileConfig.js (renamed from src/modules/serverSideConfig.js)22
-rw-r--r--src/modules/users.js41
-rw-r--r--src/services/api/api.service.js60
44 files changed, 1261 insertions, 381 deletions
diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js
index 745b1a81..f6a2e294 100644
--- a/src/components/desktop_nav/desktop_nav.js
+++ b/src/components/desktop_nav/desktop_nav.js
@@ -107,7 +107,10 @@ export default {
this.searchBarHidden = hidden
},
openSettingsModal () {
- this.$store.dispatch('openSettingsModal')
+ this.$store.dispatch('openSettingsModal', 'user')
+ },
+ openAdminModal () {
+ this.$store.dispatch('openSettingsModal', 'admin')
}
}
}
diff --git a/src/components/desktop_nav/desktop_nav.vue b/src/components/desktop_nav/desktop_nav.vue
index dc8bbfd3..49382f8e 100644
--- a/src/components/desktop_nav/desktop_nav.vue
+++ b/src/components/desktop_nav/desktop_nav.vue
@@ -48,20 +48,19 @@
icon="cog"
/>
</button>
- <a
+ <button
v-if="currentUser && currentUser.role === 'admin'"
- href="/pleroma/admin/#/login-pleroma"
- class="nav-icon"
+ class="button-unstyled nav-icon"
target="_blank"
:title="$t('nav.administration')"
- @click.stop
+ @click.stop="openAdminModal"
>
<FAIcon
fixed-width
class="fa-scale-110 fa-old-padding"
icon="tachometer-alt"
/>
- </a>
+ </button>
<span class="spacer" />
<button
v-if="currentUser"
diff --git a/src/components/interface_language_switcher/interface_language_switcher.vue b/src/components/interface_language_switcher/interface_language_switcher.vue
index a57e8761..364791a1 100644
--- a/src/components/interface_language_switcher/interface_language_switcher.vue
+++ b/src/components/interface_language_switcher/interface_language_switcher.vue
@@ -36,7 +36,9 @@
<button
class="button-default btn"
@click="addLanguage"
- >{{ $t('settings.add_language') }}</button>
+ >
+ {{ $t('settings.add_language') }}
+ </button>
</li>
</ul>
</div>
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 4d801c5e..13e7f9b8 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -162,8 +162,8 @@
</router-link>
<button
class="button-unstyled expand-icon"
- :aria-expanded="statusExpanded"
:title="$t('tool_tip.toggle_expand')"
+ :aria-expanded="statusExpanded"
@click.prevent="toggleStatusExpanded"
>
<FAIcon
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.js b/src/components/settings_modal/admin_tabs/instance_tab.js
new file mode 100644
index 00000000..4a261659
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/instance_tab.js
@@ -0,0 +1,29 @@
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import StringSetting from '../helpers/string_setting.vue'
+
+import SharedComputedObject from '../helpers/shared_computed_object.js'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faGlobe
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faGlobe
+)
+
+const InstanceTab = {
+ data () {},
+ components: {
+ BooleanSetting,
+ ChoiceSetting,
+ IntegerSetting,
+ StringSetting
+ },
+ computed: {
+ ...SharedComputedObject()
+ }
+}
+
+export default InstanceTab
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
new file mode 100644
index 00000000..ad271293
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -0,0 +1,119 @@
+<template>
+ <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"
+ draft-mode
+ >
+ NAME
+ </StringSetting>
+ </li>
+ <li>
+ <StringSetting
+ source="admin"
+ path=":pleroma.:instance.:email"
+ draft-mode
+ >
+ ADMIN EMAIL
+ </StringSetting>
+ </li>
+ <li>
+ <StringSetting
+ source="admin"
+ path=":pleroma.:instance.:description"
+ draft-mode
+ >
+ DESCRIPTION
+ </StringSetting>
+ </li>
+ <li>
+ <StringSetting
+ source="admin"
+ path=":pleroma.:instance.:short_description"
+ draft-mode
+ >
+ SHORT DESCRIPTION
+ </StringSetting>
+ </li>
+ <li>
+ <StringSetting
+ source="admin"
+ path=":pleroma.:instance.:instance_thumbnail"
+ draft-mode
+ >
+ INSTANCE THUMBNAIL
+ </StringSetting>
+ </li>
+ <li>
+ <StringSetting
+ source="admin"
+ path=":pleroma.:instance.:background_image"
+ draft-mode
+ >
+ BACKGROUND IMAGE
+ </StringSetting>
+ </li>
+ <li>
+ <BooleanSetting
+ source="admin"
+ path=":pleroma.:instance.:public"
+ draft-mode
+ >
+ PUBLIC
+ </BooleanSetting>
+ </li>
+ </ul>
+ </div>
+ <div class="setting-item">
+ <h2>{{ $t('admin_dash.registrations') }}</h2>
+ <ul class="setting-list">
+ <li>
+ <BooleanSetting
+ source="admin"
+ path=":pleroma.:instance.:registrations_open"
+ draft-mode
+ >
+ REGISTRATIONS OPEN
+ </BooleanSetting>
+ <ul class="setting-list suboptions">
+ <li>
+ <BooleanSetting
+ source="admin"
+ path=":pleroma.:instance.:invites_enabled"
+ parent-path=":pleroma.:instance.:registrations_open"
+ :parent-invert="true"
+ draft-mode
+ >
+ INVITES ENABLED
+ </BooleanSetting>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <BooleanSetting
+ source="admin"
+ path=":pleroma.:instance.:account_activation_required"
+ draft-mode
+ >
+ ACTIVATION REQUIRED
+ </BooleanSetting>
+ </li>
+ <li>
+ <BooleanSetting
+ source="admin"
+ path=":pleroma.:instance.:account_approval_required"
+ draft-mode
+ >
+ APPROVAL REQUIRED
+ </BooleanSetting>
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
+
+<script src="./instance_tab.js"></script>
diff --git a/src/components/settings_modal/admin_tabs/limits_tab.js b/src/components/settings_modal/admin_tabs/limits_tab.js
new file mode 100644
index 00000000..684739c3
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/limits_tab.js
@@ -0,0 +1,29 @@
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import StringSetting from '../helpers/string_setting.vue'
+
+import SharedComputedObject from '../helpers/shared_computed_object.js'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faGlobe
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faGlobe
+)
+
+const LimitsTab = {
+ data () {},
+ components: {
+ BooleanSetting,
+ ChoiceSetting,
+ IntegerSetting,
+ StringSetting
+ },
+ computed: {
+ ...SharedComputedObject()
+ }
+}
+
+export default LimitsTab
diff --git a/src/components/settings_modal/admin_tabs/limits_tab.vue b/src/components/settings_modal/admin_tabs/limits_tab.vue
new file mode 100644
index 00000000..3f07c554
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/limits_tab.vue
@@ -0,0 +1,152 @@
+<template>
+ <div :label="$t('admin_dash.instance')">
+ <div class="setting-item">
+ <h2>{{ $t('admin_dash.arbitrary_limits') }}</h2>
+ <ul class="setting-list">
+ <li>
+ <h3>{{ $t('admin_dash.limits.posts') }}</h3>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:limit"
+ draft-mode
+ >
+ POST LIMIT
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:remote_limit"
+ draft-mode
+ >
+ POST LIMIT (remote)
+ </IntegerSetting>
+ </li>
+ <li>
+ <h3>{{ $t('admin_dash.limits.uploads') }}</h3>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:description_limit"
+ draft-mode
+ >
+ IMAGE DESCRIPTION LIMIT
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:upload_limit"
+ draft-mode
+ >
+ UPLOAD LIMIT KiB
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:max_media_attachments"
+ draft-mode
+ >
+ MAX ATTACHMENTS
+ </IntegerSetting>
+ </li>
+ <li>
+ <h3>{{ $t('admin_dash.limits.users') }}</h3>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:user_bio_length"
+ draft-mode
+ >
+ BIO LENGTH
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:user_name_length"
+ draft-mode
+ >
+ NAME LENGTH
+ </IntegerSetting>
+ </li>
+ <li>
+ <h4>{{ $t('admin_dash.limits.profile_fields') }}</h4>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:max_account_fields"
+ draft-mode
+ >
+ MAX ACCOUNT FIELDS
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:max_remote_account_fields"
+ draft-mode
+ >
+ MAX ACCOUNT FIELDS (remote)
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:account_field_name_length"
+ draft-mode
+ >
+ MAX ACCOUNT FIELD NAME
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:account_field_value_length"
+ draft-mode
+ >
+ MAX ACCOUNT VALUE NAME
+ </IntegerSetting>
+ </li>
+ <li>
+ <h4>{{ $t('admin_dash.limits.user_uploads') }}</h4>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:avatar_upload_limit"
+ draft-mode
+ >
+ MAX AVATAR SIZE KiB
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:banner_upload_limit"
+ draft-mode
+ >
+ MAX BANNER SIZE KiB
+ </IntegerSetting>
+ </li>
+ <li>
+ <IntegerSetting
+ source="admin"
+ path=":pleroma.:instance.:max_pinned_statuses"
+ draft-mode
+ >
+ MAX PINNED POSTS
+ </IntegerSetting>
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
+
+<script src="./limits_tab.js"></script>
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
index 2e6992cb..0df01d31 100644
--- a/src/components/settings_modal/helpers/boolean_setting.js
+++ b/src/components/settings_modal/helpers/boolean_setting.js
@@ -1,56 +1,16 @@
-import { get, set } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue'
-import ModifiedIndicator from './modified_indicator.vue'
-import ServerSideIndicator from './server_side_indicator.vue'
+import Setting from './setting.js'
+
export default {
+ ...Setting,
components: {
- Checkbox,
- ModifiedIndicator,
- ServerSideIndicator
- },
- props: [
- 'path',
- 'disabled',
- 'expert'
- ],
- computed: {
- pathDefault () {
- const [firstSegment, ...rest] = this.path.split('.')
- return [firstSegment + 'DefaultValue', ...rest].join('.')
- },
- state () {
- const value = get(this.$parent, this.path)
- if (value === undefined) {
- return this.defaultState
- } else {
- return value
- }
- },
- defaultState () {
- return get(this.$parent, this.pathDefault)
- },
- isServerSide () {
- return this.path.startsWith('serverSide_')
- },
- isChanged () {
- return !this.path.startsWith('serverSide_') && this.state !== this.defaultState
- },
- matchesExpertLevel () {
- return (this.expert || 0) <= this.$parent.expertLevel
- }
+ ...Setting.components,
+ Checkbox
},
methods: {
- update (e) {
- const [firstSegment, ...rest] = this.path.split('.')
- set(this.$parent, this.path, e)
- // Updating nested properties does not trigger update on its parent.
- // probably still not as reliable, but works for depth=1 at least
- if (rest.length > 0) {
- set(this.$parent, firstSegment, { ...get(this.$parent, firstSegment) })
- }
- },
- reset () {
- set(this.$parent, this.path, this.defaultState)
+ ...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
index 41142966..aedbf23e 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -4,22 +4,34 @@
class="BooleanSetting"
>
<Checkbox
- :model-value="state"
- :disabled="disabled"
+ :model-value="draftMode ? draft :state"
+ :disabled="shouldBeDisabled"
@update:modelValue="update"
>
<span
v-if="!!$slots.default"
class="label"
>
- <slot />
+ <template v-if="backendDescription">
+ {{ backendDescriptionLabel + ' ' }}
+ </template>
+ <template v-else>
+ <slot />
+ </template>
</span>
{{ ' ' }}
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
- <ServerSideIndicator :server-side="isServerSide" />
+ <ProfileSettingIndicator :is-profile="isProfileSetting" />
+ <DraftButtons />
+ <p
+ v-if="backendDescriptionDescription"
+ class="setting-description"
+ >
+ {{ backendDescriptionDescription + ' ' }}
+ </p>
</Checkbox>
</label>
</template>
diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
index 3da559fe..a3c3bf44 100644
--- a/src/components/settings_modal/helpers/choice_setting.js
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -1,51 +1,17 @@
-import { get, set } from 'lodash'
import Select from 'src/components/select/select.vue'
-import ModifiedIndicator from './modified_indicator.vue'
-import ServerSideIndicator from './server_side_indicator.vue'
+import Setting from './setting.js'
+
export default {
+ ...Setting,
components: {
- Select,
- ModifiedIndicator,
- ServerSideIndicator
+ ...Setting.components,
+ Select
},
- props: [
- 'path',
- 'disabled',
- 'options',
- 'expert'
- ],
- computed: {
- pathDefault () {
- const [firstSegment, ...rest] = this.path.split('.')
- return [firstSegment + 'DefaultValue', ...rest].join('.')
- },
- state () {
- const value = get(this.$parent, this.path)
- if (value === undefined) {
- return this.defaultState
- } else {
- return value
- }
- },
- defaultState () {
- return get(this.$parent, this.pathDefault)
- },
- isServerSide () {
- return this.path.startsWith('serverSide_')
- },
- isChanged () {
- return !this.path.startsWith('serverSide_') && this.state !== this.defaultState
- },
- matchesExpertLevel () {
- return (this.expert || 0) <= this.$parent.expertLevel
- }
- },
- methods: {
- update (e) {
- set(this.$parent, this.path, e)
- },
- reset () {
- set(this.$parent, this.path, this.defaultState)
+ props: {
+ ...Setting.props,
+ options: {
+ type: Array,
+ required: true
}
}
}
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 8fdbb5d3..4c4cdefe 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -23,7 +23,7 @@
:changed="isChanged"
:onclick="reset"
/>
- <ServerSideIndicator :server-side="isServerSide" />
+ <ProfileSettingIndicator :is-profile="isProfileSetting" />
</label>
</template>
diff --git a/src/components/settings_modal/helpers/draft_buttons.vue b/src/components/settings_modal/helpers/draft_buttons.vue
new file mode 100644
index 00000000..53ddc9b4
--- /dev/null
+++ 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>
+ &nbsp;
+ <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>
+ &nbsp;
+ <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>
+ &nbsp;
+ <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/number_setting.js b/src/components/settings_modal/helpers/number_setting.js
index 73c39948..676a0d22 100644
--- a/src/components/settings_modal/helpers/number_setting.js
+++ b/src/components/settings_modal/helpers/number_setting.js
@@ -1,56 +1,24 @@
-import { get, set } from 'lodash'
-import ModifiedIndicator from './modified_indicator.vue'
+import Setting from './setting.js'
+
export default {
- components: {
- ModifiedIndicator
- },
+ ...Setting,
props: {
- path: String,
- disabled: Boolean,
- min: Number,
- step: Number,
- truncate: Number,
- expert: [Number, String]
- },
- computed: {
- pathDefault () {
- const [firstSegment, ...rest] = this.path.split('.')
- return [firstSegment + 'DefaultValue', ...rest].join('.')
- },
- parent () {
- return this.$parent.$parent
- },
- state () {
- const value = get(this.parent, this.path)
- if (value === undefined) {
- return this.defaultState
- } else {
- return value
- }
- },
- defaultState () {
- return get(this.parent, this.pathDefault)
- },
- isChanged () {
- return this.state !== this.defaultState
- },
- matchesExpertLevel () {
- return (this.expert || 0) <= this.parent.expertLevel
+ ...Setting.props,
+ truncate: {
+ type: Number,
+ required: false,
+ default: 1
}
},
methods: {
- truncateValue (value) {
- if (!this.truncate) {
- return value
+ ...Setting.methods,
+ getValue (e) {
+ if (!this.truncate === 1) {
+ return parseInt(e.target.value)
+ } else if (this.truncate > 1) {
+ return Math.trunc(e.target.value / this.truncate) * this.truncate
}
-
- return Math.trunc(value / this.truncate) * this.truncate
- },
- update (e) {
- set(this.parent, this.path, this.truncateValue(parseFloat(e.target.value)))
- },
- reset () {
- set(this.parent, this.path, this.defaultState)
+ return parseFloat(e.target.value)
}
}
}
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index 3eab5178..81335762 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -13,7 +13,7 @@
:step="step || 1"
:disabled="disabled"
:min="min || 0"
- :value="state"
+ :value="draftMode ? draft :state"
@change="update"
>
{{ ' ' }}
diff --git a/src/components/settings_modal/helpers/server_side_indicator.vue b/src/components/settings_modal/helpers/profile_setting_indicator.vue
index bf181959..d160781b 100644
--- a/src/components/settings_modal/helpers/server_side_indicator.vue
+++ b/src/components/settings_modal/helpers/profile_setting_indicator.vue
@@ -1,7 +1,7 @@
<template>
<span
- v-if="serverSide"
- class="ServerSideIndicator"
+ v-if="isProfile"
+ class="ProfileSettingIndicator"
>
<Popover
trigger="hover"
@@ -14,7 +14,7 @@
/>
</template>
<template #content>
- <div class="serverside-tooltip">
+ <div class="profilesetting-tooltip">
{{ $t('settings.setting_server_side') }}
</div>
</template>
@@ -33,17 +33,17 @@ library.add(
export default {
components: { Popover },
- props: ['serverSide']
+ props: ['isProfile']
}
</script>
<style lang="scss">
-.ServerSideIndicator {
+.ProfileSettingIndicator {
display: inline-block;
position: relative;
}
-.serverside-tooltip {
+.profilesetting-tooltip {
margin: 0.5em 1em;
min-width: 10em;
text-align: center;
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
new file mode 100644
index 00000000..8c7074a5
--- /dev/null
+++ b/src/components/settings_modal/helpers/setting.js
@@ -0,0 +1,161 @@
+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,
+ required: true
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ parentPath: {
+ type: String
+ },
+ parentInvert: {
+ type: Boolean,
+ default: false
+ },
+ expert: {
+ type: [Number, String],
+ default: 0
+ },
+ source: {
+ type: String,
+ default: 'default'
+ },
+ draftMode: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data () {
+ return {
+ draft: null
+ }
+ },
+ created () {
+ if (this.draftMode) {
+ this.draft = this.state
+ }
+ },
+ computed: {
+ state () {
+ const value = get(this.configSource, this.path)
+ if (value === undefined) {
+ return this.defaultState
+ } else {
+ return value
+ }
+ },
+ backendDescription () {
+ return get(this.$store.state.adminSettings.descriptions, this.path)
+ },
+ backendDescriptionLabel () {
+ return this.backendDescription?.label
+ },
+ backendDescriptionDescription () {
+ return this.backendDescription?.description
+ },
+ shouldBeDisabled () {
+ const parentValue = this.parentPath !== undefined ? get(this.configSource, this.parentPath) : null
+ return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
+ },
+ configSource () {
+ switch (this.source) {
+ case 'profile':
+ return this.$store.state.profileConfig
+ case 'admin':
+ return this.$store.state.adminSettings.config
+ default:
+ return this.$store.getters.mergedConfig
+ }
+ },
+ configSink () {
+ switch (this.source) {
+ case 'profile':
+ return (k, v) => this.$store.dispatch('setProfileOption', { name: k, value: v })
+ case 'admin':
+ return (k, v) => this.$store.dispatch('pushAdminSetting', { path: k, value: v })
+ default:
+ return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
+ }
+ },
+ defaultState () {
+ switch (this.source) {
+ case 'profile':
+ return {}
+ default:
+ return get(this.$store.getters.defaultConfig, this.path)
+ }
+ },
+ isProfileSetting () {
+ return this.source === 'profile'
+ },
+ isChanged () {
+ switch (this.source) {
+ case 'profile':
+ case 'admin':
+ 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) {
+ 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 () {
+ 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/shared_computed_object.js b/src/components/settings_modal/helpers/shared_computed_object.js
index 12431dca..912999ce 100644
--- a/src/components/settings_modal/helpers/shared_computed_object.js
+++ b/src/components/settings_modal/helpers/shared_computed_object.js
@@ -1,52 +1,12 @@
-import { defaultState as configDefaultState } from 'src/modules/config.js'
-import { defaultState as serverSideConfigDefaultState } from 'src/modules/serverSideConfig.js'
-
const SharedComputedObject = () => ({
user () {
return this.$store.state.users.currentUser
},
- // Getting values for default properties
- ...Object.keys(configDefaultState)
- .map(key => [
- key + 'DefaultValue',
- function () {
- return this.$store.getters.defaultConfig[key]
- }
- ])
- .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
- // Generating computed values for vuex properties
- ...Object.keys(configDefaultState)
- .map(key => [key, {
- get () { return this.$store.getters.mergedConfig[key] },
- set (value) {
- this.$store.dispatch('setOption', { name: key, value })
- }
- }])
- .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
- ...Object.keys(serverSideConfigDefaultState)
- .map(key => ['serverSide_' + key, {
- get () { return this.$store.state.serverSideConfig[key] },
- set (value) {
- this.$store.dispatch('setServerSideOption', { name: key, value })
- }
- }])
- .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
- // Special cases (need to transform values or perform actions first)
- useStreamingApi: {
- get () { return this.$store.getters.mergedConfig.useStreamingApi },
- set (value) {
- const promise = value
- ? this.$store.dispatch('enableMastoSockets')
- : this.$store.dispatch('disableMastoSockets')
-
- promise.then(() => {
- this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
- }).catch((e) => {
- console.error('Failed starting MastoAPI Streaming socket', e)
- this.$store.dispatch('disableMastoSockets')
- this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
- })
- }
+ expertLevel () {
+ return this.$store.getters.mergedConfig.expertLevel > 0
+ },
+ mergedConfig () {
+ return this.$store.getters.mergedConfig
}
})
diff --git a/src/components/settings_modal/helpers/size_setting.js b/src/components/settings_modal/helpers/size_setting.js
index 58697412..12cef705 100644
--- a/src/components/settings_modal/helpers/size_setting.js
+++ b/src/components/settings_modal/helpers/size_setting.js
@@ -1,67 +1,40 @@
-import { get, set } from 'lodash'
-import ModifiedIndicator from './modified_indicator.vue'
import Select from 'src/components/select/select.vue'
+import Setting from './setting.js'
export const allCssUnits = ['cm', 'mm', 'in', 'px', 'pt', 'pc', 'em', 'ex', 'ch', 'rem', 'vw', 'vh', 'vmin', 'vmax', '%']
export const defaultHorizontalUnits = ['px', 'rem', 'vw']
export const defaultVerticalUnits = ['px', 'rem', 'vh']
export default {
+ ...Setting,
components: {
- ModifiedIndicator,
+ ...Setting.components,
Select
},
props: {
- path: String,
- disabled: Boolean,
+ ...Setting.props,
min: Number,
units: {
- type: [String],
+ type: Array,
default: () => allCssUnits
- },
- expert: [Number, String]
+ }
},
computed: {
- pathDefault () {
- const [firstSegment, ...rest] = this.path.split('.')
- return [firstSegment + 'DefaultValue', ...rest].join('.')
- },
+ ...Setting.computed,
stateUnit () {
- return (this.state || '').replace(/\d+/, '')
+ return this.state.replace(/\d+/, '')
},
stateValue () {
- return (this.state || '').replace(/\D+/, '')
- },
- state () {
- const value = get(this.$parent, this.path)
- if (value === undefined) {
- return this.defaultState
- } else {
- return value
- }
- },
- defaultState () {
- return get(this.$parent, this.pathDefault)
- },
- isChanged () {
- return this.state !== this.defaultState
- },
- matchesExpertLevel () {
- return (this.expert || 0) <= this.$parent.expertLevel
+ return this.state.replace(/\D+/, '')
}
},
methods: {
- update (e) {
- set(this.$parent, this.path, e)
- },
- reset () {
- set(this.$parent, this.path, this.defaultState)
- },
+ ...Setting.methods,
updateValue (e) {
- set(this.$parent, this.path, parseInt(e.target.value) + this.stateUnit)
+ this.configSink(this.path, parseInt(e.target.value) + this.stateUnit)
},
updateUnit (e) {
- set(this.$parent, this.path, this.stateValue + e.target.value)
+ this.configSink(this.path, this.stateValue + e.target.value)
}
}
}
diff --git a/src/components/settings_modal/helpers/string_setting.js b/src/components/settings_modal/helpers/string_setting.js
new file mode 100644
index 00000000..b368cfc8
--- /dev/null
+++ b/src/components/settings_modal/helpers/string_setting.js
@@ -0,0 +1,5 @@
+import Setting from './setting.js'
+
+export default {
+ ...Setting
+}
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
new file mode 100644
index 00000000..91a4afa4
--- /dev/null
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -0,0 +1,38 @@
+<template>
+ <label
+ v-if="matchesExpertLevel"
+ class="StringSetting"
+ >
+ <label :for="path">
+ <template v-if="backendDescription">
+ {{ backendDescriptionLabel + ' ' }}
+ </template>
+ <template v-else>
+ <slot />
+ </template>
+ </label>
+ <input
+ :id="path"
+ class="string-input"
+ step="1"
+ :disabled="disabled"
+ :value="draftMode ? draft :state"
+ @change="update"
+ >
+ {{ ' ' }}
+ <ModifiedIndicator
+ :changed="isChanged"
+ :onclick="reset"
+ />
+ <ProfileSettingIndicator :is-profile="isProfileSetting" />
+ <DraftButtons />
+ <p
+ v-if="backendDescriptionDescription"
+ class="setting-description"
+ >
+ {{ backendDescriptionDescription + ' ' }}
+ </p>
+ </label>
+</template>
+
+<script src="./string_setting.js"></script>
diff --git a/src/components/settings_modal/settings_modal.js b/src/components/settings_modal/settings_modal.js
index 0a72dca1..e033d999 100644
--- a/src/components/settings_modal/settings_modal.js
+++ b/src/components/settings_modal/settings_modal.js
@@ -53,8 +53,16 @@ const SettingsModal = {
Modal,
Popover,
Checkbox,
- SettingsModalContent: getResettableAsyncComponent(
- () => import('./settings_modal_content.vue'),
+ SettingsModalUserContent: getResettableAsyncComponent(
+ () => import('./settings_modal_user_content.vue'),
+ {
+ loadingComponent: PanelLoading,
+ errorComponent: AsyncComponentError,
+ delay: 0
+ }
+ ),
+ SettingsModalAdminContent: getResettableAsyncComponent(
+ () => import('./settings_modal_admin_content.vue'),
{
loadingComponent: PanelLoading,
errorComponent: AsyncComponentError,
@@ -156,8 +164,14 @@ const SettingsModal = {
modalActivated () {
return this.$store.state.interface.settingsModalState !== 'hidden'
},
- modalOpenedOnce () {
- return this.$store.state.interface.settingsModalLoaded
+ modalMode () {
+ return this.$store.state.interface.settingsModalMode
+ },
+ modalOpenedOnceUser () {
+ return this.$store.state.interface.settingsModalLoadedUser
+ },
+ modalOpenedOnceAdmin () {
+ return this.$store.state.interface.settingsModalLoadedAdmin
},
modalPeeked () {
return this.$store.state.interface.settingsModalState === 'minimized'
@@ -167,7 +181,6 @@ const SettingsModal = {
return this.$store.state.config.expertLevel > 0
},
set (value) {
- console.log(value)
this.$store.dispatch('setOption', { name: 'expertLevel', value: value ? 1 : 0 })
}
}
diff --git a/src/components/settings_modal/settings_modal.scss b/src/components/settings_modal/settings_modal.scss
index f5861229..4cce6099 100644
--- a/src/components/settings_modal/settings_modal.scss
+++ b/src/components/settings_modal/settings_modal.scss
@@ -17,6 +17,12 @@
}
}
+ .setting-description {
+ margin-top: 0.2em;
+ margin-bottom: 2em;
+ font-size: 70%;
+ }
+
.settings-modal-panel {
overflow: hidden;
transition: transform;
diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue
index 7b457371..73e1524a 100644
--- a/src/components/settings_modal/settings_modal.vue
+++ b/src/components/settings_modal/settings_modal.vue
@@ -42,7 +42,8 @@
</button>
</div>
<div class="panel-body">
- <SettingsModalContent v-if="modalOpenedOnce" />
+ <SettingsModalUserContent v-if="modalMode === 'user' && modalOpenedOnceUser" />
+ <SettingsModalAdminContent v-if="modalMode === 'admin' && modalOpenedOnceAdmin" />
</div>
<div class="panel-footer settings-footer">
<Popover
diff --git a/src/components/settings_modal/settings_modal_admin_content.js b/src/components/settings_modal/settings_modal_admin_content.js
new file mode 100644
index 00000000..c6c8837f
--- /dev/null
+++ b/src/components/settings_modal/settings_modal_admin_content.js
@@ -0,0 +1,78 @@
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
+
+import DataImportExportTab from './tabs/data_import_export_tab.vue'
+import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
+import InstanceTab from './admin_tabs/instance_tab.vue'
+import LimitsTab from './admin_tabs/limits_tab.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faWrench,
+ faUser,
+ faFilter,
+ faPaintBrush,
+ faBell,
+ faDownload,
+ faEyeSlash,
+ faInfo
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faWrench,
+ faUser,
+ faFilter,
+ faPaintBrush,
+ faBell,
+ faDownload,
+ faEyeSlash,
+ faInfo
+)
+
+const SettingsModalAdminContent = {
+ components: {
+ TabSwitcher,
+
+ DataImportExportTab,
+ MutesAndBlocksTab,
+ InstanceTab,
+ LimitsTab
+ },
+ computed: {
+ isLoggedIn () {
+ return !!this.$store.state.users.currentUser
+ },
+ open () {
+ return this.$store.state.interface.settingsModalState !== 'hidden'
+ },
+ bodyLock () {
+ return this.$store.state.interface.settingsModalState === 'visible'
+ }
+ },
+ methods: {
+ onOpen () {
+ const targetTab = this.$store.state.interface.settingsModalTargetTab
+ // We're being told to open in specific tab
+ if (targetTab) {
+ const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
+ return elm.props && elm.props['data-tab-name'] === targetTab
+ })
+ if (tabIndex >= 0) {
+ this.$refs.tabSwitcher.setTab(tabIndex)
+ }
+ }
+ // Clear the state of target tab, so that next time settings is opened
+ // it doesn't force it.
+ this.$store.dispatch('clearSettingsModalTargetTab')
+ }
+ },
+ mounted () {
+ this.onOpen()
+ },
+ watch: {
+ open: function (value) {
+ if (value) this.onOpen()
+ }
+ }
+}
+
+export default SettingsModalAdminContent
diff --git a/src/components/settings_modal/settings_modal_content.scss b/src/components/settings_modal/settings_modal_admin_content.scss
index 87df7982..87df7982 100644
--- a/src/components/settings_modal/settings_modal_content.scss
+++ b/src/components/settings_modal/settings_modal_admin_content.scss
diff --git a/src/components/settings_modal/settings_modal_admin_content.vue b/src/components/settings_modal/settings_modal_admin_content.vue
new file mode 100644
index 00000000..16b55828
--- /dev/null
+++ b/src/components/settings_modal/settings_modal_admin_content.vue
@@ -0,0 +1,28 @@
+<template>
+ <tab-switcher
+ ref="tabSwitcher"
+ class="settings_tab-switcher"
+ :side-tab-bar="true"
+ :scrollable-tabs="true"
+ :body-scroll-lock="bodyLock"
+ >
+ <div
+ :label="$t('admin_dash.instance')"
+ icon="wrench"
+ data-tab-name="general"
+ >
+ <InstanceTab />
+ </div>
+ <div
+ :label="$t('admin_dash.limits')"
+ icon="wrench"
+ data-tab-name="limits"
+ >
+ <LimitsTab />
+ </div>
+ </tab-switcher>
+</template>
+
+<script src="./settings_modal_admin_content.js"></script>
+
+<style src="./settings_modal_admin_content.scss" lang="scss"></style>
diff --git a/src/components/settings_modal/settings_modal_content.js b/src/components/settings_modal/settings_modal_user_content.js
index 9ac0301f..9ac0301f 100644
--- a/src/components/settings_modal/settings_modal_content.js
+++ b/src/components/settings_modal/settings_modal_user_content.js
diff --git a/src/components/settings_modal/settings_modal_user_content.scss b/src/components/settings_modal/settings_modal_user_content.scss
new file mode 100644
index 00000000..87df7982
--- /dev/null
+++ b/src/components/settings_modal/settings_modal_user_content.scss
@@ -0,0 +1,56 @@
+@import "src/variables";
+
+.settings_tab-switcher {
+ height: 100%;
+
+ .setting-item {
+ border-bottom: 2px solid var(--fg, $fallback--fg);
+ margin: 1em 1em 1.4em;
+ padding-bottom: 1.4em;
+
+ > div,
+ > label {
+ display: block;
+ margin-bottom: 0.5em;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .select-multiple {
+ display: flex;
+
+ .option-list {
+ margin: 0;
+ padding-left: 0.5em;
+ }
+ }
+
+ &:last-child {
+ border-bottom: none;
+ padding-bottom: 0;
+ margin-bottom: 1em;
+ }
+
+ select {
+ min-width: 10em;
+ }
+
+ textarea {
+ width: 100%;
+ max-width: 100%;
+ height: 100px;
+ }
+
+ .unavailable,
+ .unavailable svg {
+ color: var(--cRed, $fallback--cRed);
+ color: $fallback--cRed;
+ }
+
+ .number-input {
+ max-width: 6em;
+ }
+ }
+}
diff --git a/src/components/settings_modal/settings_modal_content.vue b/src/components/settings_modal/settings_modal_user_content.vue
index 0be76d22..0221cccb 100644
--- a/src/components/settings_modal/settings_modal_content.vue
+++ b/src/components/settings_modal/settings_modal_user_content.vue
@@ -78,6 +78,6 @@
</tab-switcher>
</template>
-<script src="./settings_modal_content.js"></script>
+<script src="./settings_modal_user_content.js"></script>
-<style src="./settings_modal_content.scss" lang="scss"></style>
+<style src="./settings_modal_user_content.scss" lang="scss"></style>
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 97046ff0..41d1b54f 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -7,13 +7,11 @@
<BooleanSetting path="hideFilteredStatuses">
{{ $t('settings.hide_filtered_statuses') }}
</BooleanSetting>
- <ul
- class="setting-list suboptions"
- :class="[{disabled: !streaming}]"
- >
+ <ul class="setting-list suboptions">
<li>
<BooleanSetting
- :disabled="hideFilteredStatuses"
+ parent-path="hideFilteredStatuses"
+ :parent-invert="true"
path="hideWordFilteredPosts"
>
{{ $t('settings.hide_wordfiltered_statuses') }}
@@ -22,7 +20,8 @@
<li>
<BooleanSetting
v-if="user"
- :disabled="hideFilteredStatuses"
+ parent-path="hideFilteredStatuses"
+ :parent-invert="true"
path="hideMutedThreads"
>
{{ $t('settings.hide_muted_threads') }}
@@ -31,7 +30,8 @@
<li>
<BooleanSetting
v-if="user"
- :disabled="hideFilteredStatuses"
+ parent-path="hideFilteredStatuses"
+ :parent-invert="true"
path="hideMutedPosts"
>
{{ $t('settings.hide_muted_posts') }}
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index be97710f..3f2bcb13 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -7,7 +7,7 @@ import SizeSetting, { defaultHorizontalUnits } from '../helpers/size_setting.vue
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
-import ServerSideIndicator from '../helpers/server_side_indicator.vue'
+import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faGlobe
@@ -67,7 +67,7 @@ const GeneralTab = {
SizeSetting,
InterfaceLanguageSwitcher,
ScopeSelector,
- ServerSideIndicator
+ ProfileSettingIndicator
},
computed: {
horizontalUnits () {
@@ -110,7 +110,7 @@ const GeneralTab = {
},
methods: {
changeDefaultScope (value) {
- this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
+ this.$store.dispatch('setProfileOption', { name: 'defaultScope', value })
}
}
}
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 21e2d855..f56fa8e0 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -29,14 +29,11 @@
<BooleanSetting path="streaming">
{{ $t('settings.streaming') }}
</BooleanSetting>
- <ul
- class="setting-list suboptions"
- :class="[{disabled: !streaming}]"
- >
+ <ul class="setting-list suboptions">
<li>
<BooleanSetting
path="pauseOnUnfocused"
- :disabled="!streaming"
+ parent-path="streaming"
>
{{ $t('settings.pause_on_unfocused') }}
</BooleanSetting>
@@ -213,7 +210,7 @@
</ChoiceSetting>
</li>
<ul
- v-if="conversationDisplay !== 'linear'"
+ v-if="mergedConfig.conversationDisplay !== 'linear'"
class="setting-list suboptions"
>
<li>
@@ -265,7 +262,8 @@
<li>
<BooleanSetting
v-if="user"
- path="serverSide_stripRichContent"
+ source="profile"
+ path="stripRichContent"
expert="1"
>
{{ $t('settings.no_rich_text_description') }}
@@ -299,7 +297,7 @@
<BooleanSetting
path="preloadImage"
expert="1"
- :disabled="!hideNsfw"
+ parent-path="hideNsfw"
>
{{ $t('settings.preload_images') }}
</BooleanSetting>
@@ -308,7 +306,7 @@
<BooleanSetting
path="useOneClickNsfw"
expert="1"
- :disabled="!hideNsfw"
+ parent-path="hideNsfw"
>
{{ $t('settings.use_one_click_nsfw') }}
</BooleanSetting>
@@ -321,15 +319,13 @@
>
{{ $t('settings.loop_video') }}
</BooleanSetting>
- <ul
- class="setting-list suboptions"
- :class="[{disabled: !streaming}]"
- >
+ <ul class="setting-list suboptions">
<li>
<BooleanSetting
path="loopVideoSilentOnly"
expert="1"
- :disabled="!loopVideo || !loopSilentAvailable"
+ parent-path="loopVideo"
+ :disabled="!loopSilentAvailable"
>
{{ $t('settings.loop_video_silent_only') }}
</BooleanSetting>
@@ -427,18 +423,18 @@
<ul class="setting-list">
<li>
<label for="default-vis">
- {{ $t('settings.default_vis') }} <ServerSideIndicator :server-side="true" />
+ {{ $t('settings.default_vis') }} <ProfileSettingIndicator :is-profile="true" />
<ScopeSelector
class="scope-selector"
:show-all="true"
- :user-default="serverSide_defaultScope"
- :initial-scope="serverSide_defaultScope"
+ :user-default="$store.state.profileConfig.defaultScope"
+ :initial-scope="$store.state.profileConfig.defaultScope"
:on-scope-change="changeDefaultScope"
/>
</label>
</li>
<li>
- <!-- <BooleanSetting path="serverSide_defaultNSFW"> -->
+ <!-- <BooleanSetting source="profile" path="defaultNSFW"> -->
<BooleanSetting path="sensitiveByDefault">
{{ $t('settings.sensitive_by_default') }}
</BooleanSetting>
diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue
index dd3806ed..fcb92135 100644
--- a/src/components/settings_modal/tabs/notifications_tab.vue
+++ b/src/components/settings_modal/tabs/notifications_tab.vue
@@ -4,7 +4,10 @@
<h2>{{ $t('settings.notification_setting_filters') }}</h2>
<ul class="setting-list">
<li>
- <BooleanSetting path="serverSide_blockNotificationsFromStrangers">
+ <BooleanSetting
+ source="profile"
+ path="blockNotificationsFromStrangers"
+ >
{{ $t('settings.notification_setting_block_from_strangers') }}
</BooleanSetting>
</li>
@@ -67,7 +70,8 @@
</li>
<li>
<BooleanSetting
- path="serverSide_webPushHideContents"
+ source="profile"
+ path="webPushHideContents"
expert="1"
>
{{ $t('settings.notification_setting_hide_notification_contents') }}
diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue
index 6a5b478a..1cc850cb 100644
--- a/src/components/settings_modal/tabs/profile_tab.vue
+++ b/src/components/settings_modal/tabs/profile_tab.vue
@@ -254,37 +254,50 @@
<h2>{{ $t('settings.account_privacy') }}</h2>
<ul class="setting-list">
<li>
- <BooleanSetting path="serverSide_locked">
+ <BooleanSetting
+ source="profile"
+ path="locked"
+ >
{{ $t('settings.lock_account_description') }}
</BooleanSetting>
</li>
<li>
- <BooleanSetting path="serverSide_discoverable">
+ <BooleanSetting
+ source="profile"
+ path="discoverable"
+ >
{{ $t('settings.discoverable') }}
</BooleanSetting>
</li>
<li>
- <BooleanSetting path="serverSide_allowFollowingMove">
+ <BooleanSetting
+ source="profile"
+ path="allowFollowingMove"
+ >
{{ $t('settings.allow_following_move') }}
</BooleanSetting>
</li>
<li>
- <BooleanSetting path="serverSide_hideFavorites">
+ <BooleanSetting
+ source="profile"
+ path="hideFavorites"
+ >
{{ $t('settings.hide_favorites_description') }}
</BooleanSetting>
</li>
<li>
- <BooleanSetting path="serverSide_hideFollowers">
+ <BooleanSetting
+ source="profile"
+ path="hideFollowers"
+ >
{{ $t('settings.hide_followers_description') }}
</BooleanSetting>
- <ul
- class="setting-list suboptions"
- :class="[{disabled: !serverSide_hideFollowers}]"
- >
+ <ul class="setting-list suboptions">
<li>
<BooleanSetting
- path="serverSide_hideFollowersCount"
- :disabled="!serverSide_hideFollowers"
+ source="profile"
+ path="hideFollowersCount"
+ parent-path="hideFollowers"
>
{{ $t('settings.hide_followers_count_description') }}
</BooleanSetting>
@@ -292,17 +305,18 @@
</ul>
</li>
<li>
- <BooleanSetting path="serverSide_hideFollows">
+ <BooleanSetting
+ source="profile"
+ path="hideFollows"
+ >
{{ $t('settings.hide_follows_description') }}
</BooleanSetting>
- <ul
- class="setting-list suboptions"
- :class="[{disabled: !serverSide_hideFollows}]"
- >
+ <ul class="setting-list suboptions">
<li>
<BooleanSetting
- path="serverSide_hideFollowsCount"
- :disabled="!serverSide_hideFollows"
+ source="profile"
+ path="hideFollowsCount"
+ parent-path="hideFollows"
>
{{ $t('settings.hide_follows_count_description') }}
</BooleanSetting>
diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.vue b/src/components/settings_modal/tabs/security_tab/security_tab.vue
index 6e03bef4..d36d478f 100644
--- a/src/components/settings_modal/tabs/security_tab/security_tab.vue
+++ b/src/components/settings_modal/tabs/security_tab/security_tab.vue
@@ -143,8 +143,8 @@
/>
</div>
<div>
- <i18n
- path="settings.new_alias_target"
+ <i18n-t
+ keypath="settings.new_alias_target"
tag="p"
>
<code
@@ -152,7 +152,7 @@
>
foo@example.org
</code>
- </i18n>
+ </i18n-t>
<input
v-model="addAliasTarget"
>
@@ -175,16 +175,16 @@
<h2>{{ $t('settings.move_account') }}</h2>
<p>{{ $t('settings.move_account_notes') }}</p>
<div>
- <i18n
- path="settings.move_account_target"
+ <i18n-t
+ keypath="settings.move_account_target"
tag="p"
>
- <code
- place="example"
- >
- foo@example.org
- </code>
- </i18n>
+ <template #example>
+ <code>
+ foo@example.org
+ </code>
+ </template>
+ </i18n-t>
<input
v-model="moveAccountTarget"
>
diff --git a/src/components/tab_switcher/tab_switcher.jsx b/src/components/tab_switcher/tab_switcher.jsx
index a7ef8560..b444da43 100644
--- a/src/components/tab_switcher/tab_switcher.jsx
+++ b/src/components/tab_switcher/tab_switcher.jsx
@@ -60,13 +60,7 @@ export default {
const isWanted = slot => slot.props && slot.props['data-tab-name'] === tabName
return this.$slots.default().findIndex(isWanted) === this.activeIndex
}
- },
- settingsModalVisible () {
- return this.settingsModalState === 'visible'
- },
- ...mapState({
- settingsModalState: state => state.interface.settingsModalState
- })
+ }
},
beforeUpdate () {
const currentSlot = this.slots()[this.active]
diff --git a/src/main.js b/src/main.js
index d3e60a0f..71f19a82 100644
--- a/src/main.js
+++ b/src/main.js
@@ -10,8 +10,9 @@ import listsModule from './modules/lists.js'
import usersModule from './modules/users.js'
import apiModule from './modules/api.js'
import configModule from './modules/config.js'
-import serverSideConfigModule from './modules/serverSideConfig.js'
+import profileConfigModule from './modules/profileConfig.js'
import serverSideStorageModule from './modules/serverSideStorage.js'
+import adminSettingsModule from './modules/adminSettings.js'
import shoutModule from './modules/shout.js'
import oauthModule from './modules/oauth.js'
import authFlowModule from './modules/auth_flow.js'
@@ -80,8 +81,9 @@ const persistedStateOptions = {
lists: listsModule,
api: apiModule,
config: configModule,
- serverSideConfig: serverSideConfigModule,
+ profileConfig: profileConfigModule,
serverSideStorage: serverSideStorageModule,
+ adminSettings: adminSettingsModule,
shout: shoutModule,
oauth: oauthModule,
authFlow: authFlowModule,
diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js
new file mode 100644
index 00000000..44a4d409
--- /dev/null
+++ b/src/modules/adminSettings.js
@@ -0,0 +1,115 @@
+import { set, cloneDeep } from 'lodash'
+
+export const defaultState = {
+ needsReboot: null,
+ config: null,
+ modifiedPaths: null,
+ descriptions: null
+}
+
+export const newUserFlags = {
+ ...defaultState.flagStorage
+}
+
+const adminSettingsStorage = {
+ state: {
+ ...cloneDeep(defaultState)
+ },
+ mutations: {
+ updateAdminSettings (state, { config, modifiedPaths }) {
+ state.config = config
+ state.modifiedPaths = modifiedPaths
+ },
+ updateAdminDescriptions (state, { descriptions }) {
+ state.descriptions = descriptions
+ }
+ },
+ actions: {
+ setInstanceAdminSettings ({ state, commit, dispatch }, { backendDbConfig }) {
+ const config = state.config || {}
+ const modifiedPaths = state.modifiedPaths || new Set()
+ backendDbConfig.configs.forEach(c => {
+ const path = c.group + '.' + c.key
+ if (c.db) {
+ c.db.forEach(x => modifiedPaths.add(path + '.' + x))
+ }
+ const convert = (value) => {
+ if (Array.isArray(value) && value.length > 0 && value[0].tuple) {
+ return value.reduce((acc, c) => {
+ return { ...acc, [c.tuple[0]]: convert(c.tuple[1]) }
+ }, {})
+ } else {
+ return value
+ }
+ }
+ set(config, path, convert(c.value))
+ })
+ console.log(config[':pleroma'][':welcome'])
+ commit('updateAdminSettings', { config, modifiedPaths })
+ },
+ setInstanceAdminDescriptions ({ state, commit, dispatch }, { backendDescriptions }) {
+ const convert = ({ children, description, label, key = '<ROOT>', group, suggestions }, path, acc) => {
+ const newPath = group ? group + '.' + key : key
+ const obj = { description, label, suggestions }
+ if (Array.isArray(children)) {
+ children.forEach(c => {
+ convert(c, '.' + newPath, obj)
+ })
+ }
+ set(acc, newPath, obj)
+ }
+
+ const descriptions = {}
+ backendDescriptions.forEach(d => convert(d, '', descriptions))
+ commit('updateAdminDescriptions', { descriptions })
+ },
+ 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 }) {
+ 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 }))
+ }
+ }
+}
+
+export default adminSettingsStorage
diff --git a/src/modules/config.js b/src/modules/config.js
index 7597886e..56f8cba5 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -1,6 +1,7 @@
import Cookies from 'js-cookie'
import { setPreset, applyTheme, applyConfig } from '../services/style_setter/style_setter.js'
import messages from '../i18n/messages'
+import { set } from 'lodash'
import localeService from '../services/locale/locale.service.js'
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
@@ -148,7 +149,7 @@ const config = {
},
mutations: {
setOption (state, { name, value }) {
- state[name] = value
+ set(state, name, value)
},
setHighlight (state, { user, color, type }) {
const data = this.state.config.highlight[user]
@@ -178,32 +179,52 @@ const config = {
commit('setHighlight', { user, color, type })
},
setOption ({ commit, dispatch, state }, { name, value }) {
- commit('setOption', { name, value })
- switch (name) {
- case 'theme':
- setPreset(value)
- break
- case 'sidebarColumnWidth':
- case 'contentColumnWidth':
- case 'notifsColumnWidth':
- case 'emojiReactionsScale':
- applyConfig(state)
- break
- case 'customTheme':
- case 'customThemeSource':
- applyTheme(value)
- break
- case 'interfaceLanguage':
- messages.setLanguage(this.getters.i18n, value)
- dispatch('loadUnicodeEmojiData', value)
- Cookies.set(
- BACKEND_LANGUAGE_COOKIE_NAME,
- localeService.internalToBackendLocaleMulti(value)
- )
- break
- case 'thirdColumnMode':
- dispatch('setLayoutWidth', undefined)
- break
+ const exceptions = new Set([
+ 'useStreamingApi'
+ ])
+
+ if (exceptions.has(name)) {
+ switch (name) {
+ case 'useStreamingApi': {
+ const action = value ? 'enableMastoSockets' : 'disableMastoSockets'
+
+ dispatch(action).then(() => {
+ commit('setOption', { name: 'useStreamingApi', value })
+ }).catch((e) => {
+ console.error('Failed starting MastoAPI Streaming socket', e)
+ dispatch('disableMastoSockets')
+ dispatch('setOption', { name: 'useStreamingApi', value: false })
+ })
+ }
+ }
+ } else {
+ commit('setOption', { name, value })
+ switch (name) {
+ case 'theme':
+ setPreset(value)
+ break
+ case 'sidebarColumnWidth':
+ case 'contentColumnWidth':
+ case 'notifsColumnWidth':
+ case 'emojiReactionsScale':
+ applyConfig(state)
+ break
+ case 'customTheme':
+ case 'customThemeSource':
+ applyTheme(value)
+ break
+ case 'interfaceLanguage':
+ messages.setLanguage(this.getters.i18n, value)
+ dispatch('loadUnicodeEmojiData', value)
+ Cookies.set(
+ BACKEND_LANGUAGE_COOKIE_NAME,
+ localeService.internalToBackendLocaleMulti(value)
+ )
+ break
+ case 'thirdColumnMode':
+ dispatch('setLayoutWidth', undefined)
+ break
+ }
}
}
}
diff --git a/src/modules/interface.js b/src/modules/interface.js
index a86193ea..2d012f1b 100644
--- a/src/modules/interface.js
+++ b/src/modules/interface.js
@@ -1,7 +1,9 @@
const defaultState = {
settingsModalState: 'hidden',
- settingsModalLoaded: false,
+ settingsModalLoadedUser: false,
+ settingsModalLoadedAdmin: false,
settingsModalTargetTab: null,
+ settingsModalMode: 'user',
settings: {
currentSaveStateNotice: null,
noticeClearTimeout: null,
@@ -54,10 +56,17 @@ const interfaceMod = {
throw new Error('Illegal minimization state of settings modal')
}
},
- openSettingsModal (state) {
+ openSettingsModal (state, value) {
+ state.settingsModalMode = value
state.settingsModalState = 'visible'
- if (!state.settingsModalLoaded) {
- state.settingsModalLoaded = true
+ if (value === 'user') {
+ if (!state.settingsModalLoadedUser) {
+ state.settingsModalLoadedUser = true
+ }
+ } else if (value === 'admin') {
+ if (!state.settingsModalLoadedAdmin) {
+ state.settingsModalLoadedAdmin = true
+ }
}
},
setSettingsModalTargetTab (state, value) {
@@ -92,8 +101,8 @@ const interfaceMod = {
closeSettingsModal ({ commit }) {
commit('closeSettingsModal')
},
- openSettingsModal ({ commit }) {
- commit('openSettingsModal')
+ openSettingsModal ({ commit }, value = 'user') {
+ commit('openSettingsModal', value)
},
togglePeekSettingsModal ({ commit }) {
commit('togglePeekSettingsModal')
diff --git a/src/modules/serverSideConfig.js b/src/modules/profileConfig.js
index 476263bc..2cb2014a 100644
--- a/src/modules/serverSideConfig.js
+++ b/src/modules/profileConfig.js
@@ -22,9 +22,9 @@ const notificationsApi = ({ rootState, commit }, { path, value, oldValue }) => {
.updateNotificationSettings({ settings })
.then(result => {
if (result.status === 'success') {
- commit('confirmServerSideOption', { name, value })
+ commit('confirmProfileOption', { name, value })
} else {
- commit('confirmServerSideOption', { name, value: oldValue })
+ commit('confirmProfileOption', { name, value: oldValue })
}
})
}
@@ -94,16 +94,16 @@ export const settingsMap = {
export const defaultState = Object.fromEntries(Object.keys(settingsMap).map(key => [key, null]))
-const serverSideConfig = {
+const profileConfig = {
state: { ...defaultState },
mutations: {
- confirmServerSideOption (state, { name, value }) {
+ confirmProfileOption (state, { name, value }) {
set(state, name, value)
},
- wipeServerSideOption (state, { name }) {
+ wipeProfileOption (state, { name }) {
set(state, name, null)
},
- wipeAllServerSideOptions (state) {
+ wipeAllProfileOptions (state) {
Object.keys(settingsMap).forEach(key => {
set(state, key, null)
})
@@ -118,23 +118,23 @@ const serverSideConfig = {
}
},
actions: {
- setServerSideOption ({ rootState, state, commit, dispatch }, { name, value }) {
+ setProfileOption ({ rootState, state, commit, dispatch }, { name, value }) {
const oldValue = get(state, name)
const map = settingsMap[name]
if (!map) throw new Error('Invalid server-side setting')
const { set: path = map, api = defaultApi } = map
- commit('wipeServerSideOption', { name })
+ commit('wipeProfileOption', { name })
api({ rootState, commit }, { path, value, oldValue })
.catch((e) => {
console.warn('Error setting server-side option:', e)
- commit('confirmServerSideOption', { name, value: oldValue })
+ commit('confirmProfileOption', { name, value: oldValue })
})
},
logout ({ commit }) {
- commit('wipeAllServerSideOptions')
+ commit('wipeAllProfileOptions')
}
}
}
-export default serverSideConfig
+export default profileConfig
diff --git a/src/modules/users.js b/src/modules/users.js
index a1316ba2..45cba334 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -551,6 +551,7 @@ const users = {
loginUser (store, accessToken) {
return new Promise((resolve, reject) => {
const commit = store.commit
+ const dispatch = store.dispatch
commit('beginLogin')
store.rootState.api.backendInteractor.verifyCredentials(accessToken)
.then((data) => {
@@ -563,59 +564,65 @@ const users = {
user.domainMutes = []
commit('setCurrentUser', user)
commit('setServerSideStorage', user)
+ if (user.rights.admin) {
+ store.rootState.api.backendInteractor.fetchInstanceDBConfig()
+ .then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
+ store.rootState.api.backendInteractor.fetchInstanceConfigDescriptions()
+ .then(backendDescriptions => dispatch('setInstanceAdminDescriptions', { backendDescriptions }))
+ }
commit('addNewUsers', [user])
- store.dispatch('fetchEmoji')
+ dispatch('fetchEmoji')
getNotificationPermission()
.then(permission => commit('setNotificationPermission', permission))
// Set our new backend interactor
commit('setBackendInteractor', backendInteractorService(accessToken))
- store.dispatch('pushServerSideStorage')
+ dispatch('pushServerSideStorage')
if (user.token) {
- store.dispatch('setWsToken', user.token)
+ dispatch('setWsToken', user.token)
// Initialize the shout socket.
- store.dispatch('initializeSocket')
+ dispatch('initializeSocket')
}
const startPolling = () => {
// Start getting fresh posts.
- store.dispatch('startFetchingTimeline', { timeline: 'friends' })
+ dispatch('startFetchingTimeline', { timeline: 'friends' })
// Start fetching notifications
- store.dispatch('startFetchingNotifications')
+ dispatch('startFetchingNotifications')
// Start fetching chats
- store.dispatch('startFetchingChats')
+ dispatch('startFetchingChats')
}
- store.dispatch('startFetchingLists')
+ dispatch('startFetchingLists')
if (user.locked) {
- store.dispatch('startFetchingFollowRequests')
+ dispatch('startFetchingFollowRequests')
}
if (store.getters.mergedConfig.useStreamingApi) {
- store.dispatch('fetchTimeline', { timeline: 'friends', since: null })
- store.dispatch('fetchNotifications', { since: null })
- store.dispatch('enableMastoSockets', true).catch((error) => {
+ dispatch('fetchTimeline', { timeline: 'friends', since: null })
+ dispatch('fetchNotifications', { since: null })
+ dispatch('enableMastoSockets', true).catch((error) => {
console.error('Failed initializing MastoAPI Streaming socket', error)
}).then(() => {
- store.dispatch('fetchChats', { latest: true })
- setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000)
+ dispatch('fetchChats', { latest: true })
+ setTimeout(() => dispatch('setNotificationsSilence', false), 10000)
})
} else {
startPolling()
}
// Get user mutes
- store.dispatch('fetchMutes')
+ dispatch('fetchMutes')
- store.dispatch('setLayoutWidth', windowWidth())
- store.dispatch('setLayoutHeight', windowHeight())
+ dispatch('setLayoutWidth', windowWidth())
+ dispatch('setLayoutHeight', windowHeight())
// Fetch our friends
store.rootState.api.backendInteractor.fetchFriends({ id: user.id })
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index b8c10b21..073f40a3 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -108,6 +108,9 @@ 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/pleroma/admin/config'
+const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions'
+
const oldfetch = window.fetch
const fetch = (url, options) => {
@@ -1659,6 +1662,58 @@ const setReportState = ({ id, state, credentials }) => {
})
}
+// ADMIN STUFF // EXPERIMENTAL
+const fetchInstanceDBConfig = ({ credentials }) => {
+ return fetch(PLEROMA_ADMIN_CONFIG_URL, {
+ headers: authHeaders(credentials)
+ })
+ .then((response) => {
+ if (response.ok) {
+ return response.json()
+ } else {
+ return {
+ error: response
+ }
+ }
+ })
+}
+
+const fetchInstanceConfigDescriptions = ({ credentials }) => {
+ return fetch(PLEROMA_ADMIN_DESCRIPTIONS_URL, {
+ headers: authHeaders(credentials)
+ })
+ .then((response) => {
+ if (response.ok) {
+ return response.json()
+ } else {
+ return {
+ error: response
+ }
+ }
+ })
+}
+
+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,
@@ -1772,7 +1827,10 @@ const apiService = {
postAnnouncement,
editAnnouncement,
deleteAnnouncement,
- adminFetchAnnouncements
+ adminFetchAnnouncements,
+ fetchInstanceDBConfig,
+ fetchInstanceConfigDescriptions,
+ pushInstanceDBConfig
}
export default apiService