From b05d71fabff55ac5653994a1188c6db88048e8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:49:26 +0900 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E4=BB=8A=E6=97=A5=E8=AA=95?= =?UTF-8?q?=E7=94=9F=E6=97=A5=E3=81=AE=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E4=B8=AD=E3=81=AE=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=82=92?= =?UTF-8?q?=E4=B8=80=E8=A6=A7=E8=A1=A8=E7=A4=BA=E3=81=A7=E3=81=8D=E3=82=8B?= =?UTF-8?q?=E3=82=A6=E3=82=A3=E3=82=B8=E3=82=A7=E3=83=83=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20(#12450)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * (add) 今日誕生日のフォロイー一覧表示 * Update Changelog * Update Changelog * 実装漏れ * create index * (fix) index --- CHANGELOG.md | 1 + locales/index.d.ts | 1 + locales/ja-JP.yml | 1 + .../migration/1700902349231-add-bday-index.js | 16 +++ packages/backend/src/models/UserProfile.ts | 1 + .../server/api/endpoints/users/following.ts | 23 ++++ .../src/widgets/WidgetBirthdayFollowings.vue | 127 ++++++++++++++++++ packages/frontend/src/widgets/index.ts | 2 + 8 files changed, 172 insertions(+) create mode 100644 packages/backend/migration/1700902349231-add-bday-index.js create mode 100644 packages/frontend/src/widgets/WidgetBirthdayFollowings.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index db26ffc8ee..e40c5f0fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正 ### Client +- Feat: 今日誕生日のフォロー中のユーザーを一覧表示できるウィジェットを追加 - Enhance: 絵文字のオートコンプリート機能強化 #12364 - Enhance: ユーザーのRawデータを表示するページが復活 - Enhance: リアクション選択時に音を鳴らせるように diff --git a/locales/index.d.ts b/locales/index.d.ts index 6036c6fa66..d462816494 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2110,6 +2110,7 @@ export interface Locale { "chooseList": string; }; "clicker": string; + "birthdayFollowings": string; }; "_cw": { "hide": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0f4164652c..aa3cdf0750 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2014,6 +2014,7 @@ _widgets: _userList: chooseList: "リストを選択" clicker: "クリッカー" + birthdayFollowings: "今日誕生日のユーザー" _cw: hide: "隠す" diff --git a/packages/backend/migration/1700902349231-add-bday-index.js b/packages/backend/migration/1700902349231-add-bday-index.js new file mode 100644 index 0000000000..251526fc26 --- /dev/null +++ b/packages/backend/migration/1700902349231-add-bday-index.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AddBdayIndex1700902349231 { + name = 'AddBdayIndex1700902349231' + + async up(queryRunner) { + await queryRunner.query(`CREATE INDEX "IDX_de22cd2b445eee31ae51cdbe99" ON "user_profile" (SUBSTR("birthday", 6, 5))`); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_de22cd2b445eee31ae51cdbe99"`); + } +} diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts index 8a43b60039..6659a01412 100644 --- a/packages/backend/src/models/UserProfile.ts +++ b/packages/backend/src/models/UserProfile.ts @@ -29,6 +29,7 @@ export class MiUserProfile { }) public location: string | null; + @Index() @Column('char', { length: 10, nullable: true, comment: 'The birthday (YYYY-MM-DD) of the User.', diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 03487275a3..ead7ba8c40 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -42,6 +42,12 @@ export const meta = { code: 'FORBIDDEN', id: 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', }, + + birthdayInvalid: { + message: 'Birthday date format is invalid.', + code: 'BIRTHDAY_DATE_FORMAT_INVALID', + id: 'a2b007b9-4782-4eba-abd3-93b05ed4130d', + }, }, } as const; @@ -59,6 +65,8 @@ export const paramDef = { nullable: true, description: 'The local host is represented with `null`.', }, + + birthday: { type: 'string', nullable: true }, }, anyOf: [ { required: ['userId'] }, @@ -117,6 +125,21 @@ export default class extends Endpoint { // eslint- .andWhere('following.followerId = :userId', { userId: user.id }) .innerJoinAndSelect('following.followee', 'followee'); + if (ps.birthday) { + try { + const d = new Date(ps.birthday); + d.setHours(0, 0, 0, 0); + const birthday = `${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`; + const birthdayUserQuery = this.userProfilesRepository.createQueryBuilder('user_profile'); + birthdayUserQuery.select('user_profile.userId') + .where(`SUBSTR(user_profile.birthday, 6, 5) = '${birthday}'`); + + query.andWhere(`following.followeeId IN (${ birthdayUserQuery.getQuery() })`); + } catch (err) { + throw new ApiError(meta.errors.birthdayInvalid); + } + } + const followings = await query .limit(ps.limit) .getMany(); diff --git a/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue b/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue new file mode 100644 index 0000000000..7c4455516d --- /dev/null +++ b/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue @@ -0,0 +1,127 @@ + + + + + + + diff --git a/packages/frontend/src/widgets/index.ts b/packages/frontend/src/widgets/index.ts index 405c49ab06..36925e1bd8 100644 --- a/packages/frontend/src/widgets/index.ts +++ b/packages/frontend/src/widgets/index.ts @@ -33,6 +33,7 @@ export default function(app: App) { app.component('WidgetAichan', defineAsyncComponent(() => import('./WidgetAichan.vue'))); app.component('WidgetUserList', defineAsyncComponent(() => import('./WidgetUserList.vue'))); app.component('WidgetClicker', defineAsyncComponent(() => import('./WidgetClicker.vue'))); + app.component('WidgetBirthdayFollowings', defineAsyncComponent(() => import('./WidgetBirthdayFollowings.vue'))); } export const widgets = [ @@ -63,4 +64,5 @@ export const widgets = [ 'aichan', 'userList', 'clicker', + 'birthdayFollowings', ];