From 4d23d31fecf480abfccc4db3ac79c6640078dc3b Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 14 Mar 2023 21:50:43 +0200
Subject: initial admin settings prototype (WIP)

---
 .../settings_modal/helpers/string_setting.vue      | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 src/components/settings_modal/helpers/string_setting.vue

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

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..e4bd2de9
--- /dev/null
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -0,0 +1,25 @@
+<template>
+  <label
+    v-if="matchesExpertLevel"
+    class="StringSetting"
+  >
+    <label :for="path">
+      <slot />
+    </label>
+    <input
+      :id="path"
+      class="string-input"
+      step="1"
+      :disabled="disabled"
+      :value="state"
+      @change="update"
+    >
+    {{ ' ' }}
+    <ModifiedIndicator
+      :changed="isChanged"
+      :onclick="reset"
+    />
+  </label>
+</template>
+
+<script src="./boolean_setting.js"></script>
-- 
cgit v1.2.3-70-g09d2


From bfd802ad046886230574cf2262f9c2e5f1b03a3f Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 16 Mar 2023 23:18:55 +0200
Subject: setting admin settings works now. also now we have draftable settings

---
 .../settings_modal/admin_tabs/instance_tab.vue     |  23 ++++-
 .../settings_modal/helpers/boolean_setting.js      |  15 +--
 .../settings_modal/helpers/boolean_setting.vue     |   3 +-
 .../settings_modal/helpers/choice_setting.js       |   9 +-
 .../settings_modal/helpers/draft_buttons.vue       | 102 +++++++++++++++++++++
 .../settings_modal/helpers/integer_setting.js      |   8 +-
 .../settings_modal/helpers/integer_setting.vue     |   4 +-
 src/components/settings_modal/helpers/setting.js   |  70 ++++++++++++--
 .../settings_modal/helpers/size_setting.js         |   5 +-
 .../settings_modal/helpers/string_setting.js       |   4 -
 .../settings_modal/helpers/string_setting.vue      |   6 +-
 src/modules/adminSettings.js                       |  52 ++++++++++-
 src/modules/users.js                               |   2 +-
 src/services/api/api.service.js                    |  26 +++++-
 14 files changed, 284 insertions(+), 45 deletions(-)
 create mode 100644 src/components/settings_modal/helpers/draft_buttons.vue

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index 65b3d12f..18ba6127 100644
--- 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
index 078cc5ff..0df01d31 100644
--- 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
index 260ee75e..7e05fe85 100644
--- 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
index 8aa5f54b..a3c3bf44 100644
--- 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
new file mode 100644
index 00000000..0d99da13
--- /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/integer_setting.js b/src/components/settings_modal/helpers/integer_setting.js
index 0f29f11a..8ad033e7 100644
--- 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
index 695e2673..e900b87c 100644
--- 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
index 9195d3e9..0971b919 100644
--- 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
index 4a0f7e48..12cef705 100644
--- 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
index 64f8772d..b368cfc8 100644
--- 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
index e4bd2de9..0a71aeab 100644
--- 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
index 8006717d..d1df67d4 100644
--- 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
index 74dbdffc..12e582f4 100644
--- 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
index f0aa898a..71ba1dec 100644
--- 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
-- 
cgit v1.2.3-70-g09d2


From 332ad77e3579d2b512ba236b3f2c94ad8875864d Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 19 Mar 2023 21:27:07 +0200
Subject: limits tab, backend descriptions

---
 .../settings_modal/admin_tabs/instance_tab.vue     | 103 +++++++++++---
 .../settings_modal/admin_tabs/limits_tab.js        |  29 ++++
 .../settings_modal/admin_tabs/limits_tab.vue       | 152 +++++++++++++++++++++
 .../settings_modal/helpers/boolean_setting.vue     |  13 +-
 .../settings_modal/helpers/integer_setting.vue     |  13 +-
 src/components/settings_modal/helpers/setting.js   |  10 ++
 .../settings_modal/helpers/string_setting.vue      |  13 +-
 src/components/settings_modal/settings_modal.scss  |   6 +
 .../settings_modal/settings_modal_admin_content.js |   4 +-
 .../settings_modal_admin_content.vue               |   9 +-
 src/modules/adminSettings.js                       |  24 +++-
 src/modules/users.js                               |   2 +
 src/services/api/api.service.js                    |  17 +++
 13 files changed, 370 insertions(+), 25 deletions(-)
 create mode 100644 src/components/settings_modal/admin_tabs/limits_tab.js
 create mode 100644 src/components/settings_modal/admin_tabs/limits_tab.vue

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index 18ba6127..ad271293 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -12,6 +12,15 @@
             NAME
           </StringSetting>
         </li>
+        <li>
+          <StringSetting
+            source="admin"
+            path=":pleroma.:instance.:email"
+            draft-mode
+          >
+            ADMIN EMAIL
+          </StringSetting>
+        </li>
         <li>
           <StringSetting
             source="admin"
@@ -22,13 +31,85 @@
           </StringSetting>
         </li>
         <li>
-          <IntegerSetting
+          <StringSetting
             source="admin"
-            path=":pleroma.:instance.:limit"
+            path=":pleroma.:instance.:short_description"
             draft-mode
           >
-            POST LIMIT
-          </IntegerSetting>
+            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>
@@ -36,17 +117,3 @@
 </template>
 
 <script src="./instance_tab.js"></script>
-
-<style lang="scss">
-.column-settings {
-  display: flex;
-  justify-content: space-evenly;
-  flex-wrap: wrap;
-}
-
-.column-settings .size-label {
-  display: block;
-  margin-bottom: 0.5em;
-  margin-top: 0.5em;
-}
-</style>
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.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 7e05fe85..aedbf23e 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -12,7 +12,12 @@
         v-if="!!$slots.default"
         class="label"
       >
-        <slot />
+        <template v-if="backendDescription">
+          {{ backendDescriptionLabel + ' ' }}
+        </template>
+        <template v-else>
+          <slot />
+        </template>
       </span>
       {{ ' ' }}
       <ModifiedIndicator
@@ -21,6 +26,12 @@
       />
       <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/integer_setting.vue b/src/components/settings_modal/helpers/integer_setting.vue
index e900b87c..e935dfb0 100644
--- a/src/components/settings_modal/helpers/integer_setting.vue
+++ b/src/components/settings_modal/helpers/integer_setting.vue
@@ -4,7 +4,12 @@
     class="IntegerSetting"
   >
     <label :for="path">
-      <slot />
+      <template v-if="backendDescription">
+        {{ backendDescriptionLabel + ' ' }}
+      </template>
+      <template v-else>
+        <slot />
+      </template>
     </label>
     <input
       :id="path"
@@ -23,6 +28,12 @@
     />
     <ProfileSettingIndicator :is-profile="isProfileSetting" />
     <DraftButtons />
+    <p
+      v-if="backendDescriptionDescription"
+      class="setting-description"
+    >
+      {{ backendDescriptionDescription + ' ' }}
+    </p>
   </span>
 </template>
 
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
index 0971b919..f270216f 100644
--- a/src/components/settings_modal/helpers/setting.js
+++ b/src/components/settings_modal/helpers/setting.js
@@ -59,6 +59,16 @@ export default {
         return value
       }
     },
+    backendDescription () {
+      console.log(get(this.$store.state.adminSettings.descriptions, this.path))
+      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)
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 0a71aeab..91a4afa4 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -4,7 +4,12 @@
     class="StringSetting"
   >
     <label :for="path">
-      <slot />
+      <template v-if="backendDescription">
+        {{ backendDescriptionLabel + ' ' }}
+      </template>
+      <template v-else>
+        <slot />
+      </template>
     </label>
     <input
       :id="path"
@@ -21,6 +26,12 @@
     />
     <ProfileSettingIndicator :is-profile="isProfileSetting" />
     <DraftButtons />
