enhance: 広告ごとにセンシティブフラグを設定できるように

This commit is contained in:
syuilo 2025-09-14 15:25:22 +09:00
parent d4654dd7bd
commit 2621f468ff
12 changed files with 62 additions and 2 deletions

View File

@ -1,7 +1,7 @@
## Unreleased
### General
-
- Enhance: 広告ごとにセンシティブフラグを設定できるようになりました
### Client
- Enhance: 時刻計算のための基準値を一か所で管理するようにし、パフォーマンスを向上

View File

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SensitiveAd1757823175259 {
name = 'SensitiveAd1757823175259'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "ad" ADD "isSensitive" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "isSensitive"`);
}
}

View File

@ -117,6 +117,7 @@ export class MetaEntityService {
ratio: ad.ratio,
imageUrl: ad.imageUrl,
dayOfWeek: ad.dayOfWeek,
isSensitive: ad.isSensitive ? true : undefined,
})),
notesPerOneAd: instance.notesPerOneAd,
enableEmail: instance.enableEmail,

View File

@ -54,10 +54,17 @@ export class MiAd {
length: 8192, nullable: false,
})
public memo: string;
@Column('integer', {
default: 0, nullable: false,
})
public dayOfWeek: number;
@Column('boolean', {
default: false,
})
public isSensitive: boolean;
constructor(data: Partial<MiAd>) {
if (data == null) return;

View File

@ -60,5 +60,10 @@ export const packedAdSchema = {
optional: false,
nullable: false,
},
isSensitive: {
type: 'boolean',
optional: false,
nullable: false,
},
},
} as const;

View File

@ -195,6 +195,10 @@ export const packedMetaLiteSchema = {
type: 'integer',
optional: false, nullable: false,
},
isSensitive: {
type: 'boolean',
optional: true, nullable: false,
},
},
},
},

View File

@ -36,6 +36,7 @@ export const paramDef = {
startsAt: { type: 'integer' },
imageUrl: { type: 'string', minLength: 1 },
dayOfWeek: { type: 'integer' },
isSensitive: { type: 'boolean' },
},
required: ['url', 'memo', 'place', 'priority', 'ratio', 'expiresAt', 'startsAt', 'imageUrl', 'dayOfWeek'],
} as const;
@ -55,6 +56,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
expiresAt: new Date(ps.expiresAt),
startsAt: new Date(ps.startsAt),
dayOfWeek: ps.dayOfWeek,
isSensitive: ps.isSensitive,
url: ps.url,
imageUrl: ps.imageUrl,
priority: ps.priority,
@ -73,6 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
expiresAt: ad.expiresAt.toISOString(),
startsAt: ad.startsAt.toISOString(),
dayOfWeek: ad.dayOfWeek,
isSensitive: ad.isSensitive,
url: ad.url,
imageUrl: ad.imageUrl,
priority: ad.priority,

View File

@ -63,6 +63,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
expiresAt: ad.expiresAt.toISOString(),
startsAt: ad.startsAt.toISOString(),
dayOfWeek: ad.dayOfWeek,
isSensitive: ad.isSensitive,
url: ad.url,
imageUrl: ad.imageUrl,
memo: ad.memo,

View File

@ -39,6 +39,7 @@ export const paramDef = {
expiresAt: { type: 'integer' },
startsAt: { type: 'integer' },
dayOfWeek: { type: 'integer' },
isSensitive: { type: 'boolean' },
},
required: ['id'],
} as const;
@ -66,6 +67,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : undefined,
startsAt: ps.startsAt ? new Date(ps.startsAt) : undefined,
dayOfWeek: ps.dayOfWeek,
isSensitive: ps.isSensitive,
});
const updatedAd = await this.adsRepository.findOneByOrFail({ id: ad.id });

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { expect, userEvent, waitFor, within } from '@storybook/test';
import MkAd from './MkAd.vue';
import type { StoryObj } from '@storybook/vue3';
@ -75,6 +75,7 @@ const common = {
place: '',
imageUrl: '',
dayOfWeek: 7,
isSensitive: false,
},
},
parameters: {

View File

@ -9,21 +9,26 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSelect v-model="filterType" :items="filterTypeDef" :class="$style.input" @update:modelValue="filterItems">
<template #label>{{ i18n.ts.state }}</template>
</MkSelect>
<div>
<div v-for="ad in ads" class="_panel _gaps_m" :class="$style.ad">
<MkAd v-if="ad.url" :key="ad.id" :specify="ad"/>
<MkInput v-model="ad.url" type="url">
<template #label>URL</template>
</MkInput>
<MkInput v-model="ad.imageUrl" type="url">
<template #label>{{ i18n.ts.imageUrl }}</template>
</MkInput>
<MkRadios v-model="ad.place">
<template #label>Form</template>
<option value="square">square</option>
<option value="horizontal">horizontal</option>
<option value="horizontal-big">horizontal-big</option>
</MkRadios>
<!--
<div style="margin: 32px 0;">
{{ i18n.ts.priority }}
@ -32,6 +37,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkRadio v-model="ad.priority" value="low">{{ i18n.ts.low }}</MkRadio>
</div>
-->
<FormSplit>
<MkInput v-model="ad.ratio" type="number">
<template #label>{{ i18n.ts.ratio }}</template>
@ -43,6 +49,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.expiration }}</template>
</MkInput>
</FormSplit>
<MkSwitch v-model="ad.isSensitive">
<template #label>{{ i18n.ts.sensitive }}</template>
</MkSwitch>
<MkFolder>
<template #label>{{ i18n.ts.advancedSettings }}</template>
<span>
@ -56,9 +67,11 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</span>
</MkFolder>
<MkTextarea v-model="ad.memo">
<template #label>{{ i18n.ts.memo }}</template>
</MkTextarea>
<div class="_buttons">
<MkButton inline primary style="margin-right: 12px;" @click="save(ad)">
<i
@ -70,6 +83,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkButton>
</div>
</div>
<MkButton @click="more()">
<i class="ti ti-reload"></i>{{ i18n.ts.more }}
</MkButton>
@ -88,6 +102,7 @@ import MkRadios from '@/components/MkRadios.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkSelect from '@/components/MkSelect.vue';
import FormSplit from '@/components/form/split.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
@ -158,6 +173,7 @@ function add() {
expiresAt: new Date().toISOString(),
startsAt: new Date().toISOString(),
dayOfWeek: 0,
isSensitive: false,
});
}

View File

@ -4285,6 +4285,7 @@ export type components = {
imageUrl: string;
memo: string;
dayOfWeek: number;
isSensitive: boolean;
};
Announcement: {
/**
@ -5381,6 +5382,7 @@ export type components = {
/** Format: url */
imageUrl: string;
dayOfWeek: number;
isSensitive?: boolean;
}[];
/** @default 0 */
notesPerOneAd: number;
@ -6242,6 +6244,7 @@ export interface operations {
startsAt: number;
imageUrl: string;
dayOfWeek: number;
isSensitive?: boolean;
};
};
};
@ -6454,6 +6457,7 @@ export interface operations {
expiresAt?: number;
startsAt?: number;
dayOfWeek?: number;
isSensitive?: boolean;
};
};
};