enhance(client): tweak ui

This commit is contained in:
syuilo 2021-12-30 21:47:48 +09:00
parent e159f15600
commit 616b18a9e5
21 changed files with 393 additions and 323 deletions

View File

@ -743,7 +743,7 @@ online: "オンライン"
active: "アクティブ" active: "アクティブ"
offline: "オフライン" offline: "オフライン"
notRecommended: "非推奨" notRecommended: "非推奨"
botProtection: "Bot防御" botProtection: "Botプロテクション"
instanceBlocking: "インスタンスブロック" instanceBlocking: "インスタンスブロック"
selectAccount: "アカウントを選択" selectAccount: "アカウントを選択"
enabled: "有効" enabled: "有効"
@ -754,7 +754,7 @@ administration: "管理"
accounts: "アカウント" accounts: "アカウント"
switch: "切り替え" switch: "切り替え"
noMaintainerInformationWarning: "管理者情報が設定されていません。" noMaintainerInformationWarning: "管理者情報が設定されていません。"
noBotProtectionWarning: "Bot防御が設定されていません。" noBotProtectionWarning: "Botプロテクションが設定されていません。"
configure: "設定する" configure: "設定する"
postToGallery: "ギャラリーへ投稿" postToGallery: "ギャラリーへ投稿"
gallery: "ギャラリー" gallery: "ギャラリー"

View File

