Skip to content

feat(backend): 一括更新に remove_label_ids を追加 - #537

Open
yupix wants to merge 10 commits into
feat/task-label-activityfrom
feat/task-label-bulk-remove
Open

feat(backend): 一括更新に remove_label_ids を追加#537
yupix wants to merge 10 commits into
feat/task-label-activityfrom
feat/task-label-bulk-remove

Conversation

@yupix

@yupix yupix commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #536

概要

一括更新(POST /tasks/bulk)はラベルの追加(add_label_ids)しかできず、外す手段がなかった。単一更新が置き換え(label_ids)を持った今、一括側にも取り外しを追加して対称にする。

変更内容

  • BulkUpdateFieldsremove_label_ids を追加。指定 ID のラベルをタスクから外す
  • 未付与・プロジェクト外の ID は無害なため検証せず単に無視する(no-op)。doc コメントに明記
  • add_label_idsremove_label_ids に同じ ID が含まれるリクエストは全体を 400 で拒否(暗黙の後勝ちより明示的なエラー)
  • feat(backend): ラベル変更の labels_changed アクティビティ記録 #536 の前後スナップショットがラベル変更セクション全体を挟んでいるため、remove も追加コードなしで labels_changed アクティビティに記録される
  • openapi.json / CLI 型を再生成

挙動の変化

  • POST /tasks/bulkupdate.remove_label_ids で複数タスクからラベルを一括で外せる
  • add と remove の同一 ID 指定は 400

テスト

  • 統合テスト(task_labels_integration.rs): remove でラベルが外れて labels_changed が記録される / add∩remove は 400 / 他プロジェクト ID の remove は 200 の no-op で記録もされない
  • cargo fmt / clippy / test --lib / 対象統合テスト(labels + extensions)すべて PASS

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

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"

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploying koyori with  Cloudflare Pages  Cloudflare Pages

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

View logs

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

Coverage Report for apps/frontend

Status Category Percentage Covered / Total
🟢 Lines 86.37% 1306 / 1512
🟢 Statements 83.33% 1440 / 1728
🟢 Functions 84.69% 570 / 673
🟡 Branches 76.3% 1066 / 1397
File CoverageNo changed files found.
Generated in workflow #2072 for commit a067169 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

📦 Frontend bundle diagnostics

Metric Before After Δ Δ (%)
Raw 2.23 MB 2.23 MB 0 B 0.0%
Gzip 727.0 KB 727.0 KB 0 B 0.0%
Brotli 630.1 KB 630.1 KB 0 B 0.0%
Zstd 762.5 KB 762.5 KB 0 B 0.0%

zstd (and gzip/brotli) are per-part compression sums, not one-shot compressed sizes for whole chunks. Suitable for before/after deltas; absolute values overstate real delivery size.

Chunk changes

Chunk Status Raw Δ Raw Δ (%) Gzip Δ Gzip Δ (%) Brotli Δ Brotli Δ (%) Zstd Δ Zstd Δ (%)
No changed chunks

Open interactive treemap

yupix added 2 commits August 14, 2026 02:49
- 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
yupix force-pushed the feat/task-label-bulk-remove branch from 0d48d2d to 347c3a1 Compare August 13, 2026 17:50
yupix added 2 commits August 14, 2026 02:57
- 単一更新(label_ids 置き換え)と一括更新(add_label_ids)の両方で、変更前後の
  ラベル名(ソート済み)を比較し、実際に集合が変わったときだけ
  labels_changed { from, to } を記録する
- ステータス・担当者は一括更新でも記録されるのにラベルだけ記録されていなかった
  非一貫の解消。名前ベースの payload は status_changed の形式に合わせた
- service::task_activities に task_label_names ヘルパーを追加(両ハンドラーで共用)
- 統合テスト: 置き換えで記録 / 同一集合の置き換えは記録なし / 一括追加で記録 /
  付与済みラベルの一括追加は記録なし
yupix added 6 commits August 14, 2026 02:58
- 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
yupix force-pushed the feat/task-label-bulk-remove branch from 347c3a1 to a067169 Compare August 13, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant