merge upstream
This commit is contained in:
commit
d8908ef2d8
1065 changed files with 32953 additions and 20092 deletions
|
|
@ -71,7 +71,7 @@ import MkInput from '@/components/MkInput.vue';
|
|||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { deepClone } from '@/utility/clone.js';
|
||||
import { rolesCache } from '@/cache.js';
|
||||
|
||||
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef, watch, nextTick } from 'vue';
|
||||
import { computed, onMounted, onUnmounted, ref, useTemplateRef, watch, nextTick, inject } from 'vue';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { popupMenu } from '@/os.js';
|
||||
import { scrollToTop } from '@@/js/scroll.js';
|
||||
import { popupMenu } from '@/os.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { globalEvents } from '@/events.js';
|
||||
import { injectReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||
import { DI } from '@/di.js';
|
||||
|
||||
type Tab = {
|
||||
key?: string | null;
|
||||
|
|
@ -66,11 +66,11 @@ const emit = defineEmits<{
|
|||
(ev: 'update:tab', key: string);
|
||||
}>();
|
||||
|
||||
const pageMetadata = injectReactiveMetadata();
|
||||
const pageMetadata = inject(DI.pageMetadata);
|
||||
|
||||
const el = shallowRef<HTMLElement>(null);
|
||||
const el = useTemplateRef('el');
|
||||
const tabHighlightEl = useTemplateRef('tabHighlightEl');
|
||||
const tabRefs = {};
|
||||
const tabHighlightEl = shallowRef<HTMLElement | null>(null);
|
||||
const bg = ref<string | null>(null);
|
||||
const height = ref(0);
|
||||
const hasTabs = computed(() => {
|
||||
|
|
@ -119,15 +119,15 @@ function onTabClick(tab: Tab, ev: MouseEvent): void {
|
|||
}
|
||||
|
||||
const calcBg = () => {
|
||||
const rawBg = pageMetadata.value?.bg ?? 'var(--MI_THEME-bg)';
|
||||
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
|
||||
const rawBg = pageMetadata.value.bg ?? 'var(--MI_THEME-bg)';
|
||||
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(window.document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
|
||||
tinyBg.setAlpha(0.85);
|
||||
bg.value = tinyBg.toRgbString();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
calcBg();
|
||||
globalEvents.on('themeChanged', calcBg);
|
||||
globalEvents.on('themeChanging', calcBg);
|
||||
|
||||
watch(() => [props.tab, props.tabs], () => {
|
||||
nextTick(() => {
|
||||
|
|
@ -147,7 +147,7 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
globalEvents.off('themeChanged', calcBg);
|
||||
globalEvents.off('themeChanging', calcBg);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -71,15 +71,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, shallowRef, toRefs } from 'vue';
|
||||
import { computed, onMounted, ref, useTemplateRef, toRefs } from 'vue';
|
||||
import { entities } from 'misskey-js';
|
||||
import type { MkSystemWebhookResult } from '@/components/MkSystemWebhookEditor.impl.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import { MkSystemWebhookResult, showSystemWebhookEditorDialog } from '@/components/MkSystemWebhookEditor.impl.js';
|
||||
import { showSystemWebhookEditorDialog } from '@/components/MkSystemWebhookEditor.impl.js';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkDivider from '@/components/MkDivider.vue';
|
||||
import * as os from '@/os.js';
|
||||
|
|
@ -99,7 +100,7 @@ const props = defineProps<{
|
|||
|
||||
const { mode, id } = toRefs(props);
|
||||
|
||||
const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
const dialogEl = useTemplateRef('dialogEl');
|
||||
|
||||
const loading = ref<number>(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import { entities } from 'misskey-js';
|
|||
import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
|
||||
import XRecipient from './notification-recipient.item.vue';
|
||||
import XHeader from '@/pages/admin/_header_.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkButton link to="/admin/abuse-report-notification-recipient" primary>{{ i18n.ts.notificationSetting }}</MkButton>
|
||||
</div>
|
||||
|
||||
<MkInfo v-if="!defaultStore.reactiveState.abusesTutorial.value" closable @close="closeTutorial()">
|
||||
<MkInfo v-if="!store.r.abusesTutorial.value" closable @close="closeTutorial()">
|
||||
{{ i18n.ts._abuseUserReport.resolveTutorial }}
|
||||
</MkInfo>
|
||||
|
||||
|
|
@ -59,18 +59,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, shallowRef, ref } from 'vue';
|
||||
import { computed, useTemplateRef, ref } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import XAbuseReport from '@/components/MkAbuseReport.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { store } from '@/store.js';
|
||||
|
||||
const reports = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
const reports = useTemplateRef('reports');
|
||||
|
||||
const state = ref('unresolved');
|
||||
const reporterOrigin = ref('combined');
|
||||
|
|
@ -93,14 +93,14 @@ function resolved(reportId) {
|
|||
}
|
||||
|
||||
function closeTutorial() {
|
||||
defaultStore.set('abusesTutorial', false);
|
||||
store.set('abusesTutorial', false);
|
||||
}
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.abuseReports,
|
||||
icon: 'ti ti-exclamation-circle',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -96,9 +96,9 @@ import MkFolder from '@/components/MkFolder.vue';
|
|||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const ads = ref<Misskey.entities.Ad[]>([]);
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ const headerActions = computed(() => [{
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.ads,
|
||||
icon: 'ti ti-ad',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ import MkSwitch from '@/components/MkSwitch.vue';
|
|||
import MkRadios from '@/components/MkRadios.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ const headerActions = computed(() => [{
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.announcements,
|
||||
icon: 'ti ti-speakerphone',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -196,14 +196,14 @@ import MkRadios from '@/components/MkRadios.vue';
|
|||
import MkInput from '@/components/MkInput.vue';
|
||||
import FormSlot from '@/components/form/slot.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { useForm } from '@/scripts/use-form.js';
|
||||
import { useForm } from '@/use/use-form.js';
|
||||
import MkFormFooter from '@/components/MkFormFooter.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { ApiWithDialogCustomErrors } from '@/os.js';
|
||||
import type { ApiWithDialogCustomErrors } from '@/os.js';
|
||||
|
||||
const MkCaptcha = defineAsyncComponent(() => import('@/components/MkCaptcha.vue'));
|
||||
|
||||
|
|
|
|||
|
|
@ -128,10 +128,10 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import FromSlot from '@/components/form/slot.vue';
|
||||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { instance, fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkColorInput from '@/components/MkColorInput.vue';
|
||||
import { host } from '@@/js/config.js';
|
||||
|
|
@ -210,7 +210,7 @@ function chooseNewLike(ev: MouseEvent) {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.branding,
|
||||
icon: 'ti ti-paint',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -71,25 +71,25 @@ export type EmojiSearchQuery = {
|
|||
<script setup lang="ts">
|
||||
import { computed, defineAsyncComponent, onMounted, ref, nextTick, useCssModule } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import type { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import type { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import type { GridSetting } from '@/components/grid/grid.js';
|
||||
import * as os from '@/os.js';
|
||||
import {
|
||||
emptyStrToEmptyArray,
|
||||
emptyStrToNull,
|
||||
emptyStrToUndefined,
|
||||
RequestLogItem,
|
||||
roleIdsParser,
|
||||
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { validators } from '@/components/grid/cell-validators.js';
|
||||
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||
import { GridSetting } from '@/components/grid/grid.js';
|
||||
import { selectFile } from '@/scripts/select-file.js';
|
||||
import { selectFile } from '@/utility/select-file.js';
|
||||
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
||||
import { useLoading } from "@/components/hook/useLoading.js";
|
||||
import { useLoading } from '@/components/hook/useLoading.js';
|
||||
|
||||
type GridItem = {
|
||||
checked: boolean;
|
||||
|
|
@ -108,7 +108,7 @@ type GridItem = {
|
|||
publicUrl?: string | null;
|
||||
originalUrl?: string | null;
|
||||
type: string | null;
|
||||
}
|
||||
};
|
||||
|
||||
function setupGrid(): GridSetting {
|
||||
const $style = useCssModule();
|
||||
|
|
@ -464,8 +464,8 @@ async function refreshCustomEmojis() {
|
|||
aliases: emptyStrToUndefined(searchQuery.value.aliases),
|
||||
category: emptyStrToUndefined(searchQuery.value.category),
|
||||
license: emptyStrToUndefined(searchQuery.value.license),
|
||||
isSensitive: searchQuery.value.sensitive ? Boolean(searchQuery.value.sensitive).valueOf() : undefined,
|
||||
localOnly: searchQuery.value.localOnly ? Boolean(searchQuery.value.localOnly).valueOf() : undefined,
|
||||
isSensitive: searchQuery.value.sensitive != null ? Boolean(searchQuery.value.sensitive).valueOf() : undefined,
|
||||
localOnly: searchQuery.value.localOnly != null ? Boolean(searchQuery.value.localOnly).valueOf() : undefined,
|
||||
updatedAtFrom: emptyStrToUndefined(searchQuery.value.updatedAtFrom),
|
||||
updatedAtTo: emptyStrToUndefined(searchQuery.value.updatedAtTo),
|
||||
roleIds: searchQuery.value.roles.map(it => it.id),
|
||||
|
|
@ -592,7 +592,7 @@ const headerActions = computed(() => [{
|
|||
dispose();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
}]);
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -78,30 +78,32 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { onMounted, ref, useCssModule } from 'vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import type { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import type { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import type { DroppedFile } from '@/utility/file-drop.js';
|
||||
import type { GridSetting } from '@/components/grid/grid.js';
|
||||
import type { GridRow } from '@/components/grid/row.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import {
|
||||
emptyStrToEmptyArray,
|
||||
emptyStrToNull,
|
||||
RequestLogItem,
|
||||
roleIdsParser,
|
||||
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { validators } from '@/components/grid/cell-validators.js';
|
||||
import { chooseFileFromDrive, chooseFileFromPc } from '@/scripts/select-file.js';
|
||||
import { uploadFile } from '@/scripts/upload.js';
|
||||
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
|
||||
import { chooseFileFromDrive, chooseFileFromPc } from '@/utility/select-file.js';
|
||||
import { uploadFile } from '@/utility/upload.js';
|
||||
import { extractDroppedItems, flattenDroppedFiles } from '@/utility/file-drop.js';
|
||||
import XRegisterLogs from '@/pages/admin/custom-emojis-manager.logs.vue';
|
||||
import { GridSetting } from '@/components/grid/grid.js';
|
||||
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
|
||||
import { GridRow } from '@/components/grid/row.js';
|
||||
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const MAXIMUM_EMOJI_REGISTER_COUNT = 100;
|
||||
|
||||
|
|
@ -122,7 +124,7 @@ type GridItem = {
|
|||
localOnly: boolean;
|
||||
roleIdsThatCanBeUsedThisEmojiAsReaction: { id: string, name: string }[];
|
||||
type: string | null;
|
||||
}
|
||||
};
|
||||
|
||||
function setupGrid(): GridSetting {
|
||||
const $style = useCssModule();
|
||||
|
|
@ -242,8 +244,8 @@ function setupGrid(): GridSetting {
|
|||
|
||||
const uploadFolders = ref<FolderItem[]>([]);
|
||||
const gridItems = ref<GridItem[]>([]);
|
||||
const selectedFolderId = ref(defaultStore.state.uploadFolder);
|
||||
const keepOriginalUploading = ref(defaultStore.state.keepOriginalUploading);
|
||||
const selectedFolderId = ref(prefer.s.uploadFolder);
|
||||
const keepOriginalUploading = ref(prefer.s.keepOriginalUploading);
|
||||
const directoryToCategory = ref<boolean>(false);
|
||||
const registerButtonDisabled = ref<boolean>(false);
|
||||
const requestLogs = ref<RequestLogItem[]>([]);
|
||||
|
|
|
|||
|
|
@ -143,35 +143,32 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed, onMounted, ref, useCssModule } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkRemoteEmojiEditDialog from '@/components/MkRemoteEmojiEditDialog.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||
import {
|
||||
emptyStrToUndefined,
|
||||
GridSortOrderKey,
|
||||
gridSortOrderKeys,
|
||||
RequestLogItem,
|
||||
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import { emptyStrToUndefined, gridSortOrderKeys } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import XRegisterLogs from '@/pages/admin/custom-emojis-manager.logs.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { GridSetting } from '@/components/grid/grid.js';
|
||||
import { deviceKind } from '@/scripts/device-kind.js';
|
||||
import { deviceKind } from '@/utility/device-kind.js';
|
||||
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
|
||||
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
import { useLoading } from '@/components/hook/useLoading.js';
|
||||
|
||||
import type { GridSortOrderKey, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import type { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||
import type { GridSetting } from '@/components/grid/grid.js';
|
||||
import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
|
||||
type GridItem = {
|
||||
checked: boolean;
|
||||
id: string;
|
||||
url: string;
|
||||
name: string;
|
||||
host: string;
|
||||
}
|
||||
};
|
||||
|
||||
function setupGrid(): GridSetting {
|
||||
const $style = useCssModule();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { delay, http, HttpResponse } from 'msw';
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import { entities } from 'misskey-js';
|
||||
import { commonHandlers } from '../../../.storybook/mocks.js';
|
||||
import { emoji } from '../../../.storybook/fakes.js';
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import XGridLocalComponent from '@/pages/admin/custom-emojis-manager.local.vue';
|
||||
import XGridRemoteComponent from '@/pages/admin/custom-emojis-manager.remote.vue';
|
||||
import MkPageHeader from '@/components/global/MkPageHeader.vue';
|
||||
|
|
@ -36,7 +36,7 @@ const headerTabs = computed(() => [{
|
|||
title: i18n.ts.remote,
|
||||
}]);
|
||||
|
||||
definePageMetadata(computed(() => ({
|
||||
definePage(computed(() => ({
|
||||
title: i18n.ts.customEmojis,
|
||||
icon: 'ti ti-icons',
|
||||
needWideArea: true,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
|
||||
<MkSpacer :contentMax="800" :marginMin="16" :marginMax="32">
|
||||
<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory">
|
||||
<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;">
|
||||
|
|
@ -14,18 +13,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkKeyValue>
|
||||
</FormSuspense>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</PageWithHeader>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import bytes from '@/filters/bytes.js';
|
||||
import number from '@/filters/number.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const databasePromiseFactory = () => misskeyApi('admin/get-table-stats').then(res => Object.entries(res).sort((a, b) => b[1].size - a[1].size));
|
||||
|
||||
|
|
@ -33,7 +32,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.database,
|
||||
icon: 'ti ti-database',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -73,10 +73,10 @@ import FormSuspense from '@/components/form/suspense.vue';
|
|||
import FormSplit from '@/components/form/split.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
const enableEmail = ref<boolean>(false);
|
||||
|
|
@ -130,7 +130,7 @@ function save() {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.emailServer,
|
||||
icon: 'ti ti-mail',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -9,6 +9,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
|
||||
<FormSuspense :p="init">
|
||||
<div class="_gaps_m">
|
||||
<MkFolder>
|
||||
<template #label>Google Analytics<span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||
|
||||
<div class="_gaps_m">
|
||||
<MkInput v-model="googleAnalyticsMeasurementId">
|
||||
<template #prefix><i class="ti ti-key"></i></template>
|
||||
<template #label>Measurement ID</template>
|
||||
</MkInput>
|
||||
<MkButton primary @click="save_googleAnalytics">Save</MkButton>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder>
|
||||
<template #label>DeepL Translation</template>
|
||||
|
||||
|
|
@ -65,10 +77,10 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
||||
const deeplAuthKey = ref<string | null>('');
|
||||
|
|
@ -78,14 +90,17 @@ const deeplFreeInstance = ref<string | null>('');
|
|||
const libreTranslateURL = ref<string | null>('');
|
||||
const libreTranslateKey = ref<string | null>('');
|
||||
|
||||
const googleAnalyticsMeasurementId = ref<string>('');
|
||||
|
||||
async function init() {
|
||||
const meta = await misskeyApi('admin/meta');
|
||||
deeplAuthKey.value = meta.deeplAuthKey;
|
||||
deeplAuthKey.value = meta.deeplAuthKey ?? '';
|
||||
deeplIsPro.value = meta.deeplIsPro;
|
||||
deeplFreeMode.value = meta.deeplFreeMode;
|
||||
deeplFreeInstance.value = meta.deeplFreeInstance;
|
||||
libreTranslateURL.value = meta.libreTranslateURL;
|
||||
libreTranslateKey.value = meta.libreTranslateKey;
|
||||
googleAnalyticsMeasurementId.value = meta.googleAnalyticsMeasurementId ?? '';
|
||||
}
|
||||
|
||||
function save_deepl() {
|
||||
|
|
@ -108,11 +123,19 @@ function save_libre() {
|
|||
});
|
||||
}
|
||||
|
||||
function save_googleAnalytics() {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
googleAnalyticsMeasurementId: googleAnalyticsMeasurementId.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
});
|
||||
}
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.externalServices,
|
||||
icon: 'ph-arrow-square-out ph-bold ph-lg',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ import MkPagination from '@/components/MkPagination.vue';
|
|||
import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const host = ref('');
|
||||
const state = ref('federating');
|
||||
|
|
@ -116,7 +116,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.federation,
|
||||
icon: 'ti ti-whirl',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ import MkInput from '@/components/MkInput.vue';
|
|||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { lookupFile } from '@/scripts/admin-lookup.js';
|
||||
import { lookupFile } from '@/utility/admin-lookup.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const origin = ref('local');
|
||||
const type = ref<string | null>(null);
|
||||
|
|
@ -85,7 +85,7 @@ const headerActions = computed(() => [{
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.files,
|
||||
icon: 'ti ti-cloud',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -27,24 +27,25 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSpacer>
|
||||
</div>
|
||||
<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
|
||||
<RouterView nested/>
|
||||
<NestedRouterView/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted, onUnmounted, provide, watch, ref, computed } from 'vue';
|
||||
import type { SuperMenuDef } from '@/components/MkSuperMenu.vue';
|
||||
import type { PageMetadata } from '@/page.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
||||
import type { SuperMenuDef } from '@/components/MkSuperMenu.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { lookup } from '@/scripts/lookup.js';
|
||||
import { lookup } from '@/utility/lookup.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { lookupUser, lookupUserByEmail, lookupFile } from '@/scripts/admin-lookup.js';
|
||||
import { PageMetadata, definePageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { lookupUser, lookupUserByEmail, lookupFile } from '@/utility/admin-lookup.js';
|
||||
import { definePage, provideMetadataReceiver, provideReactiveMetadata } from '@/page.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
|
||||
const isEmpty = (x: string | null) => x == null || x === '';
|
||||
|
||||
|
|
@ -339,7 +340,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => INFO.value);
|
||||
definePage(() => INFO.value);
|
||||
|
||||
defineExpose({
|
||||
header: {
|
||||
|
|
|
|||
|
|
@ -55,21 +55,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, shallowRef } from 'vue';
|
||||
import { computed, ref, useTemplateRef } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import type { Paging } from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkInviteCode from '@/components/MkInviteCode.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = useTemplateRef('pagingComponent');
|
||||
|
||||
const type = ref('all');
|
||||
const sort = ref('+createdAt');
|
||||
|
|
@ -113,7 +114,7 @@ function deleted(id: string) {
|
|||
const headerActions = computed(() => []);
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.invite,
|
||||
icon: 'ti ti-user-plus',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -162,10 +162,10 @@ import MkInput from '@/components/MkInput.vue';
|
|||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
|
@ -319,7 +319,7 @@ function save_mediaSilencedHosts() {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.moderation,
|
||||
icon: 'ti ti-shield',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -274,6 +274,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template v-else-if="log.type === 'removeRelay'">
|
||||
<div>{{ i18n.ts.inboxUrl }}: {{ log.info.inbox }}</div>
|
||||
</template>
|
||||
<template v-else-if="log.type === 'updateProxyAccountDescription'">
|
||||
<div :class="$style.diff">
|
||||
<CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<details>
|
||||
<summary>raw</summary>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, shallowRef, ref } from 'vue';
|
||||
import { computed, useTemplateRef, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XHeader from './_header_.vue';
|
||||
import XModLog from './modlog.ModLog.vue';
|
||||
|
|
@ -38,10 +38,10 @@ import MkSelect from '@/components/MkSelect.vue';
|
|||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||
|
||||
const logs = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
const logs = useTemplateRef('logs');
|
||||
|
||||
const type = ref<string | null>(null);
|
||||
const moderatorId = ref('');
|
||||
|
|
@ -59,7 +59,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.moderationLogs,
|
||||
icon: 'ti ti-list-search',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -90,10 +90,10 @@ import MkInput from '@/components/MkInput.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
const useObjectStorage = ref<boolean>(false);
|
||||
|
|
@ -149,7 +149,7 @@ function save() {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.objectStorage,
|
||||
icon: 'ti ti-cloud',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef, ref } from 'vue';
|
||||
import { onMounted, useTemplateRef, ref } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import gradient from 'chartjs-plugin-gradient';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/scripts/chart-vline.js';
|
||||
import { initChart } from '@/scripts/init-chart.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { store } from '@/store.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/utility/chart-vline.js';
|
||||
import { initChart } from '@/utility/init-chart.js';
|
||||
|
||||
initChart();
|
||||
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const chartEl = useTemplateRef('chartEl');
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
const chartLimit = 7;
|
||||
|
|
@ -54,7 +54,7 @@ async function renderChart() {
|
|||
|
||||
const raw = await misskeyApi('charts/active-users', { limit: chartLimit, span: 'day' });
|
||||
|
||||
const vLineColor = defaultStore.state.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
const vLineColor = store.s.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
|
||||
const colorRead = '#3498db';
|
||||
const colorWrite = '#2ecc71';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { commonHandlers } from '../../../.storybook/mocks.js';
|
||||
|
|
|
|||
|
|
@ -20,22 +20,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef, ref } from 'vue';
|
||||
import { onMounted, useTemplateRef, ref } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import gradient from 'chartjs-plugin-gradient';
|
||||
import isChromatic from 'chromatic';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/scripts/chart-vline.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { alpha } from '@/scripts/color.js';
|
||||
import { initChart } from '@/scripts/init-chart.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/utility/chart-vline.js';
|
||||
import { store } from '@/store.js';
|
||||
import { alpha } from '@/utility/color.js';
|
||||
import { initChart } from '@/utility/init-chart.js';
|
||||
|
||||
initChart();
|
||||
|
||||
const chartLimit = 50;
|
||||
const chartEl = shallowRef<HTMLCanvasElement>();
|
||||
const chartEl2 = shallowRef<HTMLCanvasElement>();
|
||||
const chartEl = useTemplateRef('chartEl');
|
||||
const chartEl2 = useTemplateRef('chartEl2');
|
||||
const fetching = ref(true);
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
|
@ -68,7 +68,7 @@ onMounted(async () => {
|
|||
|
||||
const raw = await misskeyApi('charts/ap-request', { limit: chartLimit, span: 'day' });
|
||||
|
||||
const vLineColor = defaultStore.state.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
const vLineColor = store.s.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
const succColor = '#87e000';
|
||||
const failColor = '#ff4400';
|
||||
|
||||
|
|
|
|||
|
|
@ -47,13 +47,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import XPie, { type InstanceForPie } from './overview.pie.vue';
|
||||
import XPie from './overview.pie.vue';
|
||||
import type { InstanceForPie } from './overview.pie.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApiGet } from '@/utility/misskey-api.js';
|
||||
import number from '@/filters/number.js';
|
||||
import MkNumberDiff from '@/components/MkNumberDiff.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
|
||||
const topSubInstancesForPie = ref<InstanceForPie[] | null>(null);
|
||||
const topPubInstancesForPie = ref<InstanceForPie[] | null>(null);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<Transition :name="prefer.s.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<MkLoading v-if="fetching"/>
|
||||
<div v-else :class="$style.instances">
|
||||
<MkA v-for="(instance, i) in instances" :key="instance.id" v-tooltip.mfm.noDelay="`${instance.name}\n${instance.host}\n${instance.softwareName} ${instance.softwareVersion}`" :to="`/instance-info/${instance.host}`" :class="$style.instance">
|
||||
|
|
@ -18,11 +18,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { useInterval } from '@@/js/use-interval.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const instances = ref<Misskey.entities.FederationInstance[]>([]);
|
||||
const fetching = ref(true);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<Transition :name="prefer.s.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<MkLoading v-if="fetching"/>
|
||||
<div v-else :class="$style.root" class="_panel">
|
||||
<MkA v-for="user in moderators" :key="user.id" class="user" :to="`/admin/user/${user.id}`">
|
||||
|
|
@ -18,9 +18,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const moderators = ref<Misskey.entities.UserDetailed[] | null>(null);
|
||||
const fetching = ref(true);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef } from 'vue';
|
||||
import { onMounted, useTemplateRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { initChart } from '@/scripts/init-chart.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
import { initChart } from '@/utility/init-chart.js';
|
||||
|
||||
export type InstanceForPie = {
|
||||
name: string,
|
||||
|
|
@ -26,7 +26,7 @@ const props = defineProps<{
|
|||
data: InstanceForPie[];
|
||||
}>();
|
||||
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const chartEl = useTemplateRef('chartEl');
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip({
|
||||
position: 'middle',
|
||||
|
|
@ -41,7 +41,7 @@ onMounted(() => {
|
|||
labels: props.data.map(x => x.name),
|
||||
datasets: [{
|
||||
backgroundColor: props.data.map(x => x.color),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--MI_THEME-panel'),
|
||||
borderColor: getComputedStyle(window.document.documentElement).getPropertyValue('--MI_THEME-panel'),
|
||||
borderWidth: 2,
|
||||
hoverOffset: 0,
|
||||
data: props.data.map(x => x.value),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef } from 'vue';
|
||||
import { onMounted, useTemplateRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/scripts/chart-vline.js';
|
||||
import { alpha } from '@/scripts/color.js';
|
||||
import { initChart } from '@/scripts/init-chart.js';
|
||||
import { store } from '@/store.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/utility/chart-vline.js';
|
||||
import { alpha } from '@/utility/color.js';
|
||||
import { initChart } from '@/utility/init-chart.js';
|
||||
|
||||
initChart();
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ const props = defineProps<{
|
|||
type: string;
|
||||
}>();
|
||||
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const chartEl = useTemplateRef('chartEl');
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ const color =
|
|||
'?' as never;
|
||||
|
||||
onMounted(() => {
|
||||
const vLineColor = defaultStore.state.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
const vLineColor = store.s.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
|
||||
chartInstance = new Chart(chartEl.value, {
|
||||
type: 'line',
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { markRaw, onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import { markRaw, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XChart from './overview.queue.chart.vue';
|
||||
import type { ApQueueDomain } from '@/pages/admin/queue.vue';
|
||||
|
|
@ -48,10 +48,10 @@ const activeSincePrevTick = ref(0);
|
|||
const active = ref(0);
|
||||
const delayed = ref(0);
|
||||
const waiting = ref(0);
|
||||
const chartProcess = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartActive = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartDelayed = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartWaiting = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartProcess = useTemplateRef('chartProcess');
|
||||
const chartActive = useTemplateRef('chartActive');
|
||||
const chartDelayed = useTemplateRef('chartDelayed');
|
||||
const chartWaiting = useTemplateRef('chartWaiting');
|
||||
|
||||
const props = defineProps<{
|
||||
domain: ApQueueDomain;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<Transition :name="prefer.s.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<MkLoading v-if="fetching"/>
|
||||
<div v-else :class="$style.root">
|
||||
<div class="item _panel users">
|
||||
|
|
@ -63,12 +63,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js';
|
||||
import MkNumberDiff from '@/components/MkNumberDiff.vue';
|
||||
import MkNumber from '@/components/MkNumber.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { customEmojis } from '@/custom-emojis.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const stats = ref<Misskey.entities.StatsResponse | null>(null);
|
||||
const usersComparedToThePrevDay = ref<number>();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<Transition :name="prefer.s.animation ? '_transition_zoom' : ''" mode="out-in">
|
||||
<MkLoading v-if="fetching"/>
|
||||
<div v-else class="users">
|
||||
<MkA v-for="(user, i) in newUsers" :key="user.id" :to="`/admin/user/${user.id}`" class="user">
|
||||
|
|
@ -18,11 +18,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { useInterval } from '@@/js/use-interval.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const newUsers = ref<Misskey.entities.UserDetailed[] | null>(null);
|
||||
const fetching = ref(true);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { markRaw, onMounted, onBeforeUnmount, nextTick, shallowRef, ref, computed } from 'vue';
|
||||
import { markRaw, onMounted, onBeforeUnmount, nextTick, shallowRef, ref, computed, useTemplateRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XFederation from './overview.federation.vue';
|
||||
import XInstances from './overview.instances.vue';
|
||||
|
|
@ -79,13 +79,13 @@ import XModerators from './overview.moderators.vue';
|
|||
import XHeatmap from './overview.heatmap.vue';
|
||||
import type { InstanceForPie } from './overview.pie.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js';
|
||||
import { useStream } from '@/stream.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
|
||||
const rootEl = shallowRef<HTMLElement>();
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
const serverInfo = ref<Misskey.entities.ServerInfoResponse | null>(null);
|
||||
const topSubInstancesForPie = ref<InstanceForPie[] | null>(null);
|
||||
const topPubInstancesForPie = ref<InstanceForPie[] | null>(null);
|
||||
|
|
@ -184,7 +184,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.dashboard,
|
||||
icon: 'ti ti-dashboard',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -111,15 +111,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { ref, computed } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
import { useForm } from '@/scripts/use-form.js';
|
||||
import { useForm } from '@/use/use-form.js';
|
||||
import MkFormFooter from '@/components/MkFormFooter.vue';
|
||||
|
||||
const meta = await misskeyApi('admin/meta');
|
||||
|
|
@ -202,7 +202,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.other,
|
||||
icon: 'ti ti-adjustments',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef } from 'vue';
|
||||
import { onMounted, useTemplateRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/scripts/chart-vline.js';
|
||||
import { alpha } from '@/scripts/color.js';
|
||||
import { initChart } from '@/scripts/init-chart.js';
|
||||
import { store } from '@/store.js';
|
||||
import { useChartTooltip } from '@/use/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/utility/chart-vline.js';
|
||||
import { alpha } from '@/utility/color.js';
|
||||
import { initChart } from '@/utility/init-chart.js';
|
||||
|
||||
initChart();
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ const props = defineProps<{
|
|||
type: string;
|
||||
}>();
|
||||
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const chartEl = useTemplateRef('chartEl');
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ const color =
|
|||
'?' as never;
|
||||
|
||||
onMounted(() => {
|
||||
const vLineColor = defaultStore.state.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
const vLineColor = store.s.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
|
||||
|
||||
chartInstance = new Chart(chartEl.value, {
|
||||
type: 'line',
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { markRaw, onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import { markRaw, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XChart from './queue.chart.chart.vue';
|
||||
import type { ApQueueDomain } from '@/pages/admin/queue.vue';
|
||||
import number from '@/filters/number.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { useStream } from '@/stream.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
|
@ -65,10 +65,10 @@ const active = ref(0);
|
|||
const delayed = ref(0);
|
||||
const waiting = ref(0);
|
||||
const jobs = ref<Misskey.Endpoints[`admin/queue/${ApQueueDomain}-delayed`]['res']>([]);
|
||||
const chartProcess = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartActive = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartDelayed = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartWaiting = shallowRef<InstanceType<typeof XChart>>();
|
||||
const chartProcess = useTemplateRef('chartProcess');
|
||||
const chartActive = useTemplateRef('chartActive');
|
||||
const chartDelayed = useTemplateRef('chartDelayed');
|
||||
const chartWaiting = useTemplateRef('chartWaiting');
|
||||
|
||||
const props = defineProps<{
|
||||
domain: ApQueueDomain;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, type Ref } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import * as config from '@@/js/config.js';
|
||||
import XQueue from './queue.chart.vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import type { Ref } from 'vue';
|
||||
import * as os from '@/os.js';
|
||||
import * as config from '@@/js/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
export type ApQueueDomain = 'deliver' | 'inbox';
|
||||
|
|
@ -53,14 +54,7 @@ function promoteAllQueues() {
|
|||
});
|
||||
}
|
||||
|
||||
const headerActions = computed(() => [{
|
||||
asFullButton: true,
|
||||
icon: 'ti ti-external-link',
|
||||
text: i18n.ts.dashboard,
|
||||
handler: () => {
|
||||
window.open(config.url + '/queue', '_blank', 'noopener');
|
||||
},
|
||||
}]);
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => [{
|
||||
key: 'deliver',
|
||||
|
|
@ -70,7 +64,7 @@ const headerTabs = computed(() => [{
|
|||
title: 'Inbox',
|
||||
}]);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.jobQueue,
|
||||
icon: 'ti ti-clock-play',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ import * as Misskey from 'misskey-js';
|
|||
import XHeader from './_header_.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
const relays = ref<Misskey.entities.AdminRelaysListResponse>([]);
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ const headerActions = computed(() => [{
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.relays,
|
||||
icon: 'ti ti-planet',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ import { v4 as uuid } from 'uuid';
|
|||
import XHeader from './_header_.vue';
|
||||
import XEditor from './roles.editor.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { rolesCache } from '@/cache.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ async function save() {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: role.value ? `${i18n.ts._role.edit}: ${role.value.name}` : i18n.ts._role.new,
|
||||
icon: 'ti ti-badge',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -219,6 +219,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canChat, 'canChat'])">
|
||||
<template #label>{{ i18n.ts._role._options.canChat }}</template>
|
||||
<template #suffix>
|
||||
<span v-if="role.policies.canChat.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||
<span v-else>{{ role.policies.canChat.value ? i18n.ts.yes : i18n.ts.no }}</span>
|
||||
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.canChat)"></i></span>
|
||||
</template>
|
||||
<div class="_gaps">
|
||||
<MkSwitch v-model="role.policies.canChat.useDefault" :readonly="readonly">
|
||||
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
|
||||
</MkSwitch>
|
||||
<MkSwitch v-model="role.policies.canChat.value" :disabled="role.policies.canChat.useDefault" :readonly="readonly">
|
||||
<template #label>{{ i18n.ts.enable }}</template>
|
||||
</MkSwitch>
|
||||
<MkRange v-model="role.policies.canChat.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
|
||||
<template #label>{{ i18n.ts._role.priority }}</template>
|
||||
</MkRange>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
||||
<template #suffix>
|
||||
|
|
@ -769,7 +789,7 @@ import MkRange from '@/components/MkRange.vue';
|
|||
import FormSlot from '@/components/form/slot.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { deepClone } from '@/utility/clone.js';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update:modelValue', v: any): void;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="usersPagination" :displayLimit="50">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img :src="infoImageUrl" draggable="false"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -67,15 +67,15 @@ import XHeader from './_header_.vue';
|
|||
import XEditor from './roles.editor.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: `${i18n.ts.role}: ${role.name}`,
|
||||
icon: 'ti ti-badge',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkInput>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canChat, 'canChat'])">
|
||||
<template #label>{{ i18n.ts._role._options.canChat }}</template>
|
||||
<template #suffix>{{ policies.canChat ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||
<MkSwitch v-model="policies.canChat">
|
||||
<template #label>{{ i18n.ts.enable }}</template>
|
||||
</MkSwitch>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
||||
<template #suffix>{{ policies.mentionLimit }}</template>
|
||||
|
|
@ -317,12 +325,12 @@ import MkRange from '@/components/MkRange.vue';
|
|||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkRolePreview from '@/components/MkRolePreview.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import { instance, fetchInstance } from '@/instance.js';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
|
||||
const router = useRouter();
|
||||
const baseRoleQ = ref('');
|
||||
|
|
@ -365,7 +373,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.roles,
|
||||
icon: 'ti ti-badges',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -103,11 +103,11 @@ import MkRange from '@/components/MkRange.vue';
|
|||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { useForm } from '@/scripts/use-form.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import { useForm } from '@/use/use-form.js';
|
||||
import MkFormFooter from '@/components/MkFormFooter.vue';
|
||||
|
||||
const meta = await misskeyApi('admin/meta');
|
||||
|
|
@ -162,7 +162,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.security,
|
||||
icon: 'ti ti-lock',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ import XHeader from './_header_.vue';
|
|||
import * as os from '@/os.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ const remove = (index: number): void => {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.serverRules,
|
||||
icon: 'ti ti-checkbox',
|
||||
}));
|
||||
|
|
@ -122,7 +122,7 @@ definePageMetadata(() => ({
|
|||
border-radius: var(--MI-radius-sm);
|
||||
|
||||
&:hover {
|
||||
background: var(--MI_THEME-X5);
|
||||
background: light-dark(rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.05));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,15 +270,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkFolder>
|
||||
<template #icon><i class="ti ti-ghost"></i></template>
|
||||
<template #label>{{ i18n.ts.proxyAccount }}</template>
|
||||
<template v-if="proxyAccountForm.modified.value" #footer>
|
||||
<MkFormFooter :form="proxyAccountForm"/>
|
||||
</template>
|
||||
|
||||
<div class="_gaps">
|
||||
<MkInfo>{{ i18n.ts.proxyAccountDescription }}</MkInfo>
|
||||
<MkKeyValue>
|
||||
<template #key>{{ i18n.ts.proxyAccount }}</template>
|
||||
<template #value>{{ proxyAccount ? `@${proxyAccount.username}` : i18n.ts.none }}</template>
|
||||
</MkKeyValue>
|
||||
|
||||
<MkButton primary @click="chooseProxyAccount">{{ i18n.ts.selectAccount }}</MkButton>
|
||||
<MkTextarea v-model="proxyAccountForm.state.description" :max="500" tall mfmAutocomplete :mfmPreview="true">
|
||||
<template #label>{{ i18n.ts._profile.description }}</template>
|
||||
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
|
||||
</MkTextarea>
|
||||
</div>
|
||||
</MkFolder>
|
||||
</div>
|
||||
|
|
@ -288,7 +290,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, reactive } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
|
@ -296,20 +298,20 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import { useForm } from '@/scripts/use-form.js';
|
||||
import { useForm } from '@/use/use-form.js';
|
||||
import MkFormFooter from '@/components/MkFormFooter.vue';
|
||||
import MkRadios from '@/components/MkRadios.vue';
|
||||
|
||||
const meta = await misskeyApi('admin/meta');
|
||||
|
||||
const proxyAccount = ref(meta.proxyAccountId ? await misskeyApi('users/show', { userId: meta.proxyAccountId }) : null);
|
||||
const proxyAccount = await misskeyApi('users/show', { userId: meta.proxyAccountId });
|
||||
|
||||
const infoForm = useForm({
|
||||
name: meta.name ?? '',
|
||||
|
|
@ -425,16 +427,14 @@ const federationForm = useForm({
|
|||
fetchInstance(true);
|
||||
});
|
||||
|
||||
function chooseProxyAccount() {
|
||||
os.selectUser({ localOnly: true }).then(user => {
|
||||
proxyAccount.value = user;
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
proxyAccountId: user.id,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
});
|
||||
const proxyAccountForm = useForm({
|
||||
description: proxyAccount.description,
|
||||
}, async (state) => {
|
||||
await os.apiWithDialog('admin/update-proxy-account', {
|
||||
description: state.description,
|
||||
});
|
||||
}
|
||||
fetchInstance(true);
|
||||
});
|
||||
|
||||
async function genKeys() {
|
||||
if (serviceWorkerForm.savedState.swPrivateKey) {
|
||||
|
|
@ -450,7 +450,7 @@ async function genKeys() {
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: i18n.ts.general,
|
||||
icon: 'ti ti-settings',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ import { computed, onMounted, ref } from 'vue';
|
|||
import { entities } from 'misskey-js';
|
||||
import XItem from './system-webhook.item.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import XHeader from '@/pages/admin/_header_.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { showSystemWebhookEditorDialog } from '@/components/MkSystemWebhookEditor.impl.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ onMounted(async () => {
|
|||
await fetchWebhooks();
|
||||
});
|
||||
|
||||
definePageMetadata(() => ({
|
||||
definePage(() => ({
|
||||
title: 'SystemWebhook',
|
||||
icon: 'ti ti-webhook',
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :contentMax="900">
|
||||
<div class="_gaps">
|
||||
<div :class="$style.inputs">
|
||||
<MkButton style="margin-left: auto" @click="resetQuery">{{ i18n.ts.reset }}</MkButton>
|
||||
</div>
|
||||
<div :class="$style.inputs">
|
||||
<MkSelect v-model="sort" style="flex: 1;">
|
||||
<template #label>{{ i18n.ts.sort }}</template>
|
||||
|
|
@ -58,25 +61,36 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, shallowRef, ref } from 'vue';
|
||||
import { computed, useTemplateRef, ref, watchEffect } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import { defaultMemoryStorage } from '@/memory-storage';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { lookupUser } from '@/scripts/admin-lookup.js';
|
||||
import { lookupUser } from '@/utility/admin-lookup.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { dateString } from '@/filters/date.js';
|
||||
|
||||
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
type SearchQuery = {
|
||||
sort?: string;
|
||||
state?: string;
|
||||
origin?: string;
|
||||
username?: string;
|
||||
hostname?: string;
|
||||
};
|
||||
|
||||
const sort = ref('+createdAt');
|
||||
const state = ref('all');
|
||||
const origin = ref('local');
|
||||
const searchUsername = ref('');
|
||||
const searchHost = ref('');
|
||||
const paginationComponent = useTemplateRef('paginationComponent');
|
||||
const storedQuery = JSON.parse(defaultMemoryStorage.getItem('admin-users-query') ?? '{}') as SearchQuery;
|
||||
|
||||
const sort = ref(storedQuery.sort ?? '+createdAt');
|
||||
const state = ref(storedQuery.state ?? 'all');
|
||||
const origin = ref(storedQuery.origin ?? 'local');
|
||||
const searchUsername = ref(storedQuery.username ?? '');
|
||||
const searchHost = ref(storedQuery.hostname ?? '');
|
||||
const pagination = {
|
||||
endpoint: 'admin/show-users' as const,
|
||||
limit: 10,
|
||||
|
|
@ -120,6 +134,14 @@ function show(user) {
|
|||
os.pageWindow(`/admin/user/${user.id}`);
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
sort.value = '+createdAt';
|
||||
state.value = 'all';
|
||||
origin.value = 'local';
|
||||
searchUsername.value = '';
|
||||
searchHost.value = '';
|
||||
}
|
||||
|
||||
const headerActions = computed(() => [{
|
||||
icon: 'ti ti-search',
|
||||
text: i18n.ts.search,
|
||||
|
|
@ -138,7 +160,17 @@ const headerActions = computed(() => [{
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
watchEffect(() => {
|
||||
defaultMemoryStorage.setItem('admin-users-query', JSON.stringify({
|
||||
sort: sort.value,
|
||||
state: state.value,
|
||||
origin: origin.value,
|
||||
username: searchUsername.value,
|
||||
hostname: searchHost.value,
|
||||
}));
|
||||
});
|
||||
|
||||
definePage(() => ({
|
||||
title: i18n.ts.users,
|
||||
icon: 'ti ti-users',
|
||||
}));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue