summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkSystemWebhookEditor.vue
diff options
context:
space:
mode:
authorおさむのひと <46447427+samunohito@users.noreply.github.com>2024-06-08 15:34:19 +0900
committerGitHub <noreply@github.com>2024-06-08 15:34:19 +0900
commit61fae45390283aee7ac582aa5303aae863de0f7a (patch)
tree17182172ef9f932182fc55f2aabd7243d2be66b2 /packages/frontend/src/components/MkSystemWebhookEditor.vue
parent配信停止したインスタンス一覧が見れなくなる問題を修... (diff)
downloadsharkey-61fae45390283aee7ac582aa5303aae863de0f7a.tar.gz
sharkey-61fae45390283aee7ac582aa5303aae863de0f7a.tar.bz2
sharkey-61fae45390283aee7ac582aa5303aae863de0f7a.zip
feat: 通報を受けた際にメールまたはWebhookで通知を送出出来るようにする (#13758)
* feat: 通報を受けた際にメールまたはWebhookで通知を送出出来るようにする * モデログに対応&エンドポイントを単一オブジェクトでのサポートに変更(API経由で大量に作るシチュエーションもないと思うので) * fix spdx * fix migration * fix migration * fix models * add e2e webhook * tweak * fix modlog * fix bugs * add tests and fix bugs * add tests and fix bugs * add tests * fix path * regenerate locale * 混入除去 * 混入除去 * add abuseReportResolved * fix pnpm-lock.yaml * add abuseReportResolved test * fix bugs * fix ui * add tests * fix CHANGELOG.md * add tests * add RoleService.getModeratorIds tests * WebhookServiceをUserとSystemに分割 * fix CHANGELOG.md * fix test * insertOneを使う用に * fix * regenerate locales * revert version * separate webhook job queue * fix * :art: * Update QueueProcessorService.ts --------- Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Diffstat (limited to 'packages/frontend/src/components/MkSystemWebhookEditor.vue')
-rw-r--r--packages/frontend/src/components/MkSystemWebhookEditor.vue217
1 files changed, 217 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.vue b/packages/frontend/src/components/MkSystemWebhookEditor.vue
new file mode 100644
index 0000000000..007d841f00
--- /dev/null
+++ b/packages/frontend/src/components/MkSystemWebhookEditor.vue
@@ -0,0 +1,217 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<MkModalWindow
+ :width="450"
+ :height="590"
+ :canClose="true"
+ :withOkButton="false"
+ :okButtonDisabled="false"
+ @click="onCancelClicked"
+ @close="onCancelClicked"
+ @closed="onCancelClicked"
+>
+ <template #header>
+ {{ mode === 'create' ? i18n.ts._webhookSettings.createWebhook : i18n.ts._webhookSettings.modifyWebhook }}
+ </template>
+ <MkSpacer :marginMin="20" :marginMax="28">
+ <MkLoading v-if="loading !== 0"/>
+ <div v-else :class="$style.root" class="_gaps_m">
+ <MkInput v-model="title">
+ <template #label>{{ i18n.ts._webhookSettings.name }}</template>
+ </MkInput>
+ <MkInput v-model="url">
+ <template #label>URL</template>
+ </MkInput>
+ <MkInput v-model="secret">
+ <template #label>{{ i18n.ts._webhookSettings.secret }}</template>
+ </MkInput>
+ <MkFolder :defaultOpen="true">
+ <template #label>{{ i18n.ts._webhookSettings.events }}</template>
+
+ <div class="_gaps_s">
+ <MkSwitch v-model="events.abuseReport" :disabled="disabledEvents.abuseReport">
+ <template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReport }}</template>
+ </MkSwitch>
+ <MkSwitch v-model="events.abuseReportResolved" :disabled="disabledEvents.abuseReportResolved">
+ <template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReportResolved }}</template>
+ </MkSwitch>
+ </div>
+ </MkFolder>
+
+ <MkSwitch v-model="isActive">
+ <template #label>{{ i18n.ts.enable }}</template>
+ </MkSwitch>
+
+ <div :class="$style.footer" class="_buttonsCenter">
+ <MkButton primary :disabled="disableSubmitButton" @click="onSubmitClicked">
+ <i class="ti ti-check"></i>
+ {{ i18n.ts.ok }}
+ </MkButton>
+ <MkButton @click="onCancelClicked"><i class="ti ti-x"></i> {{ i18n.ts.cancel }}</MkButton>
+ </div>
+ </div>
+ </MkSpacer>
+</MkModalWindow>
+</template>
+
+<script setup lang="ts">
+import { computed, onMounted, ref, toRefs } from 'vue';
+import FormSection from '@/components/form/section.vue';
+import MkInput from '@/components/MkInput.vue';
+import MkSwitch from '@/components/MkSwitch.vue';
+import {
+ MkSystemWebhookEditorProps,
+ MkSystemWebhookResult,
+ SystemWebhookEventType,
+} from '@/components/MkSystemWebhookEditor.impl.js';
+import { i18n } from '@/i18n.js';
+import MkButton from '@/components/MkButton.vue';
+import { misskeyApi } from '@/scripts/misskey-api.js';
+import MkModalWindow from '@/components/MkModalWindow.vue';
+import MkFolder from '@/components/MkFolder.vue';
+import * as os from '@/os.js';
+
+type EventType = {
+ abuseReport: boolean;
+ abuseReportResolved: boolean;
+}
+
+const emit = defineEmits<{
+ (ev: 'submitted', result: MkSystemWebhookResult): void;
+ (ev: 'closed'): void;
+}>();
+
+const props = defineProps<MkSystemWebhookEditorProps>();
+
+const { mode, id, requiredEvents } = toRefs(props);
+
+const loading = ref<number>(0);
+
+const title = ref<string>('');
+const url = ref<string>('');
+const secret = ref<string>('');
+const events = ref<EventType>({
+ abuseReport: true,
+ abuseReportResolved: true,
+});
+const isActive = ref<boolean>(true);
+
+const disabledEvents = ref<EventType>({
+ abuseReport: false,
+ abuseReportResolved: false,
+});
+
+const disableSubmitButton = computed(() => {
+ if (!title.value) {
+ return true;
+ }
+ if (!url.value) {
+ return true;
+ }
+ if (!secret.value) {
+ return true;
+ }
+
+ return false;
+});
+
+async function onSubmitClicked() {
+ await loadingScope(async () => {
+ const params = {
+ isActive: isActive.value,
+ name: title.value,
+ url: url.value,
+ secret: secret.value,
+ on: Object.keys(events.value).filter(ev => events.value[ev as keyof EventType]) as SystemWebhookEventType[],
+ };
+
+ try {
+ switch (mode.value) {
+ case 'create': {
+ const result = await misskeyApi('admin/system-webhook/create', params);
+ emit('submitted', result);
+ break;
+ }
+ case 'edit': {
+ // eslint-disable-next-line
+ const result = await misskeyApi('admin/system-webhook/update', { id: id.value!, ...params });
+ emit('submitted', result);
+ break;
+ }
+ }
+ // eslint-disable-next-line
+ } catch (ex: any) {
+ const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
+ await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
+ emit('closed');
+ }
+ });
+}
+
+function onCancelClicked() {
+ emit('closed');
+}
+
+async function loadingScope<T>(fn: () => Promise<T>): Promise<T> {
+ loading.value++;
+ try {
+ return await fn();
+ } finally {
+ loading.value--;
+ }
+}
+
+onMounted(async () => {
+ await loadingScope(async () => {
+ switch (mode.value) {
+ case 'edit': {
+ if (!id.value) {
+ throw new Error('id is required');
+ }
+
+ try {
+ const res = await misskeyApi('admin/system-webhook/show', { id: id.value });
+
+ title.value = res.name;
+ url.value = res.url;
+ secret.value = res.secret;
+ isActive.value = res.isActive;
+ for (const ev of Object.keys(events.value)) {
+ events.value[ev] = res.on.includes(ev as SystemWebhookEventType);
+ }
+ // eslint-disable-next-line
+ } catch (ex: any) {
+ const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
+ await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
+ emit('closed');
+ }
+ break;
+ }
+ }
+
+ for (const ev of requiredEvents.value ?? []) {
+ disabledEvents.value[ev] = true;
+ }
+ });
+});
+</script>
+
+<style module lang="scss">
+.root {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: stretch;
+}
+
+.footer {
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ margin-top: 20px;
+}
+</style>