Merge branch 'improve_settings_reusability' into shigusegubu-vue3

* improve_settings_reusability:
  fixes for diabled state, tri-state boolean and access control
  made draft-mode and source inject-able
  fixes
This commit is contained in:
Henry Jameson 2023-03-22 00:01:14 +02:00
commit bd97a2dc00
10 changed files with 178 additions and 109 deletions

View file

@ -14,7 +14,12 @@ library.add(
)
const InstanceTab = {
data () {},
provide () {
return {
defaultDraftMode: true,
defaultSource: 'admin'
}
},
components: {
BooleanSetting,
ChoiceSetting,

View file

@ -4,66 +4,108 @@
<h2>{{ $t('admin_dash.instance.instance') }}</h2>
<ul class="setting-list">
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:name"
draft-mode
>
<StringSetting path=":pleroma.:instance.:name">
NAME
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:email"
draft-mode
>
<StringSetting path=":pleroma.:instance.:email">
ADMIN EMAIL
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:description"
draft-mode
>
<StringSetting path=":pleroma.:instance.:description">
DESCRIPTION
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:short_description"
draft-mode
>
<StringSetting path=":pleroma.:instance.:short_description">
SHORT DESCRIPTION
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:instance_thumbnail"
draft-mode
>
<StringSetting path=":pleroma.:instance.:instance_thumbnail">
INSTANCE THUMBNAIL
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:background_image"
draft-mode
>
<StringSetting path=":pleroma.:instance.:background_image">
BACKGROUND IMAGE
</StringSetting>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{ $t('admin_dash.instance.access') }}</h2>
<ul class="setting-list">
<li>
<BooleanSetting path=":pleroma.:instance.:public">
PUBLIC
</BooleanSetting>
</li>
<li>
<h3>{{ $t('admin_dash.instance.restrict.header') }}</h3>
</li>
<li>
<ChoiceSetting path=":pleroma.:instance.:limit_to_local_content">
SEARCH RESTRICTION
</ChoiceSetting>
</li>
<li>
<h4>{{ $t('admin_dash.instance.restrict.timelines') }}</h4>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:public"
draft-mode
path=":pleroma.:restrict_unauthenticated.:timelines.:local"
indeterminate-state=":if_instance_is_private"
>
PUBLIC
LOCAL TIMELINES
</BooleanSetting>
</li>
<li>
<BooleanSetting
path=":pleroma.:restrict_unauthenticated.:timelines.:federated"
indeterminate-state=":if_instance_is_private"
>
FED TIMELINES
</BooleanSetting>
</li>
<li>
<h4>{{ $t('admin_dash.instance.restrict.profiles') }}</h4>
</li>
<li>
<BooleanSetting
path=":pleroma.:restrict_unauthenticated.:profiles.:local"
indeterminate-state=":if_instance_is_private"
>
LOCAL PROFILES
</BooleanSetting>
</li>
<li>
<BooleanSetting
path=":pleroma.:restrict_unauthenticated.:profiles.:remote"
indeterminate-state=":if_instance_is_private"
>
FED PROFILES
</BooleanSetting>
</li>
<li>
<h4>{{ $t('admin_dash.instance.restrict.activities') }}</h4>
</li>
<li>
<BooleanSetting
path=":pleroma.:restrict_unauthenticated.:activities.:local"
indeterminate-state=":if_instance_is_private"
>
LOCAL STATUSES
</BooleanSetting>
</li>
<li>
<BooleanSetting
path=":pleroma.:restrict_unauthenticated.:activities.:remote"
indeterminate-state=":if_instance_is_private"
>
FED STATUSES
</BooleanSetting>
</li>
</ul>
@ -72,21 +114,15 @@
<h2>{{ $t('admin_dash.instance.registrations') }}</h2>
<ul class="setting-list">
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:registrations_open"
draft-mode
>
<BooleanSetting path=":pleroma.:instance.:registrations_open">
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
parent-invert
>
INVITES ENABLED
</BooleanSetting>
@ -94,20 +130,27 @@
</ul>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:account_activation_required"
draft-mode
>
<BooleanSetting path=":pleroma.:instance.:birthday_required">
BDEY REQUIRED
</BooleanSetting>
<ul class="setting-list suboptions">
<li>
<IntegerSetting
path=":pleroma.:instance.:birthday_min_age"
parent-path=":pleroma.:instance.:birthday_required"
>
BDEY age of consent
</IntegerSetting>
</li>
</ul>
</li>
<li>
<BooleanSetting path=":pleroma.:instance.:account_activation_required">
ACTIVATION REQUIRED
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:account_approval_required"
draft-mode
>
<BooleanSetting path=":pleroma.:instance.:account_approval_required">
APPROVAL REQUIRED
</BooleanSetting>
</li>
@ -115,32 +158,24 @@
<h3>{{ $t('admin_dash.instance.captcha_header') }}</h3>
</li>
<li>
<BooleanSetting
source="admin"
:path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
draft-mode
>
<BooleanSetting :path="[':pleroma', 'Pleroma.Captcha', ':enabled']">
CAPTCHA
</BooleanSetting>
<ul class="setting-list suboptions">
<li>
<ChoiceSetting
source="admin"
:path="[':pleroma', 'Pleroma.Captcha', ':method']"
:parent-path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
:option-label-map="{
'Pleroma.Captcha.Native': $t('admin_dash.captcha.native'),
'Pleroma.Captcha.Kocaptcha': $t('admin_dash.captcha.kocaptcha')
}"
draft-mode
>
CAPTCHA TYPE
</ChoiceSetting>
<IntegerSetting
source="admin"
:path="[':pleroma', 'Pleroma.Captcha', ':seconds_valid']"
:parent-path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
draft-mode
>
VALID
</IntegerSetting>
@ -152,11 +187,7 @@
>
<h4>{{ $t('admin_dash.instance.kocaptcha') }}</h4>
<li>
<StringSetting
source="admin"
:path="[':pleroma', 'Pleroma.Captcha.Kocaptcha', ':endpoint']"
draft-mode
>
<StringSetting :path="[':pleroma', 'Pleroma.Captcha.Kocaptcha', ':endpoint']">
cockAPTCHA ENDPOINT
</StringSetting>
</li>

