# 画面設計書 18-アクティビティ

## 概要

本ドキュメントは、GitLabダッシュボードのアクティビティ画面（Dashboard Activity）の画面設計を定義したものである。

### 本画面の処理概要

ログインユーザーに関連するアクティビティ（イベント）のフィードを表示するダッシュボード画面である。

**業務上の目的・背景**：GitLabでは、プロジェクトへのコミット、マージリクエストの作成、課題の更新など、様々なアクティビティが発生する。本画面は、ユーザー自身のアクティビティ、参加プロジェクトのアクティビティ、スター付きプロジェクトのアクティビティ、フォロー中ユーザーのアクティビティをフィルタリングして一元的に確認できる。チームの作業状況把握やコラボレーションの促進に活用される。

**画面へのアクセス方法**：ログイン後、サイドバーまたはナビゲーションから「Activity」メニューを選択。直接URLアクセスの場合は `/dashboard/activity` へアクセスする。

**主要な操作・処理内容**：
1. アクティビティフィードの表示
2. フィルタによるイベント絞り込み（Your Projects、Starred、Followed）
3. イベントタイプによるフィルタリング（Push、MR、Issue等）
4. ATOMフィード購読のためのURL取得
5. 各イベントの詳細画面への遷移

**画面遷移**：
- 遷移元：ログイン画面、サイドバー、ナビゲーション
- 遷移先：プロジェクト詳細画面、マージリクエスト詳細画面、課題詳細画面、コミット詳細画面

**権限による表示制御**：ログインユーザーのみアクセス可能。表示されるアクティビティはユーザーがアクセス権限を持つプロジェクト・グループに関連するもののみ。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 124 | Todoリスト | 関連機能 | アクティビティからTo-Do関連イベント表示 |

## 画面種別

一覧

## URL/ルーティング

| URL | HTTPメソッド | 説明 |
|-----|-------------|------|
| `/dashboard/activity` | GET | アクティビティ画面（HTML） |
| `/dashboard/activity.json` | GET | アクティビティ画面（JSON API） |

## 入出力項目

### 入力項目（フィルタ）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| filter | string | No | ソースフィルタ（your_projects, projects, starred, followed） |
| event_filter | string | No | イベントタイプフィルタ |
| offset | integer | No | オフセット |
| limit | integer | No | 取得件数 |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @events | Array | イベント一覧 |

## 表示項目

### アクティビティ一覧

| 項目名 | 説明 | 備考 |
|--------|------|------|
| アクター | イベントを発生させたユーザー | アバター表示 |
| アクション | 実行されたアクション（pushed, created, merged等） | アイコン表示 |
| 対象 | アクションの対象（プロジェクト、MR、課題等） | リンク |
| プロジェクト | イベントが発生したプロジェクト | リンク |
| 日時 | イベント発生日時 | 相対時間表示 |
| 詳細 | コミットメッセージ、コメント内容等 | 部分表示 |

## イベント仕様

### 1-アクティビティフィードの読み込み

ページ読み込み時またはJSON形式でアクティビティフィードを取得する。

**処理フロー**：
1. event_filterの適用
2. フィルタパラメータに基づくイベントソースの決定
3. UserRecentEventsFinderまたはEventCollectionによるイベント取得
4. Events::RenderServiceによるイベントレンダリング

### 2-フィルタ変更

フィルタ（Your Projects、Starred、Followed）を切り替えると、対応するイベントソースからアクティビティが取得される。

**フィルタ種類**：
- your_projects / projects: 参加プロジェクトのイベント
- starred: スター付きプロジェクトのイベント
- followed: フォロー中ユーザーのイベント
- デフォルト: 自分自身のイベント

### 3-JSONによる追加読み込み

スクロール等でJSON形式のアクティビティを追加取得し、ページャーで表示する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | events | SELECT | フィルタ条件に合致するイベントを取得 |
| ページ表示 | projects | SELECT | ユーザーのプロジェクト取得 |
| ページ表示 | push_event_payloads | SELECT | プッシュイベントの詳細情報取得 |

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

#### events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, action, author_id, target_id, target_type, project_id, group_id, created_at | フィルタ条件による | UserRecentEventsFinder/EventCollection経由 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | 情報 | "No activities found" | アクティビティが存在しない場合 |

## 例外処理

| 例外条件 | 処理内容 | 表示メッセージ |
|----------|----------|---------------|
| 未ログイン | ログイン画面へリダイレクト | - |

