Skip to content

feat: org_only 公開範囲の完全編集対応#161

Merged
is0692vs merged 10 commits intomainfrom
feat/org-only-edit-complete
Mar 22, 2026
Merged

feat: org_only 公開範囲の完全編集対応#161
is0692vs merged 10 commits intomainfrom
feat/org-only-edit-complete

Conversation

@is0692vs
Copy link
Copy Markdown
Contributor

@is0692vs is0692vs commented Mar 20, 2026

概要

org_only 公開範囲の論文を、作成から編集まで一貫して正しく扱えるようにしました。

変更点

  • API の papers ルートで org_only 編集フローに必要な検証・更新処理を強化
  • API テストを追加・更新し、org_only 編集ケースを網羅
  • Web の論文編集ページで org_only の表示・保存処理を改善
  • フロントエンドテストを追加・更新し、編集画面の動作を確認

テスト

  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx

Greptile Summary

このPRは org_only 公開範囲の論文について、作成から編集まで一貫して正しく扱えるようにするもので、API・フロントエンド・テストにわたる包括的な対応です。以前は編集画面で org_only への変更が完全にブロックされていましたが、今回の変更により組織選択 UI とそれに対応するバックエンド検証(メンバーシップチェック・paperOrgs の置換)が実装されました。

主な変更点:

  • API GET /api/papers/:id: paperOrgs JOIN を追加し、関連組織を常に返すよう変更
  • API PATCH /api/papers/:id: orgIds の受付・検証・メンバーシップチェック・paperOrgs の delete+insert を実装。org_only 以外への変更時は paperOrgs を削除
  • Web 編集ページ: ユーザーの所属組織一覧を並行取得し、org_only 選択時に組織チェックボックス UI を表示
  • テスト: API・フロントエンドともに org_only 編集ケース(成功・バリデーション失敗・メンバー外拒否)を網羅するテストを追加

指摘事項:

  • loadingOrgs 状態は loading と同じ finally ブロックで false にセットされるため、フォームが表示される時点では常に false であり、submit ガードとフィールドセット内のローディング表示はデッドコードになっている
  • org_only 論文の保存時に、組織選択が変更されていなくても毎回 paperOrgs の全削除・再挿入が実行される(フロントエンドが常に orgIds を送信するため)
  • GET /api/papers/:id で visibility に関係なく全論文で組織情報の JOIN が実行されるようになり、ホットパスにパフォーマンスオーバーヘッドが生じる可能性がある
  • if (orgIdsFromBody && ...) は JavaScript の空配列が truthy であることを前提とした条件式であり、orgIdsFromBody !== undefined とした方が意図が明確

Confidence Score: 3/5

  • 機能的には動作するが、デッドコードと毎回の不要な DB 書き換えによる軽微な品質・パフォーマンス問題が残っており、マージ前の確認を推奨
  • org_only の検証ロジック(メンバーシップチェック・空配列ガード・visibility 整合性)は正しく実装されており、テストカバレッジも適切。ただし loadingOrgs のデッドコード、保存ごとの不要な paperOrgs 全置換、GET ホットパスへの JOIN 追加という品質・パフォーマンス懸念が複数存在するため、満点ではない。
  • apps/api/src/routes/papers.ts(GET の JOIN オーバーヘッドと PATCH の paperOrgs 置換ロジック)と apps/web/src/app/papers/[id]/edit/page.tsx(loadingOrgs デッドコード・orgIds 常時送信)に注意が必要

Important Files Changed

Filename Overview
apps/api/src/routes/papers.ts GET エンドポイントに組織取得クエリを追加、PATCH エンドポイントに org_only 編集の完全サポートを追加。組織メンバーシップ検証ロジックは適切だが、全論文で常に JOIN が走るパフォーマンス懸念と、空配列の truthy 性に関するロジックの明確性に改善余地あり。
apps/web/src/app/papers/[id]/edit/page.tsx org_only 公開範囲の組織選択 UI を追加。loadingOrgs が到達不能なデッドコード化しており、また毎回の保存で paperOrgs を不必要に全置換する非効率な実装が含まれている。
apps/api/src/routes/tests/papers.test.ts org_only 編集ケース(切り替え時の orgIds 必須検証・更新・メンバー外拒否)のテストを追加。既存テストに組織情報モックを追加。網羅性は良好。
apps/web/src/app/tests/paper-edit-page.test.tsx 組織選択 UI のテストを追加し、orgIds が正しく PATCH ペイロードに含まれることを確認。テストは整理されており問題なし。

Sequence Diagram

sequenceDiagram
    participant Browser as ブラウザ (編集ページ)
    participant API as API サーバー
    participant DB as データベース

    Browser->>API: GET /api/papers/:id
    API->>DB: SELECT paper
    API->>DB: batch([paperFiles, paperAuthors, paperOrgs+orgs])
    DB-->>API: paper情報 + organizations[]
    API-->>Browser: { paper, authors, organizations }

    Browser->>API: GET /api/users/me/orgs
    API-->>Browser: { organizations: UserOrganization[] }

    Note over Browser: ユーザーが visibility=org_only を選択<br/>チェックボックスで対象組織を選択

    Browser->>API: PATCH /api/papers/:id<br/>{ visibility: "org_only", orgIds: ["org-1"] }
    API->>DB: SELECT paper (visibility確認)
    API->>DB: SELECT paperAuthors (著者確認)
    API->>DB: SELECT orgMembers WHERE orgId IN orgIds (メンバーシップ検証)
    alt メンバーでない場合
        API-->>Browser: 403 Forbidden
    else 正常
        API->>DB: UPDATE papers SET visibility, updatedAt
        API->>DB: DELETE paperOrgs WHERE paperId
        API->>DB: INSERT paperOrgs (paperId, orgId) × n件
        API-->>Browser: { ok: true }
    end
Loading

Comments Outside Diff (2)

  1. apps/web/src/app/papers/[id]/edit/page.tsx, line 208-213 (link)

    P2 org_only 保存時に毎回 paperOrgs を全削除・再挿入

    orgIds はフォーム保存のたびに常に送信されます(visibility === "org_only" の場合)。API 側ではこれを受け取ると、組織の選択が変更されていなくても毎回 paperOrgs を DELETE → INSERT で完全に置き換えます(papers.ts 1307〜1311行目)。

    対象組織を変更しないまま他のフィールド(タイトルなど)のみを更新した場合でも、不必要な DB 書き込みが発生します。フロントエンド側で初期値と現在値を比較して変更があった場合のみ orgIds を送信するか、API 側で現在の paperOrgs と比較してから更新するアプローチを検討してください。

    または、サブミット時に変更フラグを保持する実装に変更することを推奨します。

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/web/src/app/papers/[id]/edit/page.tsx
    Line: 208-213
    
    Comment:
    **`org_only` 保存時に毎回 `paperOrgs` を全削除・再挿入**
    
    `orgIds` はフォーム保存のたびに常に送信されます(`visibility === "org_only"` の場合)。API 側ではこれを受け取ると、組織の選択が変更されていなくても毎回 `paperOrgs` を DELETE → INSERT で完全に置き換えます(`papers.ts` 1307〜1311行目)。
    
    対象組織を変更しないまま他のフィールド(タイトルなど)のみを更新した場合でも、不必要な DB 書き込みが発生します。フロントエンド側で初期値と現在値を比較して変更があった場合のみ `orgIds` を送信するか、API 側で現在の `paperOrgs` と比較してから更新するアプローチを検討してください。
    
    
    
    または、サブミット時に変更フラグを保持する実装に変更することを推奨します。
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. apps/api/src/routes/papers.ts, line 541-578 (link)

    P2 全論文取得時に組織情報を常に JOIN

    GET /api/papers/:id エンドポイントでは、visibility に関わらず全論文で paperOrgsorgs の JOIN を常に実行するようになりました。publicprivate の論文では organizations は常に空配列になるにもかかわらず、毎回余分なクエリが走ります。

    このエンドポイントは論文ビューページからも呼び出される可能性が高く、ホットパスになりえます。visibility === 'org_only' の場合のみ組織を取得するか、編集ページ専用のエンドポイント(例: GET /api/papers/:id/edit)を用意することで、パフォーマンスへの影響を最小化できます。

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/api/src/routes/papers.ts
    Line: 541-578
    
    Comment:
    **全論文取得時に組織情報を常に JOIN**
    
    `GET /api/papers/:id` エンドポイントでは、`visibility` に関わらず全論文で `paperOrgs``orgs` の JOIN を常に実行するようになりました。`public``private` の論文では `organizations` は常に空配列になるにもかかわらず、毎回余分なクエリが走ります。
    
    このエンドポイントは論文ビューページからも呼び出される可能性が高く、ホットパスになりえます。`visibility === 'org_only'` の場合のみ組織を取得するか、編集ページ専用のエンドポイント(例: `GET /api/papers/:id/edit`)を用意することで、パフォーマンスへの影響を最小化できます。
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/web/src/app/papers/[id]/edit/page.tsx
Line: 178-192

Comment:
**`loadingOrgs` ガードは到達不能なコード**

`loadingOrgs``loading` は同じ `finally` ブロックで同時に `false` にセットされます(162行目)。フォームは `loading === false` のときのみ表示されるため、ユーザーがフォームを操作できる状態では `loadingOrgs` は常に `false` です。

この `if (loadingOrgs)` チェックおよびフィールドセット内の「組織情報を読み込み中...」テキストは、実際には表示・実行されることがありません。実質的にデッドコードになっています。

もし組織情報とフォームデータを独立して並行ロードする設計に変更するなら、`loadingOrgs` は引き続き有用ですが、現状の実装(同じ `Promise.all` + `finally`)では不要です。

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/web/src/app/papers/[id]/edit/page.tsx
Line: 208-213

Comment:
**`org_only` 保存時に毎回 `paperOrgs` を全削除・再挿入**

`orgIds` はフォーム保存のたびに常に送信されます(`visibility === "org_only"` の場合)。API 側ではこれを受け取ると、組織の選択が変更されていなくても毎回 `paperOrgs` を DELETE → INSERT で完全に置き換えます(`papers.ts` 1307〜1311行目)。

対象組織を変更しないまま他のフィールド(タイトルなど)のみを更新した場合でも、不必要な DB 書き込みが発生します。フロントエンド側で初期値と現在値を比較して変更があった場合のみ `orgIds` を送信するか、API 側で現在の `paperOrgs` と比較してから更新するアプローチを検討してください。

```suggestion
        orgIds:
          visibility === "org_only"
            ? selectedOrgIds  // 将来的には変更がある場合のみ送信することを検討
            : undefined,
```

または、サブミット時に変更フラグを保持する実装に変更することを推奨します。

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/api/src/routes/papers.ts
Line: 541-578

Comment:
**全論文取得時に組織情報を常に JOIN**

`GET /api/papers/:id` エンドポイントでは、`visibility` に関わらず全論文で `paperOrgs``orgs` の JOIN を常に実行するようになりました。`public``private` の論文では `organizations` は常に空配列になるにもかかわらず、毎回余分なクエリが走ります。

このエンドポイントは論文ビューページからも呼び出される可能性が高く、ホットパスになりえます。`visibility === 'org_only'` の場合のみ組織を取得するか、編集ページ専用のエンドポイント(例: `GET /api/papers/:id/edit`)を用意することで、パフォーマンスへの影響を最小化できます。

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/api/src/routes/papers.ts
Line: 1267-1268

Comment:
**空配列の `orgIds` に対するガード条件が意図通りか確認が必要**

JavaScript では空配列 `[]` は truthy です。そのため `orgIds: []` が送信された場合、`orgIdsFromBody = []` となり `if (orgIdsFromBody && nextVisibility !== "org_only")` の条件は `true` となります。

現状の動作:
- `visibility``org_only` 以外で `orgIds: []` を送信 → 400「orgIds can only be specified...」✓
- `visibility``org_only``orgIds: []` を送信 → 400「orgIds is required...」✓

動作は正しいのですが、`if (orgIdsFromBody !== undefined && ...)` とより明示的に書くと、意図が明確になり後から読む開発者の混乱を避けられます。

```suggestion
    if (orgIdsFromBody !== undefined && nextVisibility !== "org_only") {
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "feat: support full o..."

Greptile also left 2 inline comments on this PR.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
open-shelf Ignored Ignored Mar 22, 2026 4:29pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

バックエンドで paper の可視性検証と orgIds 処理を追加し、GET が org_only の場合に organizations を返すように変更。フロントエンドは編集画面で組織データを並列取得・表示し、フォームで org 選択と送信バリデーションを行う。テスト群を対応して拡張。

Changes

Cohort / File(s) Summary
API: papers ルートとテスト
apps/api/src/routes/papers.ts, apps/api/src/routes/__tests__/papers.test.ts
Visibility 型とガード導入。POST/PATCH で visibility/orgIds の入力検証・正規化・重複除去。GET に organizations を追加(org_only の場合に join)。PATCH は orgIds を元にメンバー確認・paperOrgs の削除/挿入をバッチ処理するよう変更。テストを細分化・追加。
Web: 編集ページとフォーム + テスト
apps/web/src/app/papers/[id]/edit/page.tsx, apps/web/src/app/__tests__/paper-edit-page.test.tsx, apps/web/src/components/papers/edit-form.tsx
編集ページが /api/users/me/orgs を並列取得し organizationsinitialSelectedOrgIdsorgsWarning を管理。PaperEditForm に組織関連 props を追加しチェックボックスで選択管理、org_only 時の送信バリデーションと条件付きで orgIds を含める送信ロジックを実装。テストで orgs モック・PATCH ペイロード検証・エラーケースを追加。
Web: paper-detail クライアントテスト
apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx
ファイルストリームの fetch 失敗を模擬するテストを追加し、エラーログとユーザー向けエラーメッセージの表示を検証。
API: users テスト(微修正)
apps/api/src/routes/__tests__/users.test.ts
テストファイル末尾の空行追加のみ(フォーマット変更)。

Sequence Diagrams

sequenceDiagram
    participant Client as Client
    participant API as API
    participant DB as DB

    Client->>API: GET /api/papers/:id
    activate API
    API->>DB: SELECT paper by id
    activate DB
    DB-->>API: paper
    deactivate DB

    alt paper.visibility == "org_only"
        API->>DB: SELECT organizations via paperOrgs join
        activate DB
        DB-->>API: organizations[]
        deactivate DB
    else
        API->>API: organizations = []
    end

    API-->>Client: { paper, authors, organizations }
    deactivate API
Loading
sequenceDiagram
    participant Client as Client
    participant API as API
    participant DB as DB

    Client->>API: PATCH /api/papers/:id { visibility, orgIds? }
    activate API
    API->>DB: SELECT paper by id
    activate DB
    DB-->>API: existing paper
    deactivate DB

    API->>API: validate nextVisibility, normalize orgIds
    alt nextVisibility == "org_only" && orgIds provided
        API->>DB: COUNT orgMembers WHERE user_id & org_id IN (orgIds)
        activate DB
        DB-->>API: count
        deactivate DB

        alt count != orgIds.length
            API-->>Client: 403 Forbidden
        else
            API->>DB: batch([ UPDATE paper, DELETE paperOrgs, INSERT paperOrgs... ])
            activate DB
            DB-->>API: ok
            deactivate DB
            API-->>Client: 200 OK
        end
    else if nextVisibility != "org_only" && orgIds provided
        API-->>Client: 400 Bad Request
    else
        API->>DB: UPDATE paper (no paperOrgs change)
        API-->>Client: 200 OK
    end
    deactivate API
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #71: 同様のファイル(apps/api/src/routes/papers.ts)と org_only の PATCH ロジックに関する変更が含まれており直接関連。
  • PR #73: papers ルート(GET/PATCH)と関連テストの変更が重複しているためコードレベルで関連。
  • PR #26: visibility/org_only と paperOrgs 周りの実装・テストが類似しており密接に関連。

Suggested labels

size/XXL

Poem

🐇 ぴょんと跳ねてコードを見て、
組織だけの紙にそっと鍵をかけ、
フォームで選んだらサーバーが確認、
バッチで整えて静かに保存、
小さな変更で世界が少し賢くなる。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PRのタイトルは「feat: org_only 公開範囲の完全編集対応」で、変更点の中核である org_only 公開範囲の編集機能完全実装を正確に説明しており、変更セット全体を適切に要約しています。
Description check ✅ Passed PR説明は変更の概要、具体的な変更点、テスト対象ファイルを記載し、変更セット全体に関連した十分な説明が提供されています。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/org-only-edit-complete

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

このプルリクエストは、org_only(組織内限定公開)の公開範囲を持つ論文について、作成から編集まで一貫して正しく扱えるようにするための包括的な機能強化を目的としています。これにより、組織内で共有される論文の管理がより柔軟かつ正確に行えるようになり、ユーザーは公開設定を細かく制御できるようになります。

Highlights

  • APIの変更: org_only公開範囲の論文編集フローに必要な検証と更新処理を強化しました。
  • Webフロントエンドの変更: 論文編集ページでorg_onlyの表示と保存処理を改善しました。
  • テストの追加・更新: APIとフロントエンドの両方でorg_only編集ケースを網羅するテストを追加・更新しました。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai coderabbitai Bot added the size/XL label Mar 20, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

このプルリクエストは、org_only公開範囲の論文の作成から編集までを完全にサポートするための変更を導入しています。API側では、org_only公開範囲の論文の取得時に所属組織情報を含めるようになり、PATCHエンドポイントでは、org_onlyへの変更時にorgIdsの検証と、ユーザーが指定されたすべての組織のメンバーであることの確認が追加されました。フロントエンドでは、論文編集ページでユーザーの所属組織をフェッチし、org_onlyを選択した場合に組織を選択できるUIが追加されています。また、関連するテストも追加・更新されており、新機能が適切に動作することを確認しています。全体的に、この機能はよく実装されており、必要な検証とUIの変更が適切に行われています。

Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
Comment thread apps/api/src/routes/papers.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/routes/papers.ts`:
- Line 1137: body.visibility is a plain string but nextVisibility is typed as
the union "public" | "org_only" | "private"; validate or narrow body.visibility
before assignment (e.g., check it is one of "public", "org_only", "private" and
then assign to nextVisibility), or map/convert the incoming string to the union
and handle invalid values (throw or set a safe default) so the TypeScript type
error is resolved while avoiding an unsafe cast on body.visibility.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 110-117: When orgsRes is not ok, instead of silently calling
setOrganizations([]) update the component to record and surface the error:
capture the failure (use orgsRes.status or await orgsRes.text()) and call a new
state setter (e.g. setOrgsError or setOrganizationsError) alongside
setOrganizations([]), log the response/error, and render a user-facing
notification (toast or inline alert) in the UI so users know org fetch failed;
update the code paths around orgsRes, setOrganizations, and the fetch/useEffect
that calls them to set and display this error state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 655716d7-96e6-46da-afda-cfb3bc1e5071

