# 画面設計書 186-組織グループ・プロジェクト

## 概要

本ドキュメントは、GitLabの組織内グループ・プロジェクト一覧画面の設計を記述したものである。

### 本画面の処理概要

**業務上の目的・背景**：組織には複数のグループとプロジェクトが所属する。この画面は組織内のリソースを一元的に管理・閲覧するためのものであり、グループとプロジェクトを切り替えて表示できる。検索、ソート、フィルタリング機能により、大規模な組織でも目的のリソースを効率的に見つけることができる。

**画面へのアクセス方法**：組織詳細画面（184-組織詳細）のグループ・プロジェクト統計カードをクリック、または直接URL `/-/organizations/:organization_path/groups_and_projects` にアクセスする。

**主要な操作・処理内容**：
1. グループ一覧の表示（デフォルト）
2. プロジェクト一覧への切り替え
3. 名前による検索（3文字以上）
4. 各種ソート条件での並び替え
5. 新規グループの作成
6. 新規プロジェクトの作成

**画面遷移**：
- 遷移元：組織詳細画面（184-組織詳細）、サイドナビゲーション
- 遷移先：グループ詳細画面、プロジェクト詳細画面、新規グループ作成画面（190）

**権限による表示制御**：
- `read_organization` 権限を持つユーザーが閲覧可能
- 公開組織の場合、未ログインユーザーも閲覧可能
- 「New group」ボタンは `create_group` 権限を持つユーザーのみに表示
- 「New project」ボタンは `can_create_project?` がtrueのユーザーのみに表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 134 | 組織管理 | 主機能 | 組織配下のグループ・プロジェクト表示 |

## 画面種別

一覧

## URL/ルーティング

- パス: `/-/organizations/:organization_path/groups_and_projects`
- クエリパラメータ: `display` (groups/projects)、`sort_name`、`sort_direction`、`search`
- HTTPメソッド: GET
- コントローラー: `Organizations::OrganizationsController#groups_and_projects`

## 入出力項目

| 項目名 | 項目ID | データ型 | 必須 | 入力形式 | 説明 |
|--------|--------|----------|------|----------|------|
| 表示タイプ | display | String | No | セレクト | groups/projects |
| 検索文字列 | search | String | No | テキスト | 3文字以上で検索実行 |
| ソート項目 | sort_name | String | No | セレクト | name/created_at等 |
| ソート方向 | sort_direction | String | No | セレクト | asc/desc |
| ページカーソル | start_cursor/end_cursor | String | No | クエリパラメータ | ページネーション用 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ページタイトル | 見出し | "Groups and projects" |
| 新規グループボタン | ボタン | "New group"（権限がある場合） |
| 新規プロジェクトボタン | ボタン | "New project"（権限がある場合） |
| 表示切替 | ドロップダウン | Groups/Projectsの切り替え |
| 検索フィールド | テキスト入力 | 名前検索 |
| ソートオプション | ドロップダウン | 並び替え条件選択 |
| リソース一覧 | リスト | グループまたはプロジェクトの一覧 |
| ページネーション | ナビゲーション | 前/次ページ |

## イベント仕様

### 1-表示タイプ切り替え

1. Groups/Projectsを選択
2. URLクエリパラメータ `display` を更新
3. ユーザー設定（user_preference）に保存
4. 対応するリソース一覧を表示

### 2-検索実行

1. 検索文字列を入力（3文字以上で実行）
2. URLクエリパラメータ `search` を更新
3. フィルタリングされた結果を表示

### 3-ソート変更

1. ソート項目または方向を選択
2. URLクエリパラメータを更新
3. ユーザー設定に保存
4. ソート適用された結果を表示

### 4-新規グループ作成ボタン押下

1. 組織グループ新規作成画面（190-グループ新規作成）へ遷移

### 5-新規プロジェクト作成ボタン押下

1. プロジェクト新規作成画面へ遷移

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | groups | SELECT | グループ一覧の取得 |
| 画面表示 | projects | SELECT | プロジェクト一覧の取得 |
| 表示設定変更 | user_preferences | UPDATE | 表示設定の保存 |
| ソート設定変更 | user_preferences | UPDATE | ソート設定の保存 |

### テーブル別更新項目詳細

#### user_preferences

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | organization_groups_projects_display | GROUPS/PROJECTS | 表示タイプ |
| UPDATE | organization_groups_projects_sort | ソート設定値 | 例: NAME_ASC |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| なし | - | - | 特別なメッセージはない（空状態時のみ表示） |

## 例外処理

