feat(backend): 一括更新に remove_label_ids を追加 - #537
Open
yupix wants to merge 10 commits into
Open
Conversation
OpenAPI diff (apps/frontend/openapi.json)diff --git a/apps/frontend/openapi.json b/apps/frontend/openapi.json
index 7c01da0..09a0eb1 100644
--- a/apps/frontend/openapi.json
+++ b/apps/frontend/openapi.json
@@ -12555,6 +12555,15 @@
"format": "uuid"
}
},
+ {
+ "name": "label_id",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "format": "uuid"
+ }
+ },
{
"name": "milestone_id",
"in": "query",
@@ -17987,6 +17996,14 @@
"clear_sprint_id": {
"type": "boolean"
},
+ "remove_label_ids": {
+ "type": ["array", "null"],
+ "items": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "既存ラベルから外す ID 一覧。未付与・プロジェクト外の ID は単に無視される。\nadd_label_ids と同じ ID を含む場合は 400"
+ },
"sprint_id": {
"type": ["string", "null"],
"format": "uuid"
@@ -20088,6 +20105,7 @@
"progress_pct",
"is_archived",
"assignees",
+ "labels",
"created_at",
"updated_at"
],
@@ -20139,6 +20157,12 @@
"is_archived": {
"type": "boolean"
},
+ "labels": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/LabelResponse"
+ }
+ },
"milestone_id": {
"type": ["string", "null"],
"format": "uuid"
@@ -20604,6 +20628,14 @@
"is_archived": {
"type": ["boolean", "null"]
},
+ "label_ids": {
+ "type": ["array", "null"],
+ "items": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "タスクのラベルをこの ID 集合で置き換える(`Some(vec![])` で全解除)。None は変更なし"
+ },
"milestone_id": {
"type": ["string", "null"],
"format": "uuid" |
Deploying koyori with
|
| Latest commit: |
a067169
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://7d15582a.koyori.pages.dev |
| Branch Preview URL: | https://feat-task-label-bulk-remove.koyori.pages.dev |
Coverage Report for apps/frontend
File CoverageNo changed files found. |
📦 Frontend bundle diagnostics
Chunk changes
|
yupix
force-pushed
the
feat/task-label-bulk-remove
branch
from
August 13, 2026 14:47
0849b73 to
94b55b9
Compare
yupix
force-pushed
the
feat/task-label-bulk-remove
branch
from
August 13, 2026 16:26
94b55b9 to
b4efc0a
Compare
yupix
force-pushed
the
feat/task-label-bulk-remove
branch
from
August 13, 2026 17:25
b4efc0a to
0d48d2d
Compare
- ListTasksQuery に label_id を追加し、assignee_id と同じ EXISTS サブクエリで 指定ラベルが付与されたタスクのみに絞り込む - 一覧ページのツールバーにラベルフィルタ(ラジオ選択・「すべて」で解除)を追加。 検索中は他のリスト操作と同様に非表示。切替時は先頭ページへ戻す - 仕様書 §4.1 のクエリパラメータ表に label_id を追記、openapi.json / CLI 型を再生成 - 一覧ページが labels API を叩くようになったため、TaskTable ストーリーの fetch モックに /labels 分岐を追加(従来はプロジェクト一覧の分岐に吸われていた)。 タスクフィクスチャにも labels を補完 - 統合テスト: label_id フィルタで対象タスクのみ返ること・非対象ラベルで 0 件に なることを追加
PR #535 レビュー指摘対応: - 指摘1: tasksQuery の placeholderData が label_id を比較しておらず、 フィルタ切替中も旧条件のタスクが表示され続けていた。前クエリの label_id と現在の選択が一致する場合(=ページング時)のみ keepPreviousData を返すよう修正 - 指摘2: createProjectSwitchMockFetch のプロジェクト一覧分岐が /labels を除外しておらず、ラベル一覧にプロジェクトを返していた。 /labels 分岐をプロジェクト別 fixture で追加 - 指摘3: ラベル一覧の取得失敗時にフィルタが無言で消えていた。 ツールバー内にエラー表示と再試行ボタンを追加(タスク一覧は ブロックしない) 回帰テスト: - story「ラベルフィルタで旧条件タスク非表示」: 絞り込みレスポンスを 保留し、旧条件タスクが表示されないことを検証(修正前は fail を確認) - story「ラベル取得エラー」: labels API 500 時のエラー表示・再試行 ボタン・タスク一覧非ブロックを検証 - story「プロジェクト切替で旧タスク非表示」: 切替後のドロップダウンに 切替先プロジェクトのラベルのみが並ぶ検証を追加
yupix
force-pushed
the
feat/task-label-bulk-remove
branch
from
August 13, 2026 17:50
0d48d2d to
347c3a1
Compare
- 単一更新(label_ids 置き換え)と一括更新(add_label_ids)の両方で、変更前後の
ラベル名(ソート済み)を比較し、実際に集合が変わったときだけ
labels_changed { from, to } を記録する
- ステータス・担当者は一括更新でも記録されるのにラベルだけ記録されていなかった
非一貫の解消。名前ベースの payload は status_changed の形式に合わせた
- service::task_activities に task_label_names ヘルパーを追加(両ハンドラーで共用)
- 統合テスト: 置き換えで記録 / 同一集合の置き換えは記録なし / 一括追加で記録 /
付与済みラベルの一括追加は記録なし
- BulkUpdateFields に remove_label_ids を追加。指定 ID のラベルをタスクから外す。 未付与・プロジェクト外の ID は無害なため検証せず単に無視する(no-op) - add_label_ids と remove_label_ids に同じ ID が含まれる場合は全体を 400 で拒否 (暗黙の後勝ちより明示的なエラーを優先) - ラベル変更セクションを挟む前後スナップショット(前 PR)により、remove も labels_changed アクティビティの記録対象になる - 統合テスト: remove で外れる / add∩remove は 400 / 他プロジェクト ID の remove は 200 の no-op で記録もされない - openapi.json / CLI 型を再生成
yupix
force-pushed
the
feat/task-label-bulk-remove
branch
from
August 13, 2026 17:58
347c3a1 to
a067169
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #536
概要
一括更新(
POST /tasks/bulk)はラベルの追加(add_label_ids)しかできず、外す手段がなかった。単一更新が置き換え(label_ids)を持った今、一括側にも取り外しを追加して対称にする。変更内容
BulkUpdateFieldsにremove_label_idsを追加。指定 ID のラベルをタスクから外すadd_label_idsとremove_label_idsに同じ ID が含まれるリクエストは全体を 400 で拒否(暗黙の後勝ちより明示的なエラー)labels_changedアクティビティに記録されるopenapi.json/ CLI 型を再生成挙動の変化
POST /tasks/bulkのupdate.remove_label_idsで複数タスクからラベルを一括で外せるテスト
task_labels_integration.rs): remove でラベルが外れてlabels_changedが記録される / add∩remove は 400 / 他プロジェクト ID の remove は 200 の no-op で記録もされないcargo fmt/clippy/test --lib/ 対象統合テスト(labels + extensions)すべて PASS