📥 Commits

Reviewing files that changed from the base of the PR and between ada7793 and 34b0149.

📒 Files selected for processing (4)
  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/api/src/routes/papers.ts
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx
  • apps/web/src/app/papers/[id]/edit/page.tsx

Comment thread apps/api/src/routes/papers.ts
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
is0692vs and others added 2 commits March 20, 2026 15:28
- Fix visibility type narrowing and explicit orgIds guard
- Avoid org JOIN on non-org_only paper detail fetch
- Remove unreachable loadingOrgs logic and surface org fetch warning
- Avoid unchanged orgIds submission from edit form
- Add/adjust API and web tests for updated behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/routes/papers.ts`:
- Around line 1164-1179: Add an explicit max-length check for each org ID before
accepting it into normalizedOrgIds: define a constant (e.g., MAX_ORG_ID_LEN) and
after trimming the orgId in the loop that processes body.orgIds (the block using
normalizedOrgIds, seen, and setting orgIdsFromBody) validate trimmed.length <=
MAX_ORG_ID_LEN, returning c.json({ error: "orgId exceeds maximum length" }, 400)
if it’s too long; perform this check before duplicate-checking/adding to seen so
overly long values are rejected early.
- Around line 1321-1329: The update to papers
(db.update(papers).set(updates).where(eq(papers.id, paperId))) and the
subsequent modifications to paperOrgs (db.delete / db.insert using paperOrgs,
finalOrgIds, paperId) must be executed atomically: wrap the papers update and
the conditional delete/insert logic (the branches using nextVisibility,
hasVisibilityInBody, shouldReplacePaperOrgs) inside a single DB transaction (use
your DB client's transaction API) so any failure rolls back both the papers
change and the paperOrgs changes; ensure you perform the delete when visibility
moves away from "org_only" and the replace insert when shouldReplacePaperOrgs is
true inside that same transaction and propagate/throw errors to trigger
rollback.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 193-204: The current guard for visibility === "org_only" blocks
updates even when the existing paper already has organization IDs; change it so
you only error when the user is trying to switch to org_only or actively change
the org selection: keep the first check but require both organizations.length
=== 0 AND initialSelectedOrgIds.length === 0 before blocking (so existing papers
with initialSelectedOrgIds can proceed), and add a second check that if
selectedOrgIds.length === 0 AND selectedOrgIds differs from
initialSelectedOrgIds then call setError (i.e., block only when the user
cleared/changed selection or there are no orgs available and no initial orgs).
Use the same symbols (visibility, organizations, selectedOrgIds,
initialSelectedOrgIds, setError) to locate and update the conditional logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6f16a2cc-3255-461f-b43b-1bebd78bd32f

📥 Commits

Reviewing files that changed from the base of the PR and between 34b0149 and 3ba3143.

📒 Files selected for processing (8)
  • apps/api/src/middleware/__tests__/auth.test.ts
  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/api/src/routes/__tests__/users.test.ts
  • apps/api/src/routes/papers.ts
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx
  • apps/web/src/app/orgs/[slug]/page.tsx
  • apps/web/src/app/papers/[id]/edit/page.tsx
  • apps/web/src/app/papers/[id]/page.tsx

Comment thread apps/api/src/routes/papers.ts
Comment thread apps/api/src/routes/papers.ts Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 21, 2026

Merge conflicts resolved successfully!

Resolved 2 conflict file(s). Commit: 96359a67aa40f36bf621f2665d0b8aefea52d387 pushed to feat/org-only-edit-complete.

5 file operation(s)
  • apps/api/src/routes/__tests__/papers.test.ts (update)
  • apps/api/src/routes/__tests__/users.test.ts (update)
  • apps/api/src/routes/papers.ts (update)
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx (update)
  • apps/web/src/app/papers/[id]/edit/page.tsx (update)
View agent analysis
I'll start by examining the git state and the conflicting files.

Let me verify the resolution state is correct:

`git ls-files -u` returned empty (no unmerged entries) and both files now show `M` (modified/staged) instead of `UU` (unmerged). The conflicts are resolved.

Let me do a quick behavioral snapshot to confirm the resolved content:

The resolved files look correct. Here's the summary:

## Resolution Summary

### Conflicts Resolved

Both conflicts were caused by trivially different comment annotations between the two branches, with otherwise identical code implementing the same "sanitize at boundary" refactoring:

**`apps/web/src/app/orgs/[slug]/page.tsx`**
- **HEAD** had `// Ensure slug is sanitized before any further processing` comment inside `generateMetadata`
- **MERGE_HEAD (main)** had the same code without that comment
- **Resolution**: Kept main's version (no comment) — cleaner and consistent with the rest of the codebase