@ -1,3 +1,5 @@
/// <reference types="vue/macros-global" />
declare module '*.vue' { declare module '*.vue' {
import type { DefineComponent } from 'vue'; import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>; const component: DefineComponent<{}, {}, any>;

View File

@ -116,7 +116,7 @@
"v-debounce": "0.1.2", "v-debounce": "0.1.2",
"vanilla-tilt": "1.7.2", "vanilla-tilt": "1.7.2",
"vue": "3.2.26", "vue": "3.2.26",
"vue-loader": "16.8.3", "vue-loader": "17.0.0",
"vue-prism-editor": "2.0.0-alpha.2", "vue-prism-editor": "2.0.0-alpha.2",
"vue-router": "4.0.5", "vue-router": "4.0.5",
"vue-style-loader": "4.1.3", "vue-style-loader": "4.1.3",

View File

@ -7,12 +7,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
export default defineComponent({
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -0,0 +1,27 @@
<template>
<div class="terlnhxf _formBlock">
<slot></slot>
</div>
</template>
<script lang="ts" setup>
const props = withDefaults(defineProps<{
minWidth: number;
}>(), {
minWidth: 210,
});
const minWidth = props.minWidth + 'px';
</script>
<style lang="scss" scoped>
.terlnhxf {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(v-bind('minWidth'), 1fr));
grid-gap: 12px;
> ::v-deep(*) {
margin: 0 !important;
}
}
</style>

View File

@ -13,7 +13,8 @@
<i class="check fas fa-check"></i> <i class="check fas fa-check"></i>
</span> </span>
<span class="label"> <span class="label">
<span @click="toggle"><slot></slot></span> <!-- TODO: 無名slotの方は廃止 -->
<span @click="toggle"><slot name="label"></slot><slot></slot></span>
<p class="caption"><slot name="caption"></slot></p> <p class="caption"><slot name="caption"></slot></p>
</span> </span>
</div> </div>

View File

@ -1,5 +1,5 @@
<template> <template>
<XModalWindow ref="dialog" <XModalWindow ref="dialogEl"
:with-ok-button="true" :with-ok-button="true"
:ok-button-disabled="selected == null" :ok-button-disabled="selected == null"
@click="cancel()" @click="cancel()"
@ -8,20 +8,20 @@
@closed="$emit('closed')" @closed="$emit('closed')"
> >
<template #header>{{ $ts.selectUser }}</template> <template #header>{{ $ts.selectUser }}</template>
<div class="tbhwbxda _monolithic_"> <div class="tbhwbxda">
<div class="_section"> <div class="form">
<div class="_inputSplit"> <FormSplit :min-width="170">
<MkInput ref="username" v-model="username" class="input" @update:modelValue="search"> <MkInput ref="usernameEl" v-model="username" @update:modelValue="search">
<template #label>{{ $ts.username }}</template> <template #label>{{ $ts.username }}</template>
<template #prefix>@</template> <template #prefix>@</template>
</MkInput> </MkInput>
<MkInput v-model="host" class="input" @update:modelValue="search"> <MkInput v-model="host" @update:modelValue="search">
<template #label>{{ $ts.host }}</template> <template #label>{{ $ts.host }}</template>
<template #prefix>@</template> <template #prefix>@</template>
</MkInput> </MkInput>
</FormSplit>
</div> </div>
</div> <div v-if="username != '' || host != ''" class="result" :class="{ hit: users.length > 0 }">
<div v-if="username != '' || host != ''" class="_section result" :class="{ hit: users.length > 0 }">
<div v-if="users.length > 0" class="users"> <div v-if="users.length > 0" class="users">
<div v-for="user in users" :key="user.id" class="user" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()"> <div v-for="user in users" :key="user.id" class="user" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/> <MkAvatar :user="user" class="avatar" :show-indicator="true"/>
@ -35,7 +35,7 @@
<span>{{ $ts.noUsers }}</span> <span>{{ $ts.noUsers }}</span>
</div> </div>
</div> </div>
<div v-if="username == '' && host == ''" class="_section recent"> <div v-if="username == '' && host == ''" class="recent">
<div class="users"> <div class="users">
<div v-for="user in recentUsers" :key="user.id" class="user" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()"> <div v-for="user in recentUsers" :key="user.id" class="user" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/> <MkAvatar :user="user" class="avatar" :show-indicator="true"/>
@ -50,87 +50,89 @@
</XModalWindow> </XModalWindow>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { nextTick, onMounted } from 'vue';
import MkInput from './form/input.vue'; import * as misskey from 'misskey-js';
import MkInput from '@/components/form/input.vue';
import FormSplit from '@/components/form/split.vue';
import XModalWindow from '@/components/ui/modal-window.vue'; import XModalWindow from '@/components/ui/modal-window.vue';
import * as os from '@/os'; import * as os from '@/os';
import { defaultStore } from '@/store';
export default defineComponent({ const emit = defineEmits<{
components: { (e: 'ok', selected: misskey.entities.UserDetailed): void;
MkInput, (e: 'cancel'): void;
XModalWindow, (e: 'closed'): void;
}, }>();
props: { let username = $ref('');
}, let host = $ref('');
let users: misskey.entities.UserDetailed[] = $ref([]);
let recentUsers: misskey.entities.UserDetailed[] = $ref([]);
let selected: misskey.entities.UserDetailed | null = $ref(null);
let usernameEl: HTMLElement = $ref();
let dialogEl = $ref();
emits: ['ok', 'cancel', 'closed'], const focus = () => {
if (usernameEl) {
data() { usernameEl.focus();
return { }
username: '',
host: '',
recentUsers: [],
users: [],
selected: null,
}; };
},
async mounted() { const search = () => {
this.focus(); if (username === '' && host === '') {
users = [];
this.$nextTick(() => {
this.focus();
});
this.recentUsers = await os.api('users/show', {
userIds: this.$store.state.recentlyUsedUsers
});
},
methods: {
search() {
if (this.username == '' && this.host == '') {
this.users = [];
return; return;
} }
os.api('users/search-by-username-and-host', { os.api('users/search-by-username-and-host', {
username: this.username, username: username,
host: this.host, host: host,
limit: 10, limit: 10,
detail: false detail: false
}).then(users => { }).then(_users => {
this.users = users; users = _users;
}); });
}, };
focus() { const ok = () => {
this.$refs.username.focus(); if (selected == null) return;
}, emit('ok', selected);
dialogEl.close();
ok() {
this.$emit('ok', this.selected);
this.$refs.dialog.close();
// 使 // 使
let recents = this.$store.state.recentlyUsedUsers; let recents = defaultStore.state.recentlyUsedUsers;
recents = recents.filter(x => x !== this.selected.id); recents = recents.filter(x => x !== selected.id);
recents.unshift(this.selected.id); recents.unshift(selected.id);
this.$store.set('recentlyUsedUsers', recents.splice(0, 16)); defaultStore.set('recentlyUsedUsers', recents.splice(0, 16));
}, };
cancel() { const cancel = () => {
this.$emit('cancel'); emit('cancel');
this.$refs.dialog.close(); dialogEl.close();
}, };
}
onMounted(() => {
focus();
nextTick(() => {
focus();
});
os.api('users/show', {
userIds: defaultStore.state.recentlyUsedUsers,
}).then(users => {
recentUsers = users;
});
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.tbhwbxda { .tbhwbxda {
> ._section { > .form {
padding: 0 var(--root-margin);
}
> .result, > .recent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: auto; overflow: auto;

View File

@ -24,7 +24,7 @@
</FormSection> </FormSection>
<FormSection> <FormSection>
<div class="_inputSplit _formBlock"> <FormSplit>
<MkKeyValue class="_formBlock"> <MkKeyValue class="_formBlock">
<template #key>{{ $ts.administrator }}</template> <template #key>{{ $ts.administrator }}</template>
<template #value>{{ $instance.maintainerName }}</template> <template #value>{{ $instance.maintainerName }}</template>
@ -33,14 +33,14 @@
<template #key>{{ $ts.contact }}</template> <template #key>{{ $ts.contact }}</template>
<template #value>{{ $instance.maintainerEmail }}</template> <template #value>{{ $instance.maintainerEmail }}</template>
</MkKeyValue> </MkKeyValue>
</div> </FormSplit>
<FormLink v-if="$instance.tosUrl" :to="$instance.tosUrl" class="_formBlock" external>{{ $ts.tos }}</FormLink> <FormLink v-if="$instance.tosUrl" :to="$instance.tosUrl" class="_formBlock" external>{{ $ts.tos }}</FormLink>
</FormSection> </FormSection>
<FormSuspense :p="initStats"> <FormSuspense :p="initStats">
<FormSection> <FormSection>
<template #label>{{ $ts.statistics }}</template> <template #label>{{ $ts.statistics }}</template>
<div class="_inputSplit"> <FormSplit>
<MkKeyValue class="_formBlock"> <MkKeyValue class="_formBlock">
<template #key>{{ $ts.users }}</template> <template #key>{{ $ts.users }}</template>
<template #value>{{ number(stats.originalUsersCount) }}</template> <template #value>{{ number(stats.originalUsersCount) }}</template>
@ -49,7 +49,7 @@
<template #key>{{ $ts.notes }}</template> <template #key>{{ $ts.notes }}</template>
<template #value>{{ number(stats.originalNotesCount) }}</template> <template #value>{{ number(stats.originalNotesCount) }}</template>
</MkKeyValue> </MkKeyValue>
</div> </FormSplit>
</FormSection> </FormSection>
</FormSuspense> </FormSuspense>
@ -73,6 +73,7 @@ import { version, instanceName } from '@/config';
import FormLink from '@/components/form/link.vue'; import FormLink from '@/components/form/link.vue';
import FormSection from '@/components/form/section.vue'; import FormSection from '@/components/form/section.vue';
import FormSuspense from '@/components/form/suspense.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormSplit from '@/components/form/split.vue';
import MkKeyValue from '@/components/key-value.vue'; import MkKeyValue from '@/components/key-value.vue';
import * as os from '@/os'; import * as os from '@/os';
import number from '@/filters/number'; import number from '@/filters/number';
@ -85,6 +86,7 @@ export default defineComponent({
FormSection, FormSection,
FormLink, FormLink,
FormSuspense, FormSuspense,
FormSplit,
}, },
data() { data() {

View File

@ -23,14 +23,14 @@
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio> <MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
</div> </div>
--> -->
<div class="_inputSplit"> <FormSplit>
<MkInput v-model="ad.ratio" type="number"> <MkInput v-model="ad.ratio" type="number">
<template #label>{{ $ts.ratio }}</template> <template #label>{{ $ts.ratio }}</template>
</MkInput> </MkInput>
<MkInput v-model="ad.expiresAt" type="date"> <MkInput v-model="ad.expiresAt" type="date">
<template #label>{{ $ts.expiration }}</template> <template #label>{{ $ts.expiration }}</template>
</MkInput> </MkInput>
</div> </FormSplit>
<MkTextarea v-model="ad.memo" class="_formBlock"> <MkTextarea v-model="ad.memo" class="_formBlock">
<template #label>{{ $ts.memo }}</template> <template #label>{{ $ts.memo }}</template>
</MkTextarea> </MkTextarea>
@ -49,6 +49,7 @@ import MkButton from '@/components/ui/button.vue';
import MkInput from '@/components/form/input.vue'; import MkInput from '@/components/form/input.vue';
import MkTextarea from '@/components/form/textarea.vue'; import MkTextarea from '@/components/form/textarea.vue';
import FormRadios from '@/components/form/radios.vue'; import FormRadios from '@/components/form/radios.vue';
import FormSplit from '@/components/form/split.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
@ -58,6 +59,7 @@ export default defineComponent({
MkInput, MkInput,
MkTextarea, MkTextarea,
FormRadios, FormRadios,
FormSplit,
}, },
emits: ['info'], emits: ['info'],

View File

@ -1,50 +1,55 @@
<template> <template>
<FormBase> <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormSwitch v-model="enableEmail">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></FormSwitch> <div class="_formRoot">
<FormSwitch v-model="enableEmail" class="_formBlock">
<template #label>{{ $ts.enableEmail }}</template>
<template #caption>{{ $ts.emailConfigInfo }}</template>
</FormSwitch>
<template v-if="enableEmail"> <template v-if="enableEmail">
<FormInput v-model="email" type="email"> <FormInput v-model="email" type="email" class="_formBlock">
<span>{{ $ts.emailAddress }}</span> <template #label>{{ $ts.emailAddress }}</template>
</FormInput> </FormInput>
<div v-sticky-container class="_debobigegoItem _debobigegoNoConcat"> <FormSection>
<div class="_debobigegoLabel">{{ $ts.smtpConfig }}</div> <template #label>{{ $ts.smtpConfig }}</template>
<div class="main"> <FormSplit :min-width="280">
<FormInput v-model="smtpHost"> <FormInput v-model="smtpHost" class="_formBlock">
<span>{{ $ts.smtpHost }}</span> <template #label>{{ $ts.smtpHost }}</template>
</FormInput> </FormInput>
<FormInput v-model="smtpPort" type="number"> <FormInput v-model="smtpPort" type="number" class="_formBlock">
<span>{{ $ts.smtpPort }}</span> <template #label>{{ $ts.smtpPort }}</template>
</FormInput> </FormInput>
<FormInput v-model="smtpUser"> </FormSplit>
<span>{{ $ts.smtpUser }}</span> <FormSplit :min-width="280">
<FormInput v-model="smtpUser" class="_formBlock">
<template #label>{{ $ts.smtpUser }}</template>
</FormInput> </FormInput>
<FormInput v-model="smtpPass" type="password"> <FormInput v-model="smtpPass" type="password" class="_formBlock">
<span>{{ $ts.smtpPass }}</span> <template #label>{{ $ts.smtpPass }}</template>
</FormInput> </FormInput>
<FormInfo>{{ $ts.emptyToDisableSmtpAuth }}</FormInfo> </FormSplit>
<FormSwitch v-model="smtpSecure">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></FormSwitch> <FormInfo class="_formBlock">{{ $ts.emptyToDisableSmtpAuth }}</FormInfo>
</div> <FormSwitch v-model="smtpSecure" class="_formBlock">
</div> <template #label>{{ $ts.smtpSecure }}</template>
<template #caption>{{ $ts.smtpSecureInfo }}</template>
<FormButton @click="testEmail">{{ $ts.testEmail }}</FormButton> </FormSwitch>
</FormSection>
</template> </template>
</div>
<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense> </FormSuspense>
</FormBase> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import FormSwitch from '@/components/debobigego/switch.vue'; import FormSwitch from '@/components/form/switch.vue';
import FormInput from '@/components/debobigego/input.vue'; import FormInput from '@/components/form/input.vue';
import FormButton from '@/components/debobigego/button.vue'; import FormInfo from '@/components/ui/info.vue';
import FormBase from '@/components/debobigego/base.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormGroup from '@/components/debobigego/group.vue'; import FormSplit from '@/components/form/split.vue';
import FormInfo from '@/components/debobigego/info.vue'; import FormSection from '@/components/form/section.vue';
import FormSuspense from '@/components/debobigego/suspense.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
@ -53,9 +58,8 @@ export default defineComponent({
components: { components: {
FormSwitch, FormSwitch,
FormInput, FormInput,
FormBase, FormSplit,
FormGroup, FormSection,
FormButton,
FormInfo, FormInfo,
FormSuspense, FormSuspense,
}, },
@ -68,6 +72,16 @@ export default defineComponent({
title: this.$ts.emailServer, title: this.$ts.emailServer,
icon: 'fas fa-envelope', icon: 'fas fa-envelope',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{
asFullButton: true,
text: this.$ts.testEmail,
handler: this.testEmail,
}, {
asFullButton: true,
icon: 'fas fa-check',
text: this.$ts.save,
handler: this.save,
}],
}, },
enableEmail: false, enableEmail: false,
email: null, email: null,

View File

@ -23,7 +23,7 @@
</div> </div>
<div v-else-if="tab === 'remote'" class="remote"> <div v-else-if="tab === 'remote'" class="remote">
<div class="_inputSplit"> <FormSplit>
<MkInput v-model="queryRemote" :debounce="true" type="search"> <MkInput v-model="queryRemote" :debounce="true" type="search">
<template #prefix><i class="fas fa-search"></i></template> <template #prefix><i class="fas fa-search"></i></template>
<template #label>{{ $ts.search }}</template> <template #label>{{ $ts.search }}</template>
@ -31,7 +31,7 @@
<MkInput v-model="host" :debounce="true"> <MkInput v-model="host" :debounce="true">
<template #label>{{ $ts.host }}</template> <template #label>{{ $ts.host }}</template>
</MkInput> </MkInput>
</div> </FormSplit>
<MkPagination ref="remoteEmojis" :pagination="remotePagination"> <MkPagination ref="remoteEmojis" :pagination="remotePagination">
<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> <template #empty><span>{{ $ts.noCustomEmojis }}</span></template>
<template v-slot="{items}"> <template v-slot="{items}">
@ -57,6 +57,7 @@ import MkButton from '@/components/ui/button.vue';
import MkInput from '@/components/form/input.vue'; import MkInput from '@/components/form/input.vue';
import MkPagination from '@/components/ui/pagination.vue'; import MkPagination from '@/components/ui/pagination.vue';
import MkTab from '@/components/tab.vue'; import MkTab from '@/components/tab.vue';
import FormSplit from '@/components/form/split.vue';
import { selectFiles } from '@/scripts/select-file'; import { selectFiles } from '@/scripts/select-file';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
@ -67,6 +68,7 @@ export default defineComponent({
MkButton, MkButton,
MkInput, MkInput,
MkPagination, MkPagination,
FormSplit,
}, },
emits: ['info'], emits: ['info'],

View File

@ -1,41 +1,41 @@
<template> <template>
<FormBase> <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormSwitch v-model="cacheRemoteFiles"> <div class="_formRoot">
{{ $ts.cacheRemoteFiles }} <FormSwitch v-model="cacheRemoteFiles" class="_formBlock">
<template #desc>{{ $ts.cacheRemoteFilesDescription }}</template> <template #label>{{ $ts.cacheRemoteFiles }}</template>
<template #caption>{{ $ts.cacheRemoteFilesDescription }}</template>
</FormSwitch> </FormSwitch>
<FormSwitch v-model="proxyRemoteFiles"> <FormSwitch v-model="proxyRemoteFiles" class="_formBlock">
{{ $ts.proxyRemoteFiles }} <template #label>{{ $ts.proxyRemoteFiles }}</template>
<template #desc>{{ $ts.proxyRemoteFilesDescription }}</template> <template #caption>{{ $ts.proxyRemoteFilesDescription }}</template>
</FormSwitch> </FormSwitch>
<FormInput v-model="localDriveCapacityMb" type="number"> <FormSplit :min-width="280">
<span>{{ $ts.driveCapacityPerLocalAccount }}</span> <FormInput v-model="localDriveCapacityMb" type="number" class="_formBlock">
<template #label>{{ $ts.driveCapacityPerLocalAccount }}</template>
<template #suffix>MB</template> <template #suffix>MB</template>
<template #desc>{{ $ts.inMb }}</template> <template #caption>{{ $ts.inMb }}</template>
</FormInput> </FormInput>
<FormInput v-model="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles"> <FormInput v-model="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles" class="_formBlock">
<span>{{ $ts.driveCapacityPerRemoteAccount }}</span> <template #label>{{ $ts.driveCapacityPerRemoteAccount }}</template>
<template #suffix>MB</template> <template #suffix>MB</template>
<template #desc>{{ $ts.inMb }}</template> <template #caption>{{ $ts.inMb }}</template>
</FormInput> </FormInput>
</FormSplit>
<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> </div>
</FormSuspense> </FormSuspense>
</FormBase> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import FormSwitch from '@/components/debobigego/switch.vue'; import FormSwitch from '@/components/form/switch.vue';
import FormInput from '@/components/debobigego/input.vue'; import FormInput from '@/components/form/input.vue';
import FormButton from '@/components/debobigego/button.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormBase from '@/components/debobigego/base.vue'; import FormSplit from '@/components/form/split.vue';
import FormGroup from '@/components/debobigego/group.vue';
import FormSuspense from '@/components/debobigego/suspense.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
@ -44,9 +44,7 @@ export default defineComponent({
components: { components: {
FormSwitch, FormSwitch,
FormInput, FormInput,
FormBase, FormSplit,
FormGroup,
FormButton,
FormSuspense, FormSuspense,
}, },
@ -58,6 +56,12 @@ export default defineComponent({
title: this.$ts.files, title: this.$ts.files,
icon: 'fas fa-cloud', icon: 'fas fa-cloud',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{
asFullButton: true,
icon: 'fas fa-check',
text: this.$ts.save,
handler: this.save,
}],
}, },
cacheRemoteFiles: false, cacheRemoteFiles: false,
proxyRemoteFiles: false, proxyRemoteFiles: false,

View File

@ -3,7 +3,7 @@
<div v-if="!narrow || page == null" class="nav"> <div v-if="!narrow || page == null" class="nav">
<MkHeader :info="header"></MkHeader> <MkHeader :info="header"></MkHeader>
<MkSpacer :content-max="700"> <MkSpacer :content-max="700" :margin-min="16">
<div class="lxpfedzu"> <div class="lxpfedzu">
<div class="banner"> <div class="banner">
<img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> <img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/>

View File

@ -1,76 +1,78 @@
<template> <template>
<FormBase> <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormSwitch v-model="useObjectStorage">{{ $ts.useObjectStorage }}</FormSwitch> <div class="_formRoot">
<FormSwitch v-model="useObjectStorage" class="_formBlock">{{ $ts.useObjectStorage }}</FormSwitch>
<template v-if="useObjectStorage"> <template v-if="useObjectStorage">
<FormInput v-model="objectStorageBaseUrl"> <FormInput v-model="objectStorageBaseUrl" class="_formBlock">
<span>{{ $ts.objectStorageBaseUrl }}</span> <template #label>{{ $ts.objectStorageBaseUrl }}</template>
<template #desc>{{ $ts.objectStorageBaseUrlDesc }}</template> <template #caption>{{ $ts.objectStorageBaseUrlDesc }}</template>
</FormInput> </FormInput>
<FormInput v-model="objectStorageBucket"> <FormInput v-model="objectStorageBucket" class="_formBlock">
<span>{{ $ts.objectStorageBucket }}</span> <template #label>{{ $ts.objectStorageBucket }}</template>
<template #desc>{{ $ts.objectStorageBucketDesc }}</template> <template #caption>{{ $ts.objectStorageBucketDesc }}</template>
</FormInput> </FormInput>
<FormInput v-model="objectStoragePrefix"> <FormInput v-model="objectStoragePrefix" class="_formBlock">
<span>{{ $ts.objectStoragePrefix }}</span> <template #label>{{ $ts.objectStoragePrefix }}</template>
<template #desc>{{ $ts.objectStoragePrefixDesc }}</template> <template #caption>{{ $ts.objectStoragePrefixDesc }}</template>
</FormInput> </FormInput>
<FormInput v-model="objectStorageEndpoint"> <FormInput v-model="objectStorageEndpoint" class="_formBlock">
<span>{{ $ts.objectStorageEndpoint }}</span> <template #label>{{ $ts.objectStorageEndpoint }}</template>
<template #desc>{{ $ts.objectStorageEndpointDesc }}</template> <template #caption>{{ $ts.objectStorageEndpointDesc }}</template>
</FormInput> </FormInput>
<FormInput v-model="objectStorageRegion"> <FormInput v-model="objectStorageRegion" class="_formBlock">
<span>{{ $ts.objectStorageRegion }}</span> <template #label>{{ $ts.objectStorageRegion }}</template>
<template #desc>{{ $ts.objectStorageRegionDesc }}</template> <template #caption>{{ $ts.objectStorageRegionDesc }}</template>
</FormInput> </FormInput>
<FormInput v-model="objectStorageAccessKey"> <FormSplit :min-width="280">
<FormInput v-model="objectStorageAccessKey" class="_formBlock">
<template #prefix><i class="fas fa-key"></i></template> <template #prefix><i class="fas fa-key"></i></template>
<span>Access key</span> <template #label>Access key</template>
</FormInput> </FormInput>
<FormInput v-model="objectStorageSecretKey"> <FormInput v-model="objectStorageSecretKey" class="_formBlock">
<template #prefix><i class="fas fa-key"></i></template> <template #prefix><i class="fas fa-key"></i></template>
<span>Secret key</span> <template #label>Secret key</template>
</FormInput> </FormInput>
</FormSplit>
<FormSwitch v-model="objectStorageUseSSL"> <FormSwitch v-model="objectStorageUseSSL" class="_formBlock">
{{ $ts.objectStorageUseSSL }} <template #label>{{ $ts.objectStorageUseSSL }}</template>
<template #desc>{{ $ts.objectStorageUseSSLDesc }}</template> <template #caption>{{ $ts.objectStorageUseSSLDesc }}</template>
</FormSwitch> </FormSwitch>
<FormSwitch v-model="objectStorageUseProxy"> <FormSwitch v-model="objectStorageUseProxy" class="_formBlock">
{{ $ts.objectStorageUseProxy }} <template #label>{{ $ts.objectStorageUseProxy }}</template>
<template #desc>{{ $ts.objectStorageUseProxyDesc }}</template> <template #caption>{{ $ts.objectStorageUseProxyDesc }}</template>
</FormSwitch> </FormSwitch>
<FormSwitch v-model="objectStorageSetPublicRead"> <FormSwitch v-model="objectStorageSetPublicRead" class="_formBlock">
{{ $ts.objectStorageSetPublicRead }} <template #label>{{ $ts.objectStorageSetPublicRead }}</template>
</FormSwitch> </FormSwitch>
<FormSwitch v-model="objectStorageS3ForcePathStyle"> <FormSwitch v-model="objectStorageS3ForcePathStyle" class="_formBlock">
s3ForcePathStyle <template #label>s3ForcePathStyle</template>
</FormSwitch> </FormSwitch>
</template> </template>
</div>
<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense> </FormSuspense>
</FormBase> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import FormSwitch from '@/components/debobigego/switch.vue'; import FormSwitch from '@/components/form/switch.vue';
import FormInput from '@/components/debobigego/input.vue'; import FormInput from '@/components/form/input.vue';
import FormButton from '@/components/debobigego/button.vue'; import FormGroup from '@/components/form/group.vue';
import FormBase from '@/components/debobigego/base.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormGroup from '@/components/debobigego/group.vue'; import FormSplit from '@/components/form/split.vue';
import FormSuspense from '@/components/debobigego/suspense.vue'; import FormSection from '@/components/form/section.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
@ -79,10 +81,10 @@ export default defineComponent({
components: { components: {
FormSwitch, FormSwitch,
FormInput, FormInput,
FormBase,
FormGroup, FormGroup,
FormButton,
FormSuspense, FormSuspense,
FormSplit,
FormSection,
}, },
emits: ['info'], emits: ['info'],
@ -93,6 +95,12 @@ export default defineComponent({
title: this.$ts.objectStorage, title: this.$ts.objectStorage,
icon: 'fas fa-cloud', icon: 'fas fa-cloud',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{
asFullButton: true,
icon: 'fas fa-check',
text: this.$ts.save,
handler: this.save,
}],
}, },
useObjectStorage: false, useObjectStorage: false,
objectStorageBaseUrl: null, objectStorageBaseUrl: null,

View File

@ -1,31 +1,35 @@
<template> <template>
<FormBase> <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormLink to="/admin/bot-protection"> <div class="_formRoot">
<FormSection>
<FormSwitch v-model="enableRegistration" class="_formBlock">
<template #label>{{ $ts.enableRegistration }}</template>
</FormSwitch>
<FormSwitch v-model="emailRequiredForSignup" class="_formBlock">
<template #label>{{ $ts.emailRequiredForSignup }}</template>
</FormSwitch>
</FormSection>
<FormLink to="/admin/bot-protection" class="_formBlock">
<i class="fas fa-shield-alt"></i> {{ $ts.botProtection }} <i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}
<template v-if="enableHcaptcha" #suffix>hCaptcha</template> <template v-if="enableHcaptcha" #suffix>hCaptcha</template>
<template v-else-if="enableRecaptcha" #suffix>reCAPTCHA</template> <template v-else-if="enableRecaptcha" #suffix>reCAPTCHA</template>
<template v-else #suffix>{{ $ts.none }} ({{ $ts.notRecommended }})</template> <template v-else #suffix>{{ $ts.none }} ({{ $ts.notRecommended }})</template>
</FormLink> </FormLink>
</div>
<FormSwitch v-model="enableRegistration">{{ $ts.enableRegistration }}</FormSwitch>
<FormSwitch v-model="emailRequiredForSignup">{{ $ts.emailRequiredForSignup }}</FormSwitch>
<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense> </FormSuspense>
</FormBase> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue'; import { defineAsyncComponent, defineComponent } from 'vue';
import FormLink from '@/components/debobigego/link.vue'; import FormLink from '@/components/form/link.vue';
import FormSwitch from '@/components/debobigego/switch.vue'; import FormSwitch from '@/components/form/switch.vue';
import FormButton from '@/components/debobigego/button.vue'; import FormInfo from '@/components/ui/info.vue';
import FormBase from '@/components/debobigego/base.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormGroup from '@/components/debobigego/group.vue'; import FormSection from '@/components/form/section.vue';
import FormInfo from '@/components/debobigego/info.vue';
import FormSuspense from '@/components/debobigego/suspense.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
@ -34,10 +38,8 @@ export default defineComponent({
components: { components: {
FormLink, FormLink,
FormSwitch, FormSwitch,
FormBase,
FormGroup,
FormButton,
FormInfo, FormInfo,
FormSection,
FormSuspense, FormSuspense,
}, },
@ -49,6 +51,12 @@ export default defineComponent({
title: this.$ts.security, title: this.$ts.security,
icon: 'fas fa-lock', icon: 'fas fa-lock',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{
asFullButton: true,
icon: 'fas fa-check',
text: this.$ts.save,
handler: this.save,
}],
}, },
enableHcaptcha: false, enableHcaptcha: false,
enableRecaptcha: false, enableRecaptcha: false,

View File

@ -1,72 +1,75 @@
<template> <template>
<FormBase> <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormInput v-model="name"> <div class="_formRoot">
<span>{{ $ts.instanceName }}</span> <FormInput v-model="name" class="_formBlock">
<template #label>{{ $ts.instanceName }}</template>
</FormInput> </FormInput>
<FormTextarea v-model="description"> <FormTextarea v-model="description" class="_formBlock">
<span>{{ $ts.instanceDescription }}</span> <template #label>{{ $ts.instanceDescription }}</template>
</FormTextarea> </FormTextarea>
<FormInput v-model="iconUrl"> <FormInput v-model="iconUrl" class="_formBlock">
<template #prefix><i class="fas fa-link"></i></template> <template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.iconUrl }}</span> <template #label>{{ $ts.iconUrl }}</template>
</FormInput> </FormInput>
<FormInput v-model="bannerUrl"> <FormInput v-model="bannerUrl" class="_formBlock">
<template #prefix><i class="fas fa-link"></i></template> <template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.bannerUrl }}</span> <template #label>{{ $ts.bannerUrl }}</template>
</FormInput> </FormInput>
<FormInput v-model="backgroundImageUrl"> <FormInput v-model="backgroundImageUrl" class="_formBlock">
<template #prefix><i class="fas fa-link"></i></template> <template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.backgroundImageUrl }}</span> <template #label>{{ $ts.backgroundImageUrl }}</template>
</FormInput> </FormInput>
<FormInput v-model="tosUrl"> <FormInput v-model="tosUrl" class="_formBlock">
<template #prefix><i class="fas fa-link"></i></template> <template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.tosUrl }}</span> <template #label>{{ $ts.tosUrl }}</template>
</FormInput> </FormInput>
<FormInput v-model="maintainerName"> <FormSplit :min-width="300">
<span>{{ $ts.maintainerName }}</span> <FormInput v-model="maintainerName" class="_formBlock">
<template #label>{{ $ts.maintainerName }}</template>
</FormInput> </FormInput>
<FormInput v-model="maintainerEmail" type="email"> <FormInput v-model="maintainerEmail" type="email" class="_formBlock">
<template #prefix><i class="fas fa-envelope"></i></template> <template #prefix><i class="fas fa-envelope"></i></template>
<span>{{ $ts.maintainerEmail }}</span> <template #label>{{ $ts.maintainerEmail }}</template>
</FormInput> </FormInput>
</FormSplit>
<FormTextarea v-model="pinnedUsers"> <FormTextarea v-model="pinnedUsers" class="_formBlock">
<span>{{ $ts.pinnedUsers }}</span> <template #label>{{ $ts.pinnedUsers }}</template>
<template #desc>{{ $ts.pinnedUsersDescription }}</template> <template #caption>{{ $ts.pinnedUsersDescription }}</template>
</FormTextarea> </FormTextarea>
<FormInput v-model="maxNoteTextLength" type="number"> <FormInput v-model="maxNoteTextLength" type="number" class="_formBlock">
<template #prefix><i class="fas fa-pencil-alt"></i></template> <template #prefix><i class="fas fa-pencil-alt"></i></template>
<span>{{ $ts.maxNoteTextLength }}</span> <template #label>{{ $ts.maxNoteTextLength }}</template>
</FormInput> </FormInput>
<FormSwitch v-model="enableLocalTimeline">{{ $ts.enableLocalTimeline }}</FormSwitch> <FormSection>
<FormSwitch v-model="enableGlobalTimeline">{{ $ts.enableGlobalTimeline }}</FormSwitch> <FormSwitch v-model="enableLocalTimeline" class="_formBlock">{{ $ts.enableLocalTimeline }}</FormSwitch>
<FormInfo>{{ $ts.disablingTimelinesInfo }}</FormInfo> <FormSwitch v-model="enableGlobalTimeline" class="_formBlock">{{ $ts.enableGlobalTimeline }}</FormSwitch>
<FormInfo class="_formBlock">{{ $ts.disablingTimelinesInfo }}</FormInfo>
<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> </FormSection>
</div>
</FormSuspense> </FormSuspense>
</FormBase> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import FormSwitch from '@/components/debobigego/switch.vue'; import FormSwitch from '@/components/form/switch.vue';
import FormInput from '@/components/debobigego/input.vue'; import FormInput from '@/components/form/input.vue';
import FormButton from '@/components/debobigego/button.vue'; import FormTextarea from '@/components/form/textarea.vue';
import FormBase from '@/components/debobigego/base.vue'; import FormInfo from '@/components/ui/info.vue';
import FormGroup from '@/components/debobigego/group.vue'; import FormSection from '@/components/form/section.vue';
import FormTextarea from '@/components/debobigego/textarea.vue'; import FormSplit from '@/components/form/split.vue';
import FormInfo from '@/components/debobigego/info.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormSuspense from '@/components/debobigego/suspense.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
@ -75,12 +78,11 @@ export default defineComponent({
components: { components: {
FormSwitch, FormSwitch,
FormInput, FormInput,
FormBase, FormSuspense,
FormGroup,
FormButton,
FormTextarea, FormTextarea,
FormInfo, FormInfo,
FormSuspense, FormSection,
FormSplit,
}, },
emits: ['info'], emits: ['info'],
@ -91,6 +93,12 @@ export default defineComponent({
title: this.$ts.general, title: this.$ts.general,
icon: 'fas fa-cog', icon: 'fas fa-cog',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{
asFullButton: true,
icon: 'fas fa-check',
text: this.$ts.save,
handler: this.save,
}],
}, },
name: null, name: null,
description: null, description: null,

View File

@ -6,7 +6,7 @@
<template #prefix><i class="fas fa-search"></i></template> <template #prefix><i class="fas fa-search"></i></template>
<template #label>{{ $ts.host }}</template> <template #label>{{ $ts.host }}</template>
</MkInput> </MkInput>
<div class="_inputSplit" style="margin-top: var(--margin);"> <FormSplit style="margin-top: var(--margin);">
<MkSelect v-model="state"> <MkSelect v-model="state">
<template #label>{{ $ts.state }}</template> <template #label>{{ $ts.state }}</template>
<option value="all">{{ $ts.all }}</option> <option value="all">{{ $ts.all }}</option>
@ -38,7 +38,7 @@
<option value="+driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.descendingOrder }})</option> <option value="+driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.descendingOrder }})</option>
<option value="-driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.ascendingOrder }})</option> <option value="-driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.ascendingOrder }})</option>
</MkSelect> </MkSelect>
</div> </FormSplit>
</div> </div>
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination"> <MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
@ -101,6 +101,7 @@ import MkButton from '@/components/ui/button.vue';
import MkInput from '@/components/form/input.vue'; import MkInput from '@/components/form/input.vue';
import MkSelect from '@/components/form/select.vue'; import MkSelect from '@/components/form/select.vue';
import MkPagination from '@/components/ui/pagination.vue'; import MkPagination from '@/components/ui/pagination.vue';
import FormSplit from '@/components/form/split.vue';
import * as os from '@/os'; import * as os from '@/os';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
@ -110,6 +111,7 @@ export default defineComponent({
MkInput, MkInput,
MkSelect, MkSelect,
MkPagination, MkPagination,
FormSplit,
}, },
emits: ['info'], emits: ['info'],

View File

@ -5,7 +5,7 @@
<div class="_formBlock uawsfosz"> <div class="_formBlock uawsfosz">
<div class="meter"><div :style="meterStyle"></div></div> <div class="meter"><div :style="meterStyle"></div></div>
</div> </div>
<div class="_inputSplit _formBlock"> <FormSplit>
<MkKeyValue class="_formBlock"> <MkKeyValue class="_formBlock">
<template #key>{{ $ts.capacity }}</template> <template #key>{{ $ts.capacity }}</template>
<template #value>{{ bytes(capacity, 1) }}</template> <template #value>{{ bytes(capacity, 1) }}</template>
@ -14,7 +14,7 @@
<template #key>{{ $ts.inUse }}</template> <template #key>{{ $ts.inUse }}</template>
<template #value>{{ bytes(usage, 1) }}</template> <template #value>{{ bytes(usage, 1) }}</template>
</MkKeyValue> </MkKeyValue>
</div> </FormSplit>
</FormSection> </FormSection>
<FormSection> <FormSection>
@ -38,6 +38,7 @@ import * as tinycolor from 'tinycolor2';
import FormLink from '@/components/form/link.vue'; import FormLink from '@/components/form/link.vue';
import FormSection from '@/components/form/section.vue'; import FormSection from '@/components/form/section.vue';
import MkKeyValue from '@/components/key-value.vue'; import MkKeyValue from '@/components/key-value.vue';
import FormSplit from '@/components/form/split.vue';
import * as os from '@/os'; import * as os from '@/os';
import bytes from '@/filters/bytes'; import bytes from '@/filters/bytes';
import * as symbols from '@/symbols'; import * as symbols from '@/symbols';
@ -49,6 +50,7 @@ export default defineComponent({
FormLink, FormLink,
FormSection, FormSection,
MkKeyValue, MkKeyValue,
FormSplit,
}, },
emits: ['info'], emits: ['info'],

View File

@ -386,16 +386,6 @@ hr {
backdrop-filter: var(--blur, blur(15px)); backdrop-filter: var(--blur, blur(15px));
} }
._inputSplit {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
grid-gap: 12px;
> * {
margin: 0 !important;
}
}
._formBlock { ._formBlock {
margin: 1.5em 0; margin: 1.5em 0;
} }

View File

@ -47,6 +47,7 @@ module.exports = {
loader: 'vue-loader', loader: 'vue-loader',
options: { options: {
cssSourceMap: false, cssSourceMap: false,
reactivityTransform: true,
compilerOptions: { compilerOptions: {
preserveWhitespace: false preserveWhitespace: false
} }

View File

@ -6162,10 +6162,10 @@ vue-eslint-parser@^8.0.1:
lodash "^4.17.21" lodash "^4.17.21"
semver "^7.3.5" semver "^7.3.5"
vue-loader@16.8.3: vue-loader@17.0.0:
version "16.8.3" version "17.0.0"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.8.3.tgz#d43e675def5ba9345d6c7f05914c13d861997087" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-17.0.0.tgz#2eaa80aab125b19f00faa794b5bd867b17f85acb"
integrity sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA== integrity sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==
dependencies: dependencies:
chalk "^4.1.0" chalk "^4.1.0"
hash-sum "^2.0.0" hash-sum "^2.0.0"