Merge branch 'admin-tabs-2' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2025-12-11 18:31:26 +02:00
commit 30966210f4
15 changed files with 258 additions and 111 deletions

View file

@ -381,7 +381,6 @@ nav {
font-size: 1em;
font-family: sans-serif;
font-family: var(--font);
height: 2em;
&.-transparent {
backdrop-filter: blur(0.125em) contrast(60%);
@ -705,13 +704,8 @@ option {
position: relative;
display: inline-flex;
vertical-align: middle;
min-height: 2em;
align-items: end;
.input {
height: 2em;
}
> *,
> * .button-default {
--_roundness-left: 0;

View file

@ -13,8 +13,8 @@
</label>
<span class="setting-control btn-group">
<Select
:name="uniqueId+index"
:id="uniqueId+index"
:name="uniqueId+index"
class="language-select"
:model-value="controlledLanguage[index]"
@update:model-value="val => setLanguageAt(index, val)"

View file

@ -44,6 +44,7 @@
path=":pleroma.:instance.:instance_thumbnail"
/>
</li>
<h4>{{ $t('admin_dash.instance.pwa.manifest') }}</H4>
<li>
<PWAManifestIconsSetting path=":pleroma.:manifest.:icons" />
</li>

View file

@ -1,12 +1,69 @@
import { clone } from 'lodash'
import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
import Setting from './setting.js'
import Select from 'src/components/select/select.vue'
import Attachment from 'src/components/attachment/attachment.vue'
import MediaUpload from 'src/components/media_upload/media_upload.vue'
export default {
...Setting,
components: {
...Setting.components,
Select,
Attachment,
MediaUpload
},
computed: {
...Setting.computed,
purposeOptions () {
return ['any','monochrome','maskable'].map(value => ({
value,
key: value,
label: this.$t('admin_dash.instance.pwa.icon.' + value)
}))
}
},
methods: {
...Setting.methods,
optionPresent (option) {
return this.valueSet.has(option)
attachment (e) {
const path = e[':src']
if (!path) {
return {
mimetype: '',
url: ''
}
}
const url = path.includes('://') ? path : this.$store.state.instance.server + path
return {
mimetype: fileTypeExt(url),
url
}
},
setMediaFile ({ event, index }) {
this.update({
event: {
target: {
value: event.url
},
},
index,
eventType: 'edit',
field: ':src'
})
},
setPurpose ({ event, index }) {
this.update({
event: {
target: {
value: event
},
},
index,
eventType: 'edit',
field: ':purpose'
})
},
getValue ({ event, field, index, eventType }) {
switch (eventType) {
@ -27,7 +84,6 @@ export default {
const post = this.visibleState.slice(index + 1)
const item = clone(this.visibleState[index])
const string = event.target.value
console.log(item)
if (!string) {
delete item[field]
@ -35,8 +91,6 @@ export default {
item[field] = string
}
console.log(item)
return [...pre, item, ...post]
}
}

View file

@ -7,6 +7,12 @@
class="pwa-label setting-label"
:class="{ 'faint': shouldBeDisabled }"
>
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
{{ ' ' }}
<template v-if="backendDescriptionLabel">
{{ backendDescriptionLabel + ' ' }}
</template>
@ -22,106 +28,130 @@
>
{{ backendDescriptionDescription + ' ' }}
</p>
<ul class="setting-list setting-control">
<li
v-for="(item, index) in visibleState"
:key="index"
>
<div class="setting-item">
<dl>
<dt><code>purpose</code></dt>
<dd>
<input
class="input string-input"
<div class="setting-control">
<ul class="item-list">
<li
v-if="visibleState.length === 0"
class="no_items"
>
{{ $t('admin_dash.instance.pwa.no_icons') }}
<button
v-if="visibleState.length === 0"
class="button-default add-button"
@click="e => update({ eventType: 'add' })"
>
<FAIcon icon="plus" />
</button>
</li>
<li
v-for="(item, index) in visibleState"
:key="index"
>
<div class="icon-element">
<div class="src-field">
<Attachment
class="src-attachment"
:compact="compact"
:attachment="attachment(item)"
size="small"
hide-description
/>
<div class="src-url">
<label for="path">{{ $t('settings.url') }}</label>
<input
:id="path"
class="input string-input"
:disabled="shouldBeDisabled"
:value="item[':src']"
@change="event => update({ event, index, eventType: 'edit', field: ':src' })"
>
</div>
<MediaUpload
ref="mediaUpload"
class="src-upload media-upload-icon"
:class="{ disabled: shouldBeDisabled }"
:value="item[':purpose']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':purpose' })"
normal-button
:accept-types="acceptTypes"
@uploaded="event => setMediaFile({ event, index })"
/>
</div>
<dl>
<dt>{{ $t('admin_dash.instance.pwa.icon.purpose') }}</dt>
<dd>
<Select
:class="{ disabled: shouldBeDisabled }"
:disabled="shouldBeDisabled"
:model-value="item[':purpose']"
@update:model-value="event => setPurpose({ event, index })"
>
<option
v-for="(purpose, index) in purposeOptions"
:key="index"
:value="purpose.value"
>
{{ purpose.label }}
</option>
</Select>
</dd>
<dt><code>sizes</code>{{ $t('admin_dash.instance.pwa.optional') }}</dt>
<dd>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item[':sizes']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':sizes' })"
>
</dd>
<dt><code>type</code>{{ $t('admin_dash.instance.pwa.optional') }}</dt>
<dd>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item[':type']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':type' })"
>
</dd>
</dl>
<div class="buttons">
<button
v-if="index === visibleState.length - 1"
class="button-default add-button"
@click="e => update({ eventType: 'add' })"
>
</dd>
<dt><code>sizes</code></dt>
<dd>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item[':sizes']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':sizes' })"
<FAIcon icon="plus" />
</button>
<button
class="button-default delete-button"
@click="e => update({ index, eventType: 'remove' })"
>
</dd>
<dt><code>src</code></dt>
<dd>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item[':src']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':src' })"
>
</dd>
<dt><code>type</code></dt>
<dd>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item[':type']"
@change="e => update({ event: e, index, eventType: 'edit', field: ':type' })"
>
</dd>
</dl>
<div class="buttons">
<button
v-if="index === visibleState.length - 1"
class="button-default add-button"
@click="e => update({ eventType: 'add' })"
>
<FAIcon icon="plus" />
</button>
<button
class="button-default delete-button"
@click="e => update({ index, eventType: 'remove' })"
>
<FAIcon icon="times" />
</button>
<FAIcon icon="times" />
</button>
</div>
</div>
</div>
</li>
</ul>
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
</li>
</ul>
</div>
<DraftButtons />
</div>
</template>
<script src="./pwa_manifest_icons_setting.js"></script>
<style lang="scss">
.PWAManifestIconsSetting {
div.PWAManifestIconsSetting {
&.setting-item {
display: grid;
grid-template-areas:
"label control"
"desc control"
". draft";
"label"
"desc"
"control"
"draft";
grid-template-rows: 2em auto 1fr;
grid-template-columns: 1fr;
}
.pwa-label.setting-label {
align-self: end;
}
.setting-description {
text-align: right;
align-self: start;
}
.setting-list {
display: grid;
gap: 0.5em;
}
.setting-item {
display: inline-block;
text-align: left;
}
.buttons {
@ -135,16 +165,22 @@
}
}
ul {
list-style: none;
display: grid;
grid-template-columns: repeat(auto-fit, 12em);
grid-gap: 2em;
}
dl {
display: inline-grid;
grid-template-columns: auto auto;
gap: 0.5em;
display: grid;
grid-template-columns: 1fr;
margin-top: 0.5em;
gap: 0.25em;
align-items: baseline;
dt {
display: inline;
font-weight: 800;
text-align: right;
&::after {
content: ':'
@ -152,9 +188,38 @@
}
dd {
display: inline;
margin: 0
}
}
.src-field {
display: grid;
grid-template-columns: auto;
justify-items: center;
gap: 0.5em;
.src-attachment {
width: 10em;
height: 10em;
display: block;
margin-bottom: 0.5em;
}
.src-upload {
display: block;
width: 100%;
}
.src-url {
display: flex;
flex-direction: column;
gap: 0.25em;
width: 100%;
label {
display: block;
}
}
}
}
</style>

View file

@ -87,13 +87,13 @@
</table>
<Checkbox
:model-value="isSeparate"
@update:model-value="event => update({ event: event ? 'join' : 'split', eventType: 'toggleMode' })"
@update:model-value="event => update({ event: event ? 'join' : 'split', eventType: 'toggleMode' })"
>
{{ $t('admin_dash.rate_limit.separate') }}
</Checkbox>
</div>
<DraftButtons />
</div>
<DraftButtons />
</div>
</template>
<script src="./rate_setting.js"></script>

View file

@ -161,7 +161,6 @@ export default {
}
},
backendDescriptionDescription () {
console.log('LOL', this.description)
if (this.description) return this.description
if (this.realSource !== 'admin') return ''
if (this.hideDescription) return null

View file

@ -1,7 +1,7 @@
<template>
<span
class="setting-item"
v-if="matchesExpertLevel"
class="setting-item"
>
<label
v-if="!hideLabel"

View file

@ -208,10 +208,11 @@
}
}
/* stylelint-disable no-descending-specificity */
.setting-item {
grid-template-columns: 1fr min-content;
column-gap: 0.5em;
padding: 1em 1em;
padding: 1em;
align-items: center;
.setting-label {
@ -229,6 +230,8 @@
}
}
.setting-list:not(.suboptions),
.option-list {
&.two-column {

View file

@ -4,7 +4,10 @@
<h3>{{ $t('settings.general') }}</h3>
<ul class="setting-list">
<li>
<label class="setting-item " for="default-vis">
<label
class="setting-item "
for="default-vis"
>
<span class="setting-label">
<ProfileSettingIndicator :is-profile="true" />
{{ $t('settings.default_vis') }}

View file

@ -54,8 +54,8 @@
</span>
<Select
id="onBlockDefaultActionLv1"
class="setting-control"
v-model="onBlockDefaultActionLv1"
class="setting-control"
>
<option
v-for="option in muteBlockLv1Options"

View file

@ -142,7 +142,9 @@
class="setting-list"
>
<li class="select-multiple">
<h4 class="label">{{ $t('settings.confirm_dialogs') }}</h4>
<h4 class="label">
{{ $t('settings.confirm_dialogs') }}
</h4>
<ul class="option-list">
<li>
<BooleanSetting path="modalOnRepeat">

View file

@ -40,8 +40,8 @@
<li>
<h4> {{ $t('settings.notification_visibility') }}</h4>
<p
class="sidenote"
v-if="expertLevel > 0"
class="sidenote"
>
{{ $t('settings.notification_setting_filters_chrome_push') }}
</p>

View file

@ -13,8 +13,8 @@
<li>
<div class="setting-item">
<Checkbox
class="setting-label setting-control custom-boolean-setting"
v-model="locked"
class="setting-label setting-control custom-boolean-setting"
>
<ProfileSettingIndicator :is-profile="true" />
{{ $t('settings.lock_account_description') }}

View file

@ -1391,6 +1391,32 @@
"always": "Always",
"never": "Never"
},
"instance": {
"instance": "Instance information",
"pwa": {
"manifest": "PWA Manifest",
"optional": "(optional)",
"no_icons": "No icons defined",
"icon": {
"purpose": "Icon purpose",
"any": "Any",
"monochrome": "Monochrome",
"maskable": "Maskable"
}
},
"branding": "Branding",
"access": "Instance access",
"rich_metadata": "Metadata",
"restrict": {
"header": "Restrict access for anonymous visitors",
"description": "Detailed setting for allowing/disallowing access to certain aspects of API. By default (indeterminate state) it will disallow if instance is not public, ticked checkbox means disallow access even if instance is public, unticked means allow access even if instance is private. Please note that unexpected behavior might happen if some settings are set, i.e. if profile access is disabled posts will show without profile information.",
"timelines": "Timelines access",
"profiles": "User profiles access",
"activities": "Statuses/activities access"
},
":unauthenticated": "Unauthenticated",
":all": "Everyone"
},
"temp_overrides": {
":pleroma": {
":connections_pool": {