**`apps/web/src/app/papers/[id]/page.tsx`**
- **HEAD** had `// Sanitization check` comment
- **MERGE_HEAD (main)** had the same code without it
- **Resolution**: Kept main's version (no comment)

### Behavioral Snapshot

The resolved files correctly implement the "sanitize at boundary" pattern:
- `generateMetadata` receives the raw route param, immediately sanitizes via `safePath()` to `safeSlug`/`safeId`
- The sanitized value is passed to `fetchOrgMetadata(safeSlug)` / `fetchPaperMetadata(safeId)`
- All URL constructions (`openGraph.url`, canonical `url`) use the sanitized value
- No code was introduced from neither side — the resolution is a pure subset of the incoming branch's code

### Status
- `git ls-files -u`: empty (no unmerged paths)
- `git status`: both files show `M` (staged), no `UU` conflicts remain

Resolved conflicts in:
- apps/web/src/app/orgs/[slug]/page.tsx (content)
- apps/web/src/app/papers/[id]/page.tsx (content)

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 21, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 34 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
apps/api/src/routes/papers.ts 85.47% 15 Missing and 2 partials ⚠️
apps/web/src/components/papers/edit-form.tsx 74.28% 4 Missing and 5 partials ⚠️
apps/web/src/app/papers/[id]/edit/page.tsx 77.14% 2 Missing and 6 partials ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
apps/api/src/routes/papers.ts (2)

1159-1179: ⚠️ Potential issue | 🟡 Minor

orgIds の各要素に長さ上限がありません。

Line 1164-1176 では trim と重複排除だけなので、極端に長い ID が membership lookup と paperOrgs 更新候補まで進みます。ここでも org ID の最大長を先に弾いてください。