View file

@ -3,13 +3,28 @@ import Setting from './setting.js'
export default {
...Setting,
props: {
...Setting.props,
indeterminateState: [String, Object]
},
components: {
...Setting.components,
Checkbox
},
computed: {
...Setting.computed,
isIndeterminate () {
return this.visibleState === this.indeterminateState
}
},
methods: {
...Setting.methods,
getValue (e) {
// Basic tri-state toggle implementation
if (!!this.indeterminateState && !e && this.visibleState === true) {
// If we have indeterminate state, switching from true to false first goes through indeterminate
return this.indeterminateState
}
return e
}
}

View file

@ -4,35 +4,37 @@
class="BooleanSetting"
>
<Checkbox
:model-value="draftMode ? draft :state"
:model-value="visibleState"
:disabled="shouldBeDisabled"
:indeterminate="isIndeterminate"
@update:modelValue="update"
>
<span
v-if="!!$slots.default"
class="label"
:class="{ 'faint': shouldBeDisabled }"
>
<template v-if="backendDescription">
{{ backendDescriptionLabel + ' ' }}
{{ backendDescriptionLabel }}
</template>
<template v-else>
<slot />
</template>
</span>
{{ ' ' }}
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
<DraftButtons />
<p
v-if="backendDescriptionDescription"
class="setting-description"
>
{{ backendDescriptionDescription + ' ' }}
</p>
</Checkbox>
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
<DraftButtons />
<p
v-if="backendDescriptionDescription"
class="setting-description"
:class="{ 'faint': shouldBeDisabled }"
>
{{ backendDescriptionDescription + ' ' }}
</p>
</label>
</template>

View file

@ -22,8 +22,7 @@ export default {
computed: {
...Setting.computed,
realOptions () {
if (this.source === 'admin') {
console.log(this.backendDescriptionSuggestions)
if (this.realSource === 'admin') {
return this.backendDescriptionSuggestions.map(x => ({
key: x,
value: x,

View file

@ -11,7 +11,7 @@
</template>
{{ ' ' }}
<Select
:model-value="draftMode ? draft :state"
:model-value="realDraftMode ? draft :state"
:disabled="disabled"
@update:modelValue="update"
>

View file

@ -5,13 +5,13 @@
class="DraftButtons"
>
<Popover
v-if="$parent.isDirty"
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')"
@ -27,13 +27,13 @@
</template>
</Popover>
<Popover
v-if="$parent.isDirty"
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')"
@ -49,13 +49,13 @@
</template>
</Popover>
<Popover
v-if="$parent.canHardReset"
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')"

View file

@ -3,7 +3,7 @@
v-if="matchesExpertLevel"
class="NumberSetting"
>
<label :for="path">
<label :for="path" :class="{ 'faint': shouldBeDisabled }">
<template v-if="backendDescription">
{{ backendDescriptionLabel + ' ' }}
</template>
@ -16,9 +16,9 @@
class="number-input"
type="number"
:step="step || 1"
:disabled="disabled"
:disabled="shouldBeDisabled"
:min="min || 0"
:value="draftMode ? draft :state"
:value="realDraftMode ? draft :state"
@change="update"
>
{{ ' ' }}
@ -31,6 +31,7 @@
<p
v-if="backendDescriptionDescription"
class="setting-description"
:class="{ 'faint': shouldBeDisabled }"
>
{{ backendDescriptionDescription + ' ' }}
</p>

View file

@ -1,4 +1,3 @@
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'
@ -6,7 +5,6 @@ import { get, set } from 'lodash'
export default {
components: {
Checkbox,
ModifiedIndicator,
DraftButtons,
ProfileSettingIndicator
@ -33,10 +31,18 @@ export default {
},
source: {
type: String,
default: 'default'
default: undefined
},
draftMode: {
type: Boolean,
default: undefined
}
},
inject: {
defaultSource: {
default: 'default'
},
defaultDraftMode: {
default: false
}
},
@ -46,7 +52,7 @@ export default {
}
},
created () {
if (this.draftMode) {
if (this.realDraftMode) {
this.draft = this.state
}
},
@ -59,6 +65,15 @@ export default {
return value
}
},
visibleState () {
return this.realDraftMode ? this.draft : this.state
},
realSource () {
return this.source || this.defaultSource
},
realDraftMode () {
return typeof this.draftMode === 'undefined' ? this.defaultDraftMode : this.draftMode
},
backendDescription () {
return get(this.$store.state.adminSettings.descriptions, this.path)
},
@ -76,7 +91,7 @@ export default {
return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
},
configSource () {
switch (this.source) {
switch (this.realSource) {
case 'profile':
return this.$store.state.profileConfig
case 'admin':
@ -86,7 +101,7 @@ export default {
}
},
configSink () {
switch (this.source) {
switch (this.realSource) {
case 'profile':
return (k, v) => this.$store.dispatch('setProfileOption', { name: k, value: v })
case 'admin':
@ -96,7 +111,7 @@ export default {
}
},
defaultState () {
switch (this.source) {
switch (this.realSource) {
case 'profile':
return {}
default:
@ -104,10 +119,10 @@ export default {
}
},
isProfileSetting () {
return this.source === 'profile'
return this.realSource === 'profile'
},
isChanged () {
switch (this.source) {
switch (this.realSource) {
case 'profile':
case 'admin':
return false
@ -116,10 +131,10 @@ export default {
}
},
isDirty () {
return this.draftMode && this.draft !== this.state
return this.realDraftMode && this.draft !== this.state
},
canHardReset () {
return this.source === 'admin' && this.$store.state.adminSettings.modifiedPaths.has(this.path)
return this.realSource === 'admin' && this.$store.state.adminSettings.modifiedPaths.has(this.path)
},
matchesExpertLevel () {
return (this.expert || 0) <= this.$store.state.config.expertLevel > 0
@ -130,20 +145,20 @@ export default {
return e.target.value
},
update (e) {
if (this.draftMode) {
if (this.realDraftMode) {
this.draft = this.getValue(e)
} else {
this.configSink(this.path, this.getValue(e))
}
},
commitDraft () {
if (this.draftMode) {
if (this.realDraftMode) {
this.configSink(this.path, this.draft)
}
},
reset () {
console.log('reset')
if (this.draftMode) {
if (this.realDraftMode) {
console.log(this.draft)
console.log(this.state)
this.draft = this.state
@ -152,7 +167,7 @@ export default {
}
},
hardReset () {
switch (this.source) {
switch (this.realSource) {
case 'admin':
return this.$store.dispatch('resetAdminSetting', { path: this.path })
.then(() => { this.draft = this.state })

View file

@ -3,7 +3,7 @@
v-if="matchesExpertLevel"
class="StringSetting"
>
<label :for="path">
<label :for="path" :class="{ 'faint': shouldBeDisabled }">
<template v-if="backendDescription">
{{ backendDescriptionLabel + ' ' }}
</template>
@ -15,8 +15,8 @@
:id="path"
class="string-input"
step="1"
:disabled="disabled"
:value="draftMode ? draft :state"
:disabled="shouldBeDisabled"
:value="realDraftMode ? draft : state"
@change="update"
>
{{ ' ' }}
@ -29,6 +29,7 @@
<p
v-if="backendDescriptionDescription"
class="setting-description"
:class="{ 'faint': shouldBeDisabled }"
>
{{ backendDescriptionDescription + ' ' }}
</p>