+    <p
+      v-if="backendDescriptionDescription"
+      class="setting-description"
+    >
+      {{ backendDescriptionDescription + ' ' }}
+    </p>
   </label>
 </template>
 
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_admin_content.js b/src/components/settings_modal/settings_modal_admin_content.js
index 88ba1755..c6c8837f 100644
--- a/src/components/settings_modal/settings_modal_admin_content.js
+++ b/src/components/settings_modal/settings_modal_admin_content.js
@@ -3,6 +3,7 @@ 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 {
@@ -33,7 +34,8 @@ const SettingsModalAdminContent = {
 
     DataImportExportTab,
     MutesAndBlocksTab,
-    InstanceTab
+    InstanceTab,
+    LimitsTab
   },
   computed: {
     isLoggedIn () {
diff --git a/src/components/settings_modal/settings_modal_admin_content.vue b/src/components/settings_modal/settings_modal_admin_content.vue
index 9873b127..16b55828 100644
--- a/src/components/settings_modal/settings_modal_admin_content.vue
+++ b/src/components/settings_modal/settings_modal_admin_content.vue
@@ -7,12 +7,19 @@
     :body-scroll-lock="bodyLock"
   >
     <div
-      :label="$t('settings.general')"
+      :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>
 
diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js
index d1df67d4..44a4d409 100644
--- a/src/modules/adminSettings.js
+++ b/src/modules/adminSettings.js
@@ -3,7 +3,8 @@ import { set, cloneDeep } from 'lodash'
 export const defaultState = {
   needsReboot: null,
   config: null,
-  modifiedPaths: null
+  modifiedPaths: null,
+  descriptions: null
 }
 
 export const newUserFlags = {
@@ -18,6 +19,9 @@ const adminSettingsStorage = {
     updateAdminSettings (state, { config, modifiedPaths }) {
       state.config = config
       state.modifiedPaths = modifiedPaths
+    },
+    updateAdminDescriptions (state, { descriptions }) {
+      state.descriptions = descriptions
     }
   },
   actions: {
@@ -40,8 +44,25 @@ const adminSettingsStorage = {
         }
         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
@@ -71,7 +92,6 @@ const adminSettingsStorage = {
         .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)
diff --git a/src/modules/users.js b/src/modules/users.js
index 12e582f4..45cba334 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -567,6 +567,8 @@ const users = {
               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])
 
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 71ba1dec..073f40a3 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -109,6 +109,7 @@ const PLEROMA_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements
 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
 
@@ -1677,6 +1678,21 @@ const fetchInstanceDBConfig = ({ credentials }) => {
     })
 }
 
+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: {
@@ -1813,6 +1829,7 @@ const apiService = {
   deleteAnnouncement,
   adminFetchAnnouncements,
   fetchInstanceDBConfig,
+  fetchInstanceConfigDescriptions,
   pushInstanceDBConfig
 }
 
-- 
cgit v1.2.3-70-g09d2


From 2bf224e214d9b42333a2139a89c089ca9a544149 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 21 Mar 2023 22:46:40 +0200
Subject: made draft-mode and source inject-able

---
 .../settings_modal/admin_tabs/instance_tab.js      |  6 ++
 .../settings_modal/admin_tabs/instance_tab.vue     | 78 ++++------------------
 .../settings_modal/helpers/choice_setting.js       |  3 +-
 .../settings_modal/helpers/choice_setting.vue      |  2 +-
 .../settings_modal/helpers/number_setting.vue      |  2 +-
 src/components/settings_modal/helpers/setting.js   | 41 ++++++++----
 .../settings_modal/helpers/string_setting.vue      |  2 +-
 7 files changed, 50 insertions(+), 84 deletions(-)

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.js b/src/components/settings_modal/admin_tabs/instance_tab.js
index 77a05d38..7aaedbce 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.js
+++ b/src/components/settings_modal/admin_tabs/instance_tab.js
@@ -14,6 +14,12 @@ library.add(
 )
 
 const InstanceTab = {
+  provide () {
+    return {
+      defaultDraftMode: true,
+      defaultSource: 'admin'
+    }
+  },
   components: {
     BooleanSetting,
     ChoiceSetting,
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index 411982cc..43ad4c8c 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -4,65 +4,37 @@
       <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>
         <li>
-          <BooleanSetting
-            source="admin"
-            path=":pleroma.:instance.:public"
-            draft-mode
-          >
+          <BooleanSetting path=":pleroma.:instance.:public">
             PUBLIC
           </BooleanSetting>
         </li>
@@ -72,21 +44,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
               >
                 INVITES ENABLED
               </BooleanSetting>
@@ -94,20 +60,12 @@
           </ul>
         </li>
         <li>
-          <BooleanSetting
-            source="admin"
-            path=":pleroma.:instance.:account_activation_required"
-            draft-mode
-          >
+          <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 +73,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 +102,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>
diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
index 3ff81bc9..bdeece76 100644
--- a/src/components/settings_modal/helpers/choice_setting.js
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -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,
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 55f9a62c..8713acf5 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -11,7 +11,7 @@
     </template>
     {{ ' ' }}
     <Select
-      :model-value="draftMode ? draft :state"
+      :model-value="realDraftMode ? draft :state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index 93a7a79a..f97d5cf2 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -18,7 +18,7 @@
       :step="step || 1"
       :disabled="disabled"
       :min="min || 0"
-      :value="draftMode ? draft :state"
+      :value="realDraftMode ? draft :state"
       @change="update"
     >
     {{ ' ' }}
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
index fd730db9..7cad27b7 100644
--- a/src/components/settings_modal/helpers/setting.js
+++ b/src/components/settings_modal/helpers/setting.js
@@ -31,10 +31,18 @@ export default {
     },
     source: {
       type: String,
-      default: 'default'
+      default: undefined
     },
     draftMode: {
       type: Boolean,
+      default: undefined
+    }
+  },
+  inject: {
+    defaultSource: {
+      default: 'default'
+    },
+    defaultDraftMode: {
       default: false
     }
   },
@@ -44,7 +52,7 @@ export default {
     }
   },
   created () {
-    if (this.draftMode) {
+    if (this.realDraftMode) {
       this.draft = this.state
     }
   },
@@ -57,6 +65,12 @@ export default {
         return value
       }
     },
+    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)
     },
@@ -74,7 +88,8 @@ export default {
       return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
     },
     configSource () {
-      switch (this.source) {
+      console.log('SRC', this.realSource)
+      switch (this.realSource) {
         case 'profile':
           return this.$store.state.profileConfig
         case 'admin':
@@ -84,7 +99,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':
@@ -94,7 +109,7 @@ export default {
       }
     },
     defaultState () {
-      switch (this.source) {
+      switch (this.realSource) {
         case 'profile':
           return {}
         default:
@@ -102,10 +117,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
@@ -114,10 +129,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
@@ -128,20 +143,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
@@ -150,7 +165,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 })
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 91a4afa4..fb91b5d9 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -16,7 +16,7 @@
       class="string-input"
       step="1"
       :disabled="disabled"
-      :value="draftMode ? draft :state"
+      :value="realDraftMode ? draft : state"
       @change="update"
     >
     {{ ' ' }}
-- 
cgit v1.2.3-70-g09d2


From 6992439c92c247bf5b48155a76ff4e39a57b0ec7 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 22 Mar 2023 00:00:52 +0200
Subject: fixes for diabled state, tri-state boolean and access control

---
 .../settings_modal/admin_tabs/instance_tab.vue     | 87 +++++++++++++++++++++-
 .../settings_modal/helpers/boolean_setting.js      | 15 ++++
 .../settings_modal/helpers/boolean_setting.vue     |  5 +-
 .../settings_modal/helpers/draft_buttons.vue       |  2 +-
 .../settings_modal/helpers/number_setting.vue      |  5 +-
 src/components/settings_modal/helpers/setting.js   |  4 +-
 .../settings_modal/helpers/string_setting.vue      |  5 +-
 7 files changed, 115 insertions(+), 8 deletions(-)

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index 43ad4c8c..96d8a17e 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -33,11 +33,81 @@
             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
+            path=":pleroma.:restrict_unauthenticated.:timelines.:local"
+            indeterminate-state=":if_instance_is_private"
+          >
+            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>
     </div>
     <div class="setting-item">
@@ -52,13 +122,28 @@
               <BooleanSetting
                 path=":pleroma.:instance.:invites_enabled"
                 parent-path=":pleroma.:instance.:registrations_open"
-                :parent-invert="true"
+                parent-invert
               >
                 INVITES ENABLED
               </BooleanSetting>
             </li>
           </ul>
         </li>
+        <li>
+          <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
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
index 0df01d31..199d3d0f 100644
--- a/src/components/settings_modal/helpers/boolean_setting.js
+++ b/src/components/settings_modal/helpers/boolean_setting.js
@@ -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
     }
   }
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 07971b00..6307d526 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -4,13 +4,15 @@
     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 }}