| 例外パターン | 処理内容 |
|-------------|----------|
| 権限不足 | アクセス拒否（403） |
| データ取得エラー | アラートでエラーメッセージを表示 |
| ユーザー設定更新エラー | Sentryにログを送信し、サイレント失敗 |

## 備考

- 検索は3文字未満の場合は実行されない（API要件）
- ユーザー設定の更新はバックグラウンドで行われ、失敗してもユーザーに通知しない
- ソート設定はGraphQL enumとして定義されている（`SORT_ITEMS_GRAPHQL_ENUMS`）
- Vue Routerを使用してURLとの同期を維持

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.js | `app/assets/javascripts/organizations/groups_and_projects/constants.js` | 表示タイプ、ソートオプションの定義 |

**読解のコツ**: `DISPLAY_LISTBOX_ITEMS` と `SORT_ITEMS` の構造を確認すること。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | organizations_controller.rb | `app/controllers/organizations/organizations_controller.rb` | groups_and_projectsアクション |

**主要処理フロー**:
1. **行14**: `before_action :authorize_read_organization!` - 権限チェック
2. **行19**: `skip_before_action :authenticate_user!` - 認証スキップ
3. **行50**: `def groups_and_projects; end` - 空のアクション

#### Step 3: ヘルパーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | organization_helper.rb | `app/helpers/organizations/organization_helper.rb` | organization_groups_and_projects_app_data |

**主要処理フロー**:
- **行36-41**: `organization_groups_and_projects_app_data` - Vue用データ準備

#### Step 4: フロントエンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | groups_and_projects.html.haml | `app/views/organizations/organizations/groups_and_projects.html.haml` | マウントポイント |
| 4-2 | app.vue | `app/assets/javascripts/organizations/groups_and_projects/components/app.vue` | メインコンポーネント |
| 4-3 | groups_view.vue | `app/assets/javascripts/organizations/shared/components/groups_view.vue` | グループ一覧表示 |
| 4-4 | projects_view.vue | `app/assets/javascripts/organizations/shared/components/projects_view.vue` | プロジェクト一覧表示 |

**主要処理フロー**:
- **行59-69**: `routerView` - 表示コンポーネントの動的切り替え
- **行132-137**: `onDisplayListboxSelect` - 表示タイプ変更処理
- **行175-200**: `userPreferencesUpdateMutate` - ユーザー設定の保存

### プログラム呼び出し階層図

```
groups_and_projects.html.haml
    │
    └─ #js-organizations-groups-and-projects (Vue mount point)
           │
           └─ GroupsAndProjectsApp (app.vue)
                  │
                  ├─ FilteredSearchAndSort
                  │      ├─ 表示切替ドロップダウン
                  │      ├─ 検索フィールド
                  │      └─ ソートオプション
                  │
                  ├─ NewGroupButton (権限がある場合)
                  │
                  ├─ NewProjectButton (権限がある場合)
                  │
                  └─ routerView (動的コンポーネント)
                         ├─ GroupsView (display=groups)
                         │      └─ GraphQL Query
                         │
                         └─ ProjectsView (display=projects)
                                └─ GraphQL Query
```

### データフロー図

```
[入力]                    [処理]                           [出力]

URLアクセス ───▶ OrganizationsController#groups_and_projects
                      │
                      └─ organization_groups_and_projects_app_data
                              │
                              └─▶ Vue.js App
                                      │
                                      ├─ URL Query解析
                                      │      └─ display, sort, search
                                      │
                                      ├─ GraphQL Query
                                      │      └─ groups or projects
                                      │
                                      └─▶ リソース一覧表示

設定変更 ────────▶ GraphQL Mutation: userPreferencesUpdate
                      │
                      └─▶ user_preferences更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| organizations_controller.rb | `app/controllers/organizations/organizations_controller.rb` | コントローラー | リクエスト処理 |
| groups_and_projects.html.haml | `app/views/organizations/organizations/groups_and_projects.html.haml` | ビュー | マウントポイント |
| app.vue | `app/assets/javascripts/organizations/groups_and_projects/components/app.vue` | Vue | メインコンポーネント |
| groups_view.vue | `app/assets/javascripts/organizations/shared/components/groups_view.vue` | Vue | グループ一覧 |
| projects_view.vue | `app/assets/javascripts/organizations/shared/components/projects_view.vue` | Vue | プロジェクト一覧 |
| constants.js | `app/assets/javascripts/organizations/groups_and_projects/constants.js` | 定数 | 設定値 |
| organization_helper.rb | `app/helpers/organizations/organization_helper.rb` | ヘルパー | app_data生成 |