## 備考

- サーバーサイドレンダリング + JSON APIによるハイブリッド実装
- ATOMフィード対応（auto_discovery_link_tag）
- EventFilter concernによるイベントタイプフィルタリング
- global_time_tracking_reportフィーチャーフラグ対応
- Events::RenderServiceでイベントのレンダリング前処理
- pager_jsonによるページネーション

---

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

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

### 推奨読解順序

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

まず、イベントのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.rb | `app/models/event.rb` | Eventモデルの定義、ACTIONS定数 |
| 1-2 | event_collection.rb | `app/models/event_collection.rb` | イベントコレクションの構築 |
| 1-3 | user_recent_events_finder.rb | `app/finders/user_recent_events_finder.rb` | ユーザーイベント検索ロジック |

**読解のコツ**: EventはACTIONS（created, updated, pushed, merged等）とTARGET_TYPES（issue, merge_request等）を持つポリモーフィックな関連を含む。

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

処理の起点となるコントローラを特定する。

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

**主要処理フロー**:
1. **Line 12**: `before_action :event_filter`でイベントフィルタを適用
2. **Line 47-55**: activityアクションでHTML/JSON形式を分岐
3. **Line 64-76**: load_eventsメソッドでフィルタに基づくイベント取得
4. **Line 75**: Events::RenderServiceでイベントをレンダリング可能に

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | activity.html.haml | `app/views/dashboard/activity.html.haml` | HAMLテンプレート |

**主要処理フロー**:
- **Line 1-2**: ATOMフィードのmeta tag設定
- **Line 7**: ページタイトル設定
- **Line 11**: last_pushパーシャルのレンダリング
- **Line 12**: activity_headパーシャル（フィルタUI）
- **Line 14-15**: アクティビティ一覧表示

#### Step 4: イベント取得ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | user_recent_events_finder.rb | `app/finders/user_recent_events_finder.rb` | ユーザーベースのイベント取得 |
| 4-2 | event_collection.rb | `app/models/event_collection.rb` | プロジェクトベースのイベント取得 |

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

```
DashboardController#activity
    |
    +-- event_filter (before_action)
    |
    +-- respond_to
    |       |
    |       +-- format.html (render)
    |       |
    |       +-- format.json
    |               |
    |               +-- load_events
    |                       |
    |                       +-- [filter == your_projects/projects/starred]
    |                       |       |
    |                       |       +-- load_project_events
    |                       |               |
    |                       |               +-- ProjectsFinder (starred)
    |                       |               |       or
    |                       |               +-- current_user.authorized_projects
    |                       |               |
    |                       |               +-- EventCollection.new.to_a
    |                       |
    |                       +-- [filter == followed]
    |                       |       |
    |                       |       +-- load_user_events(current_user.followees)
    |                       |               |
    |                       |               +-- UserRecentEventsFinder.new.execute
    |                       |
    |                       +-- [default]
    |                               |
    |                               +-- load_user_events(current_user)
    |                                       |
    |                                       +-- UserRecentEventsFinder.new.execute
    |
    +-- Events::RenderService.new.execute(@events)
    |
    +-- pager_json('events/_events', count)
```

### データフロー図

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

URLパラメータ ───▶ DashboardController#activity ───▶ HTML/JSONレスポンス
(filter,                  |
 event_filter)            |
                          v
                   UserRecentEventsFinder
                          or
                   EventCollection
                          |
                          v
                   Event (Model)
                          |
                          v
                   PostgreSQL
                          |
                          v
                   Events::RenderService
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dashboard_controller.rb | `app/controllers/dashboard_controller.rb` | コントローラ | リクエスト処理 |
| activity.html.haml | `app/views/dashboard/activity.html.haml` | ビュー | 画面テンプレート |
| _activity_head.html.haml | `app/views/dashboard/_activity_head.html.haml` | パーシャル | フィルタUI |
| _activities.html.haml | `app/views/dashboard/_activities.html.haml` | パーシャル | アクティビティリスト |
| event.rb | `app/models/event.rb` | モデル | イベントデータ定義 |
| event_collection.rb | `app/models/event_collection.rb` | モデル | イベントコレクション |
| user_recent_events_finder.rb | `app/finders/user_recent_events_finder.rb` | ファインダー | ユーザーイベント検索 |
| dashboard.rb | `config/routes/dashboard.rb` | ルート | URL定義 |