@@ -29,6 +31,7 @@
     <p
       v-if="backendDescriptionDescription"
       class="setting-description"
+      :class="{ 'faint': shouldBeDisabled }"
     >
       {{ backendDescriptionDescription + ' ' }}
     </p>
diff --git a/src/components/settings_modal/helpers/draft_buttons.vue b/src/components/settings_modal/helpers/draft_buttons.vue
index 9e972b14..80da92e8 100644
--- a/src/components/settings_modal/helpers/draft_buttons.vue
+++ b/src/components/settings_modal/helpers/draft_buttons.vue
@@ -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')"
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index f97d5cf2..2b90c336 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -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,7 +16,7 @@
       class="number-input"
       type="number"
       :step="step || 1"
-      :disabled="disabled"
+      :disabled="shouldBeDisabled"
       :min="min || 0"
       :value="realDraftMode ? draft :state"
       @change="update"
@@ -31,6 +31,7 @@
     <p
       v-if="backendDescriptionDescription"
       class="setting-description"
+      :class="{ 'faint': shouldBeDisabled }"
     >
       {{ backendDescriptionDescription + ' ' }}
     </p>
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
index 7cad27b7..d42ae763 100644
--- a/src/components/settings_modal/helpers/setting.js
+++ b/src/components/settings_modal/helpers/setting.js
@@ -65,6 +65,9 @@ export default {
         return value
       }
     },
+    visibleState () {
+      return this.realDraftMode ? this.draft : this.state
+    },
     realSource () {
       return this.source || this.defaultSource
     },