As per coding guidelines: apps/api/src/routes/**/*.ts: Validate all user-supplied strings with explicit length bounds before database writes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/routes/papers.ts` around lines 1159 - 1179, The orgIds parsing
block (orgIdsFromBody, normalizedOrgIds, seen) currently only trims and dedups
but doesn't enforce a maximum length; add a check after trimming each orgId in
the loop to reject values exceeding a defined max (e.g., MAX_ORG_ID_LENGTH) and
return a 400 JSON error like the other validations; either reuse an existing
MAX_ORG_ID_LENGTH constant or define one near the top of the file (or validation
helpers) and use that constant in the loop to validate trimmed.length before
adding to seen/normalizedOrgIds so overly long IDs never proceed to membership
lookup or paperOrgs updates.

1321-1329: ⚠️ Potential issue | 🟠 Major

paperspaperOrgs の更新がまだ分離しています。

Line 1321 で本体更新が確定した後に Line 1323-1329 の関連組織更新が別 await なので、後段で失敗すると visibilitypaper_orgs が不整合になります。特に org_only への変更途中で insert が失敗すると、論文だけが org_only になり対象組織が欠けた状態が残ります。少なくともこの更新は同じ更新単位でまとめてください。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/routes/papers.ts` around lines 1321 - 1329,
現状、db.update(papers).set(updates).where(eq(papers.id, paperId)) と paperOrgs の
delete/insert(paperOrgs, finalOrgIds, nextVisibility, hasVisibilityInBody,
shouldReplacePaperOrgs)が別々の await
になっており途中失敗で不整合になるため、これらを単一トランザクションにまとめてください。具体的には db.transaction(...)
を使い、トランザクション内で先に db.update(papers).set(updates).where(eq(papers.id, paperId))
を実行し、その後の paperOrgs に対する delete と必要なら insert(finalOrgIds.map(...))
を同じトランザクション(tx.delete/tx.insert)で実行するように変更してください。
apps/web/src/app/papers/[id]/edit/page.tsx (1)

193-204: ⚠️ Potential issue | 🟠 Major

既存の org_only 論文まで保存不能です。

Line 194-197 が organizations.length === 0 だけで止めているため、data.organizations で既存の選択を保持していても、所属組織取得失敗時や脱退後のタイトル更新までブロックされます。PATCH 側は未変更時の orgIds 省略を許容しているので、未変更の組織選択を維持するケースは通してください。

