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 ## Unreleased
### General ### General
- - Enhance: 広告ごとにセンシティブフラグを設定できるようになりました
### Client ### Client
- Enhance: 時刻計算のための基準値を一か所で管理するようにし、パフォーマンスを向上 - 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, ratio: ad.ratio,
imageUrl: ad.imageUrl, imageUrl: ad.imageUrl,
dayOfWeek: ad.dayOfWeek, dayOfWeek: ad.dayOfWeek,
isSensitive: ad.isSensitive ? true : undefined,
})), })),
notesPerOneAd: instance.notesPerOneAd, notesPerOneAd: instance.notesPerOneAd,
enableEmail: instance.enableEmail, enableEmail: instance.enableEmail,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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