@@ -88,7 +91,6 @@ export default {
       return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
     },
     configSource () {
-      console.log('SRC', this.realSource)
       switch (this.realSource) {
         case 'profile':
           return this.$store.state.profileConfig
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index fb91b5d9..5ee75a84 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -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,7 +15,7 @@
       :id="path"
       class="string-input"
       step="1"
-      :disabled="disabled"
+      :disabled="shouldBeDisabled"
       :value="realDraftMode ? draft : state"
       @change="update"
     >
@@ -29,6 +29,7 @@
     <p
       v-if="backendDescriptionDescription"
       class="setting-description"
+      :class="{ 'faint': shouldBeDisabled }"
     >
       {{ backendDescriptionDescription + ' ' }}
     </p>
-- 
cgit v1.2.3-70-g09d2


From 4c158e636bd7ae9ec03a202e54aa681e66645a78 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 12 Apr 2023 23:58:21 +0300
Subject: more i18n stuff, added missing labels and such

---
 .../settings_modal/admin_tabs/instance_tab.vue     | 12 +++++++
 .../settings_modal/helpers/boolean_setting.vue     |  2 +-
 .../settings_modal/helpers/choice_setting.vue      |  2 +-
 .../settings_modal/helpers/number_setting.vue      |  2 +-
 src/components/settings_modal/helpers/setting.js   | 41 ++++++++++++++++++++--
 .../settings_modal/helpers/string_setting.vue      |  2 +-
 src/i18n/en.json                                   | 23 +++++++++++-
 7 files changed, 77 insertions(+), 7 deletions(-)

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index fc41af65..40e33495 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -58,6 +58,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:timelines.:local"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             LOCAL TIMELINES
           </BooleanSetting>
@@ -66,6 +68,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:timelines.:federated"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             FED TIMELINES
           </BooleanSetting>
@@ -82,6 +86,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:profiles.:local"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             LOCAL PROFILES
           </BooleanSetting>
@@ -90,6 +96,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:profiles.:remote"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             FED PROFILES
           </BooleanSetting>
@@ -106,6 +114,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:activities.:local"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             LOCAL STATUSES
           </BooleanSetting>
@@ -114,6 +124,8 @@
           <BooleanSetting
             path=":pleroma.:restrict_unauthenticated.:activities.:remote"
             indeterminate-state=":if_instance_is_private"
+            swap-description-and-label
+            hide-description
           >
             FED STATUSES
           </BooleanSetting>
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 6307d526..3089c3b3 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -14,7 +14,7 @@
         class="label"
         :class="{ 'faint': shouldBeDisabled }"
       >
-        <template v-if="backendDescription">
+        <template v-if="backendDescriptionLabel">
           {{ backendDescriptionLabel }}
         </template>
         <template v-else>
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 8713acf5..114e9b7d 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -3,7 +3,7 @@
     v-if="matchesExpertLevel"
     class="ChoiceSetting"
   >
-    <template v-if="backendDescription">
+    <template v-if="backendDescriptionLabel">
       {{ backendDescriptionLabel }}
     </template>
     <template v-else>
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index 2b90c336..ce168570 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -4,7 +4,7 @@
     class="NumberSetting"
   >
     <label :for="path" :class="{ 'faint': shouldBeDisabled }">
-      <template v-if="backendDescription">
+      <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
       <template v-else>
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
index 4f0be448..fec1b947 100644
--- a/src/components/settings_modal/helpers/setting.js
+++ b/src/components/settings_modal/helpers/setting.js
@@ -33,6 +33,18 @@ export default {
       type: String,
       default: undefined
     },
+    hideDescription: {
+      type: Boolean
+    },
+    swapDescriptionAndLabel: {
+      type: Boolean
+    },
+    overrideBackendDescription: {
+      type: Boolean
+    },
+    overrideBackendDescriptionLabel: {
+      type: Boolean
+    },
     draftMode: {
       type: Boolean,
       default: undefined
@@ -95,10 +107,35 @@ export default {
       return get(this.$store.state.adminSettings.descriptions, this.path)
     },
     backendDescriptionLabel () {
-      return this.backendDescription?.label
+      if (this.realSource !== 'admin') return ''
+      if (!this.backendDescription || this.overrideBackendDescriptionLabel) {
+        return this.$t([
+          'admin_dash',
+          'temp_overrides',
+          ...this.canonPath.map(p => p.replace(/\./g, '_DOT_')),
+          'label'
+        ].join('.'))
+      } else {
+        return this.swapDescriptionAndLabel
+          ? this.backendDescription?.description
+          : this.backendDescription?.label
+      }
     },
     backendDescriptionDescription () {
-      return this.backendDescription?.description
+      if (this.realSource !== 'admin') return ''
+      if (this.hideDescription) return null
+      if (!this.backendDescription || this.overrideBackendDescription) {
+        return this.$t([
+          'admin_dash',
+          'temp_overrides',
+          ...this.canonPath.map(p => p.replace(/\./g, '_DOT_')),
+          'description'
+        ].join('.'))
+      } else {
+        return this.swapDescriptionAndLabel
+          ? this.backendDescription?.label
+          : this.backendDescription?.description
+      }
     },
     backendDescriptionSuggestions () {
       return this.backendDescription?.suggestions
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 5ee75a84..7e70b82f 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -4,7 +4,7 @@
     class="StringSetting"
   >
     <label :for="path" :class="{ 'faint': shouldBeDisabled }">
-      <template v-if="backendDescription">
+      <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
       <template v-else>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index f4c2df3e..082ad826 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -864,7 +864,14 @@
       "instance": "Instance information",
       "registrations": "User sign-ups",
       "captcha_header": "CAPTCHA",
-      "kocaptcha": "KoCaptcha settings"
+      "kocaptcha": "KoCaptcha settings",
+      "access": "Instance access",
+      "restrict": {
+        "header": "Restrict access",
+        "timelines": "Timelines access",
+        "profiles": "User profiles access",
+        "activities": "Statues/activities access"
+      }
     },
     "limits": {
       "arbitrary_limits": "Arbitrary limits",
@@ -890,6 +897,20 @@
       "default_frontend_tip": "Default front-end will be shown to all users. Currently there's no way to for a user to select personal front-end. If you switch away from PleromaFE you'll most likely have to use old and buggy AdminFE to do instance configuration until we replace it.",
       "default_frontend_tip2": "WIP: Since Pleroma backend doesn't properly list all installed frontends you'll have to enter name and reference manually. List below provides shortcuts to fill the values.",
       "available_frontends": "Available for install"
+    },
+    "temp_overrides": {
+      ":pleroma": {
+        ":instance": {
+          ":description_limit": {
+            "label": "Limit",
+            "description": "Character limit for attachment descriptions"
+          },
+          ":background_image": {
+            "label": "Background image",
+            "description": "Background image (primarily used by PleromaFE)"
+          }
+        }
+      }
     }
   },
   "time": {
-- 
cgit v1.2.3-70-g09d2


From 9aaa8a86f52bc97838c768a8859919a3ad6fd54f Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 13 Apr 2023 01:11:20 +0300
Subject: initial implementation of attachmentsetting

---
 .../settings_modal/admin_tabs/instance_tab.js      |  2 +
 .../settings_modal/admin_tabs/instance_tab.vue     |  8 +--
 .../settings_modal/helpers/attachment_setting.js   | 42 +++++++++++++
 .../settings_modal/helpers/attachment_setting.vue  | 70 ++++++++++++++++++++++
 .../settings_modal/helpers/string_setting.vue      |  1 -
 src/services/file_type/file_type.service.js        | 18 +++++-
 6 files changed, 134 insertions(+), 7 deletions(-)
 create mode 100644 src/components/settings_modal/helpers/attachment_setting.js
 create mode 100644 src/components/settings_modal/helpers/attachment_setting.vue

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/admin_tabs/instance_tab.js b/src/components/settings_modal/admin_tabs/instance_tab.js
index f702afcf..b07bafe8 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.js
+++ b/src/components/settings_modal/admin_tabs/instance_tab.js
@@ -3,6 +3,7 @@ import ChoiceSetting from '../helpers/choice_setting.vue'
 import IntegerSetting from '../helpers/integer_setting.vue'
 import StringSetting from '../helpers/string_setting.vue'
 import GroupSetting from '../helpers/group_setting.vue'
+import AttachmentSetting from '../helpers/attachment_setting.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
@@ -26,6 +27,7 @@ const InstanceTab = {
     ChoiceSetting,
     IntegerSetting,
     StringSetting,
+    AttachmentSetting,
     GroupSetting
   },
   computed: {
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index 535e4132..e519e135 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -24,14 +24,14 @@
           </StringSetting>
         </li>
         <li>
-          <StringSetting path=":pleroma.:instance.:instance_thumbnail">
+          <AttachmentSetting path=":pleroma.:instance.:instance_thumbnail">
             INSTANCE THUMBNAIL
-          </StringSetting>
+          </AttachmentSetting>
         </li>
         <li>
-          <StringSetting path=":pleroma.:instance.:background_image">
+          <AttachmentSetting path=":pleroma.:instance.:background_image">
             BACKGROUND IMAGE
-          </StringSetting>
+          </AttachmentSetting>
         </li>
       </ul>
     </div>
diff --git a/src/components/settings_modal/helpers/attachment_setting.js b/src/components/settings_modal/helpers/attachment_setting.js
new file mode 100644
index 00000000..a0a12ead
--- /dev/null
+++ b/src/components/settings_modal/helpers/attachment_setting.js
@@ -0,0 +1,42 @@
+import Setting from './setting.js'
+import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
+import MediaUpload from 'src/components/media_upload/media_upload.vue'
+import Attachment from 'src/components/attachment/attachment.vue'
+
+export default {
+  ...Setting,
+  props: {
+    ...Setting.props,
+    type: {
+      type: Array,
+      required: false,
+      default: []
+    }
+  },
+  components: {
+    ...Setting.components,
+    MediaUpload,
+    Attachment
+  },
+  computed: {
+    ...Setting.computed,
+    attachment () {
+      const path = this.realDraftMode ? this.draft : this.state
+      const url = path.includes('://') ? path : this.$store.state.instance.server + path
+      return {
+        mimetype: fileTypeExt(url),
+        url
+      }
+    }
+  },
+  methods: {
+    ...Setting.methods,
+    setMediaFile (fileInfo) {
+      if (this.realDraftMode) {
+        this.draft = fileInfo.url
+      } else {
+        this.configSink(this.path, fileInfo.url)
+      }
+    }
+  }
+}
diff --git a/src/components/settings_modal/helpers/attachment_setting.vue b/src/components/settings_modal/helpers/attachment_setting.vue
new file mode 100644
index 00000000..3a933511
--- /dev/null
+++ b/src/components/settings_modal/helpers/attachment_setting.vue
@@ -0,0 +1,70 @@
+<template>
+  <span
+    v-if="matchesExpertLevel"
+    class="AttachmentSetting"
+  >
+    <label :for="path" :class="{ 'faint': shouldBeDisabled }">
+      <template v-if="backendDescriptionLabel">
+        {{ backendDescriptionLabel + ' ' }}
+      </template>
+      <template v-else>
+        <slot />
+      </template>
+
+    </label>
+    <p
+      v-if="backendDescriptionDescription"
+      class="setting-description"
+      :class="{ 'faint': shouldBeDisabled }"
+    >
+      {{ backendDescriptionDescription + ' ' }}
+    </p>
+    <div class="attachment-input">
+      <Attachment
+        class="attachment"
+        :compact="compact"
+        :attachment="attachment"
+        size="small"
+        hide-description
+        @setMedia="onMedia"
+        @naturalSizeLoad="onNaturalSizeLoad"
+      />
+      <div class="controls">
+        <media-upload
+          normal-button
+          ref="mediaUpload"
+          class="media-upload-icon"
+          :drop-files="dropFiles"
+          @uploaded="setMediaFile"
+          @upload-failed="uploadFailed"
+        />
+        <input
+          :id="path"
+          class="string-input"
+          :disabled="shouldBeDisabled"
+          :value="realDraftMode ? draft : state"
+          @change="update"
+        >
+        {{ ' ' }}
+        <ModifiedIndicator
+          :changed="isChanged"
+          :onclick="reset"
+        />
+        <ProfileSettingIndicator :is-profile="isProfileSetting" />
+      </div>
+    </div>
+    <DraftButtons />
+  </span>
+</template>
+
+<script src="./attachment_setting.js"></script>
+
+<style lang="scss">
+.AttachmentSetting {
+  .attachment {
+    display: block;
+    width: 20em;
+    height: 15em;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 7e70b82f..84d0a9d6 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -14,7 +14,6 @@
     <input
       :id="path"
       class="string-input"
-      step="1"
       :disabled="shouldBeDisabled"
       :value="realDraftMode ? draft : state"
       @change="update"
diff --git a/src/services/file_type/file_type.service.js b/src/services/file_type/file_type.service.js
index 5182ecd1..b92c6c64 100644
--- a/src/services/file_type/file_type.service.js
+++ b/src/services/file_type/file_type.service.js
@@ -1,7 +1,7 @@
 // TODO this func might as well take the entire file and use its mimetype
 // or the entire service could be just mimetype service that only operates
 // on mimetypes and not files. Currently the naming is confusing.
-const fileType = mimetype => {
+export const fileType = mimetype => {
   if (mimetype.match(/flash/)) {
     return 'flash'
   }
@@ -25,11 +25,25 @@ const fileType = mimetype => {
   return 'unknown'
 }
 
-const fileMatchesSomeType = (types, file) =>
+export const fileTypeExt = url => {
+  if (url.match(/\.(png|jpe?g|gif|webp|avif)$/)) {
+    return 'image'
+  }
+  if (url.match(/\.(ogv|mp4|webm|mov)$/)) {
+    return 'video'
+  }
+  if (url.match(/\.(it|s3m|mod|umx|mp3|aac|m4a|flac|alac|ogg|oga|opus|wav|ape|midi?)$/)) {
+    return 'audio'
+  }
+  return 'unknown'
+}
+
+export const fileMatchesSomeType = (types, file) =>
   types.some(type => fileType(file.mimetype) === type)
 
 const fileTypeService = {
   fileType,
+  fileTypeExt,
   fileMatchesSomeType
 }
 
-- 
cgit v1.2.3-70-g09d2


From 1492937a7e8e27a31699879dc710d3e36c67b953 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 24 Apr 2023 23:01:29 +0300
Subject: lint

---
 src/components/media_upload/media_upload.vue       |  6 +--
 .../settings_modal/admin_tabs/frontends_tab.vue    | 56 ++++++++++++++++------
 .../settings_modal/helpers/attachment_setting.vue  |  9 ++--
 .../settings_modal/helpers/number_setting.vue      |  5 +-
 .../settings_modal/helpers/string_setting.vue      |  5 +-
 src/components/settings_modal/settings_modal.vue   | 13 +++--
 6 files changed, 66 insertions(+), 28 deletions(-)

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/media_upload/media_upload.vue b/src/components/media_upload/media_upload.vue
index c761b94f..993c01a4 100644
--- a/src/components/media_upload/media_upload.vue
+++ b/src/components/media_upload/media_upload.vue
@@ -1,7 +1,7 @@
 <template>
   <component
-    class="media-upload"
     :is="normalButton ? 'button' : 'label'"
+    class="media-upload"
     :class="{ disabled: disabled, ['media-upload button-default btn']: normalButton }"
     :title="$t('tool_tip.media_upload')"
     @click="onClick"
@@ -23,13 +23,13 @@
     </template>
     <input
       v-if="uploadReady"
+      ref="input"
       class="hidden-input-file"
       :disabled="disabled"
       type="file"
       multiple="true"
-      @change="change"
-      ref="input"
       :accept="acceptTypes"
+      @change="change"
     >
   </component>
 </template>
diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.vue b/src/components/settings_modal/admin_tabs/frontends_tab.vue
index 71bbfa69..e108a963 100644
--- a/src/components/settings_modal/admin_tabs/frontends_tab.vue
+++ b/src/components/settings_modal/admin_tabs/frontends_tab.vue
@@ -1,5 +1,8 @@
 <template>
-  <div class="frontends-tab" :label="$t('admin_dash.tabs.frontends')">
+  <div
+    class="frontends-tab"
+    :label="$t('admin_dash.tabs.frontends')"
+  >
     <div class="setting-item">
       <h2>{{ $t('admin_dash.tabs.frontends') }}</h2>
       <p>{{ $t('admin_dash.frontend.wip_notice') }}</p>
@@ -20,23 +23,26 @@
           </StringSetting>
         </li>
         <li>
-          <GroupSetting path=":pleroma.:frontends.:primary"/>
+          <GroupSetting path=":pleroma.:frontends.:primary" />
         </li>
       </ul>
       <div class="setting-list">
         <h3>{{ $t('admin_dash.frontend.available_frontends') }}</h3>
         <ul class="cards-list">
-          <li v-for="frontend in frontends" :key="frontend.name">
+          <li
+            v-for="frontend in frontends"
+            :key="frontend.name"
+          >
             <strong>{{ frontend.name }}</strong>
             {{ ' ' }}
             <span v-if="adminDraft[':pleroma'][':frontends'][':primary'].name === frontend.name">
               <i18n-t
-                keypath="admin_dash.frontend.is_default"
                 v-if="adminDraft[':pleroma'][':frontends'][':primary'].ref === frontend.refs[0]"
+                keypath="admin_dash.frontend.is_default"
               />
               <i18n-t
-                keypath="admin_dash.frontend.is_default_custom"
                 v-else
+                keypath="admin_dash.frontend.is_default_custom"
               >
                 <template #version>
                   <code>{{ adminDraft[':pleroma'][':frontends'][':primary'].ref }}</code>
@@ -45,13 +51,30 @@
             </span>
             <dl>
               <dt>{{ $t('admin_dash.frontend.repository') }}</dt>
-              <dd><a :href="frontend.git" target="_blank">{{ frontend.git }}</a></dd>
+              <dd>
+                <a
+                  :href="frontend.git"
+                  target="_blank"
+                >{{ frontend.git }}</a>
+              </dd>
               <template v-if="expertLevel">
                 <dt>{{ $t('admin_dash.frontend.versions') }}</dt>
-                <dd v-for="ref in frontend.refs" :key="ref"><code>{{ ref }}</code></dd>
+                <dd
+                  v-for="ref in frontend.refs"
+                  :key="ref"
+                >
+                  <code>{{ ref }}</code>
+                </dd>
               </template>
-              <dt v-if="expertLevel">{{ $t('admin_dash.frontend.build_url') }}</dt>
-              <dd v-if="expertLevel"><a :href="frontend.build_url" target="_blank">{{ frontend.build_url }}</a></dd>
+              <dt v-if="expertLevel">
+                {{ $t('admin_dash.frontend.build_url') }}
+              </dt>
+              <dd v-if="expertLevel">
+                <a
+                  :href="frontend.build_url"
+                  target="_blank"
+                >{{ frontend.build_url }}</a>
+              </dd>
             </dl>
             <div>
               <span class="btn-group">
@@ -62,7 +85,7 @@
                   @click="update(frontend)"
                 >
                   {{
-                      frontend.installed
+                    frontend.installed
                       ? $t('admin_dash.frontend.reinstall')
                       : $t('admin_dash.frontend.install')
                   }}
@@ -100,19 +123,22 @@
                   </template>
                 </Popover>
               </span>
-              <span class="btn-group" v-if="frontend.name !== 'admin-fe'">
+              <span
+                v-if="frontend.name !== 'admin-fe'"
+                class="btn-group"
+              >
                 <button
                   class="button button-default btn"
                   type="button"
                   :disabled="
-                             adminDraft[':pleroma'][':frontends'][':primary'].name === frontend.name &&
-                             adminDraft[':pleroma'][':frontends'][':primary'].ref === frontend.refs[0]
-                             "
+                    adminDraft[':pleroma'][':frontends'][':primary'].name === frontend.name &&
+                      adminDraft[':pleroma'][':frontends'][':primary'].ref === frontend.refs[0]
+                  "
                   :title="$t('admin_dash.frontend.update')"
                   @click="setDefault(frontend)"
                 >
                   {{
-                      $t('admin_dash.frontend.set_default')
+                    $t('admin_dash.frontend.set_default')
                   }}
                 </button>
                 {{ ' ' }}
diff --git a/src/components/settings_modal/helpers/attachment_setting.vue b/src/components/settings_modal/helpers/attachment_setting.vue
index cc2278b0..0bede2c2 100644
--- a/src/components/settings_modal/helpers/attachment_setting.vue
+++ b/src/components/settings_modal/helpers/attachment_setting.vue
@@ -3,7 +3,10 @@
     v-if="matchesExpertLevel"
     class="AttachmentSetting"
   >
-    <label :for="path" :class="{ 'faint': shouldBeDisabled }">
+    <label
+      :for="path"
+      :class="{ 'faint': shouldBeDisabled }"
+    >
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
@@ -51,10 +54,10 @@
           ref="mediaUpload"
           class="media-upload-icon"
           :drop-files="dropFiles"
-          @uploaded="setMediaFile"
-          @upload-failed="uploadFailed"
           normal-button
           :accept-types="acceptTypes"
+          @uploaded="setMediaFile"
+          @upload-failed="uploadFailed"
         />
       </div>
     </div>
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index ce168570..065cfbcf 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -3,7 +3,10 @@
     v-if="matchesExpertLevel"
     class="NumberSetting"
   >
-    <label :for="path" :class="{ 'faint': shouldBeDisabled }">
+    <label
+      :for="path"
+      :class="{ 'faint': shouldBeDisabled }"
+    >
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 84d0a9d6..9de99d78 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -3,7 +3,10 @@
     v-if="matchesExpertLevel"
     class="StringSetting"
   >
-    <label :for="path" :class="{ 'faint': shouldBeDisabled }">
+    <label
+      :for="path"
+      :class="{ 'faint': shouldBeDisabled }"
+    >
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue
index 57ec5535..4e7fd931 100644
--- a/src/components/settings_modal/settings_modal.vue
+++ b/src/components/settings_modal/settings_modal.vue
@@ -125,21 +125,24 @@
           id="unscrolled-content"
           class="extra-content"
         />
-        <span class="admin-buttons" v-if="modalMode === 'admin'">
+        <span
+          v-if="modalMode === 'admin'"
+          class="admin-buttons"
+        >
           <button
             class="button-default btn"
-            @click="resetAdminDraft"
             :disabled="!adminDraftAny"
+            @click="resetAdminDraft"
           >
-              {{ $t("admin_dash.reset_all") }}
+            {{ $t("admin_dash.reset_all") }}
           </button>
           {{ ' ' }}
           <button
             class="button-default btn"
-            @click="pushAdminDraft"
             :disabled="!adminDraftAny"
+            @click="pushAdminDraft"
           >
-              {{ $t("admin_dash.commit_all") }}
+            {{ $t("admin_dash.commit_all") }}
           </button>
         </span>
       </div>
-- 
cgit v1.2.3-70-g09d2


From 05a7e612aa6d9f2a44eea22266b325933da6f5ad Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 8 May 2023 21:10:06 +0300
Subject: show warning for developer for missing labels

---
 .../settings_modal/helpers/attachment_setting.vue        |  5 +++--
 .../settings_modal/helpers/boolean_setting.vue           | 16 +++++++++++++---
 src/components/settings_modal/helpers/number_setting.vue |  5 +++--
 src/components/settings_modal/helpers/string_setting.vue |  5 +++--
 4 files changed, 22 insertions(+), 9 deletions(-)

(limited to 'src/components/settings_modal/helpers/string_setting.vue')

diff --git a/src/components/settings_modal/helpers/attachment_setting.vue b/src/components/settings_modal/helpers/attachment_setting.vue
index 0bede2c2..447fa172 100644
--- a/src/components/settings_modal/helpers/attachment_setting.vue
+++ b/src/components/settings_modal/helpers/attachment_setting.vue
@@ -10,9 +10,10 @@
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
-      <template v-else>
-        <slot />
+      <template v-else-if="source === 'admin'">
+        MISSING LABEL FOR {{ path }}
       </template>
+      <slot v-else />
 
     </label>
     <p
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 3089c3b3..5ddf5aad 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -10,16 +10,16 @@
       @update:modelValue="update"
     >
       <span
-        v-if="!!$slots.default"
         class="label"
         :class="{ 'faint': shouldBeDisabled }"
       >
         <template v-if="backendDescriptionLabel">
           {{ backendDescriptionLabel }}
         </template>
-        <template v-else>
-          <slot />
+        <template v-else-if="source === 'admin'">
+          MISSING LABEL FOR {{ path }}
         </template>
+        <slot v-else />
       </span>
     </Checkbox>
     <ModifiedIndicator
@@ -35,6 +35,16 @@
     >
       {{ backendDescriptionDescription + ' ' }}
     </p>
+    <!-- debugging -->
+    <!--
+    <p
+      v-else
+      class="setting-description"
+      :class="{ 'faint': shouldBeDisabled }"
+    >
+      MISSING DESCRIPTION FOR {{ path }}
+    </p>
+    -->
   </label>
 </template>
 
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index 065cfbcf..93f11331 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -10,9 +10,10 @@
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
-      <template v-else>
-        <slot />
+      <template v-else-if="source === 'admin'">
+        MISSING LABEL FOR {{ path }}
       </template>
+      <slot v-else />
     </label>
     <input
       :id="path"
diff --git a/src/components/settings_modal/helpers/string_setting.vue b/src/components/settings_modal/helpers/string_setting.vue
index 9de99d78..0cfa61ce 100644
--- a/src/components/settings_modal/helpers/string_setting.vue
+++ b/src/components/settings_modal/helpers/string_setting.vue
@@ -10,9 +10,10 @@
       <template v-if="backendDescriptionLabel">
         {{ backendDescriptionLabel + ' ' }}
       </template>
-      <template v-else>
-        <slot />
+      <template v-else-if="source === 'admin'">
+        MISSING LABEL FOR {{ path }}
       </template>
+      <slot v-else />
     </label>
     <input
       :id="path"
-- 
cgit v1.2.3-70-g09d2