💡 最小修正案
-    if (visibility === "org_only") {
-      if (organizations.length === 0) {
+    if (visibility === "org_only") {
+      const keepingExistingSelection =
+        initialSelectedOrgIds.length > 0 &&
+        areSameOrgSelection(selectedOrgIds, initialSelectedOrgIds);
+
+      if (organizations.length === 0 && !keepingExistingSelection) {
         setError("所属組織がありません。公開範囲を変更してください。");
         return;
       }
-      if (selectedOrgIds.length === 0) {
+      if (
+        selectedOrgIds.length === 0 &&
+        !areSameOrgSelection(selectedOrgIds, initialSelectedOrgIds)
+      ) {
         setError(
           "組織公開にする場合は少なくとも1つの対象組織を選択してください。",
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx around lines 193 - 204, The guard
in the save flow incorrectly blocks saving when visibility === "org_only" solely
because organizations.length === 0, even if the paper already has organizations
in data.organizations or the PATCH can omit unchanged orgIds; update the checks
in the component handling visibility (use the variables visibility,
organizations, selectedOrgIds and data.organizations) so that you only setError
and return when there are no current org selections anywhere (i.e.,
organizations.length === 0 AND (data.organizations is empty or undefined) AND
selectedOrgIds.length === 0); if data.organizations exists (non-empty) allow the
save to proceed and omit orgIds from the PATCH, otherwise enforce selecting at
least one organization and keep the existing error messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/routes/__tests__/users.test.ts`:
- Around line 471-532: These three tests duplicate existing cases in the same
file (same test names and behavior found at lines ~332-395); remove the
duplicate tests or consolidate them into a single table-driven test to avoid
redundant coverage and noisy failures — locate the tests by their titles "GET
/api/users/me returns 404 when user is not found in database", "PATCH
/api/users/me rejects non-object body", and "PATCH /api/users/me rejects
displayName longer than 50 chars" and the helpers
createTestJWT/createTestApp/createTestEnv/mockDb used in them, then either
delete these duplicate blocks or refactor them into a parameterized test that
covers the distinct scenarios once.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 107-131: The Promise.all call currently bundles
apiFetch(`/api/papers/${encodeURIComponent(paperId)}`) and
apiFetch("/api/users/me/orgs") so a rejection from the orgs fetch aborts the
whole operation; separate the org fetch so paper fetch cannot fail due to org
errors—either replace Promise.all with Promise.allSettled and handle orgsRes
outcome separately, or keep the paper fetch in its own await and wrap
apiFetch("/api/users/me/orgs") in a try/catch; on org fetch failure
setOrganizations([]) and setOrgsWarning(...) but still allow the paperRes
handling (the existing paperRes.ok logic and router.replace call) to run
unaffected.

---

Duplicate comments:
In `@apps/api/src/routes/papers.ts`:
- Around line 1159-1179: The orgIds parsing block (orgIdsFromBody,
normalizedOrgIds, seen) currently only trims and dedups but doesn't enforce a
maximum length; add a check after trimming each orgId in the loop to reject
values exceeding a defined max (e.g., MAX_ORG_ID_LENGTH) and return a 400 JSON
error like the other validations; either reuse an existing MAX_ORG_ID_LENGTH
constant or define one near the top of the file (or validation helpers) and use
that constant in the loop to validate trimmed.length before adding to
seen/normalizedOrgIds so overly long IDs never proceed to membership lookup or
paperOrgs updates.
- Around line 1321-1329: 現状、db.update(papers).set(updates).where(eq(papers.id,
paperId)) と paperOrgs の delete/insert(paperOrgs, finalOrgIds, nextVisibility,
hasVisibilityInBody, shouldReplacePaperOrgs)が別々の await
になっており途中失敗で不整合になるため、これらを単一トランザクションにまとめてください。具体的には db.transaction(...)
を使い、トランザクション内で先に db.update(papers).set(updates).where(eq(papers.id, paperId))
を実行し、その後の paperOrgs に対する delete と必要なら insert(finalOrgIds.map(...))
を同じトランザクション(tx.delete/tx.insert)で実行するように変更してください。

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 193-204: The guard in the save flow incorrectly blocks saving when
visibility === "org_only" solely because organizations.length === 0, even if the
paper already has organizations in data.organizations or the PATCH can omit
unchanged orgIds; update the checks in the component handling visibility (use
the variables visibility, organizations, selectedOrgIds and data.organizations)
so that you only setError and return when there are no current org selections
anywhere (i.e., organizations.length === 0 AND (data.organizations is empty or
undefined) AND selectedOrgIds.length === 0); if data.organizations exists
(non-empty) allow the save to proceed and omit orgIds from the PATCH, otherwise
enforce selecting at least one organization and keep the existing error
messages.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 027f94c5-eb31-4770-93af-2dde9979fa95

📥 Commits

Reviewing files that changed from the base of the PR and between 3ba3143 and 96359a6.

📒 Files selected for processing (5)
  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/api/src/routes/__tests__/users.test.ts
  • apps/api/src/routes/papers.ts
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx
  • apps/web/src/app/papers/[id]/edit/page.tsx

Comment thread apps/api/src/routes/__tests__/users.test.ts Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
@is0692vs
Copy link
Copy Markdown
Contributor Author

メンテナ確認済みです。Botコメント(Codecov / CodeRabbit / Gemini / Jules / Greptile / Vercel)を確認し、現時点で追加対応が必要な指摘はありません。必要な追対応が出た場合はこのPRで反映します。

…mplete

# Conflicts:
#	apps/web/src/app/__tests__/paper-edit-page.test.tsx
#	apps/web/src/app/papers/[id]/edit/page.tsx
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 22, 2026

Merging this PR will not alter performance

✅ 12 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing feat/org-only-edit-complete (7c5460a) with main (ea3d50f)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/api/src/routes/__tests__/papers.test.ts (1)

556-621: 🧹 Nitpick | 🔵 Trivial

org_only 解除時の paperOrgs 削除分岐も固定しておきたいです。

今回の追加ケースは「org_only に入る/置き換える」側は押さえていますが、apps/api/src/routes/papers.ts Line 1264-1265 の「org_only から外れるときに paperOrgs を削除する」分岐は未検証です。ここが壊れると private/public に戻した後も組織アクセスが残りうるので、1 本追加しておくと安心です。

🧪 追加したいテストの最小イメージ
+    it("PATCH /api/papers/:id clears paperOrgs when leaving org_only", async () => {
+        // initial visibility: org_only
+        // request: { visibility: "private" }
+        // expect: mockDb.delete called once, mockDb.insert not called
+    });

Also applies to: 821-856

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/routes/__tests__/papers.test.ts` around lines 556 - 621, Add a
test that asserts paperOrgs are removed when changing visibility away from
org_only: mock the initial select to return the paper with visibility "org_only"
and an existing paperOrgs row (e.g., { orgId: "org-1" }), stub mockDb.delete to
return an object with a where() spy (like deleteWhere), then send a PATCH to the
papers endpoint with visibility set to "private" (or "public") and no orgIds;
assert status 200 and that deleteWhere was called once and
mockDb.insert/insertValues was not called. Reference the existing test
scaffolding (the PATCH /api/papers/:id tests, mocks mockDb.select,
mockDb.delete, deleteWhere, mockDb.insert/insertValues) and the papers.ts branch
that removes paperOrgs when leaving "org_only" (the org_only -> non-org_only
deletion branch).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/routes/papers.ts`:
- Around line 1230-1270: The code currently sets shouldReplacePaperOrgs = true
whenever orgIdsFromBody !== undefined, causing DELETE→INSERT even if the
submitted orgIds equal the current ones; instead, query the existing org IDs for
the paper (select orgId from paperOrgs where paperId = paperId), compare that
set to finalOrgIds (treat as sets, ignoring order/duplicates) and only set
shouldReplacePaperOrgs = true when they differ. Update the logic around
orgIdsFromBody/finalOrgIds/shouldReplacePaperOrgs so no DB delete/insert
operations are enqueued when the two sets are identical.
- Around line 1236-1245: The file uses the orgMembers symbol in the memberships
query but it is not imported, causing TypeScript errors; add orgMembers to the
existing schema imports at the top of the file (where other table schemas are
imported) so the query using orgMembers, db.select, and inArray/eq compiles and
the memberships query resolves correctly.

In `@apps/web/src/app/papers/`[id]/__tests__/paper-detail-client.test.tsx:
- Line 464: There is a duplicate spy on console.error: remove the redundant
vi.spyOn(console, "error").mockImplementation(() => {}); in the test at the
later location and rely on the existing spy set up in the beforeEach (or vice
versa), ensuring only one spy setup remains (the one in beforeEach or the one
intended for that specific test) so tests don’t double-mock console.error;
update/keep the single vi.spyOn(console, "error") usage and remove the other to
clarify intent.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 43-50: The code awaits
apiFetch(`/api/papers/${encodeURIComponent(paperId)}`) and then serially awaits
apiFetch("/api/users/me/orgs"), causing an extra RTT; instead fire both requests
in parallel (e.g., start both promises and use Promise.allSettled or
Promise.all) so paper fetch isn't delayed by orgs, keep the existing behavior of
swallowing orgs errors by checking the settled result for the orgs promise and
setting orgsRes to null (and optionally logging a warning) while still using the
paperRes value immediately; locate the promises around paperRes, orgsRes and
apiFetch to implement this change.

---

Outside diff comments:
In `@apps/api/src/routes/__tests__/papers.test.ts`:
- Around line 556-621: Add a test that asserts paperOrgs are removed when
changing visibility away from org_only: mock the initial select to return the
paper with visibility "org_only" and an existing paperOrgs row (e.g., { orgId:
"org-1" }), stub mockDb.delete to return an object with a where() spy (like
deleteWhere), then send a PATCH to the papers endpoint with visibility set to
"private" (or "public") and no orgIds; assert status 200 and that deleteWhere
was called once and mockDb.insert/insertValues was not called. Reference the
existing test scaffolding (the PATCH /api/papers/:id tests, mocks mockDb.select,
mockDb.delete, deleteWhere, mockDb.insert/insertValues) and the papers.ts branch
that removes paperOrgs when leaving "org_only" (the org_only -> non-org_only
deletion branch).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ad58dccb-2e08-4183-9138-b3132ee2055e

📥 Commits

Reviewing files that changed from the base of the PR and between 96359a6 and dd2acf6.

📒 Files selected for processing (7)
  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/api/src/routes/__tests__/users.test.ts
  • apps/api/src/routes/papers.ts
  • apps/web/src/app/__tests__/paper-edit-page.test.tsx
  • apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx
  • apps/web/src/app/papers/[id]/edit/page.tsx
  • apps/web/src/components/papers/edit-form.tsx

Comment thread apps/api/src/routes/papers.ts
Comment thread apps/api/src/routes/papers.ts
Comment thread apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/papers/`[id]/__tests__/paper-detail-client.test.tsx:
- Line 550: Remove the redundant call to fetchSpy.mockRestore() in the test
teardown; the existing afterEach block already calls vi.restoreAllMocks(), so
delete the fetchSpy.mockRestore() invocation (referencing fetchSpy.mockRestore
and the afterEach that calls vi.restoreAllMocks()) to avoid duplicate mock
restoration.
- Around line 463-551: The test overcomplicates failure simulation by spying on
window.fetch; instead modify the apiFetch mock used in this test so when
url.includes("/files/file-image/stream") and method === "GET" it directly
returns a rejected promise or throws an Error to simulate the network failure
(affecting the test's apiFetch mock implementation), remove the window.fetch
spy/fetchSpy usage and its restore, and keep assertions that PaperDetailClient
(rendered with paperId="paper-1") logs the error and shows the "画像の読み込みに失敗しました"
message.

In `@apps/web/src/app/papers/`[id]/edit/page.tsx:
- Around line 88-89: 不要既存の組織メタデータを捨てないでください — 現状 setInitialSelectedOrgIds が
data.organizations を id 配列に変換しているため、PaperEditForm に表示用の name/slug 等が渡っていません。修正は
data.organizations 全体を保持してフォームに渡すようにし、selected IDs は別で生成すること(参照: setPaperData,
setInitialSelectedOrgIds, PaperEditForm,
data.organizations);同様の変更をファイル内の別箇所(該当ブロック 122-129 に相当する処理)にも適用してください。

In `@apps/web/src/components/papers/edit-form.tsx`:
- Around line 136-149: The guard wrongly uses
areSameOrgSelection(selectedOrgIds, initialSelectedOrgIds) directly (which
returns true for [] vs []) allowing an empty selection to pass; change the
conditional to use the previously computed keepingExistingSelection (which
already checks initialSelectedOrgIds.length > 0) in the second check so the
empty-initial case is not treated as preserving selection; update the identical
condition later (the block around methods handling includeOrgIds/visibility) to
use keepingExistingSelection as well and keep using setError, selectedOrgIds,
initialSelectedOrgIds, areSameOrgSelection, and includeOrgIds unchanged
otherwise.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ec186660-90d5-4a68-aa5f-7982e4b58299

📥 Commits

Reviewing files that changed from the base of the PR and between dd2acf6 and 1568d52.

📒 Files selected for processing (5)
  • apps/api/src/routes/__tests__/papers.test.ts
  • apps/api/src/routes/papers.ts
  • apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx
  • apps/web/src/app/papers/[id]/edit/page.tsx
  • apps/web/src/components/papers/edit-form.tsx

Comment thread apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx
Comment thread apps/web/src/app/papers/[id]/__tests__/paper-detail-client.test.tsx Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
Comment thread apps/web/src/components/papers/edit-form.tsx Outdated
Copy link
Copy Markdown
Contributor Author

@is0692vs is0692vs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed remaining review feedback in commit 7c5460a.

Comment thread apps/api/src/routes/__tests__/papers.test.ts
Comment thread apps/api/src/routes/papers.ts
Comment thread apps/api/src/routes/papers.ts
Comment thread apps/api/src/routes/papers.ts Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
Comment thread apps/api/src/routes/__tests__/users.test.ts Outdated
Comment thread apps/web/src/app/papers/[id]/edit/page.tsx Outdated
@is0692vs is0692vs merged commit 195c74f into main Mar 22, 2026
23 checks passed
@is0692vs is0692vs deleted the feat/org-only-edit-complete branch March 22, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant