Implement: US #29 - Shared EPUB Upload and Section Splitting #35

Closed
marko wants to merge 1 commits from feature/us29-group-epub-upload-sections into main
Owner

Overview

Implements the full Group EPUB Upload and Section Splitting feature (US #29).

Backend (Django)

  • New groups app with models: ReadingGroup, GroupBook, Section, ReadingSchedule, MemberProgress
  • EPUB section splitting service (section_splitting.py):
    • Auto-detects sections from TOC structure or groups chapters into chunks
    • Estimates reading time per section (250 words/min)
    • Section recommendation engine for 4-week meeting schedules
  • REST API:
    • GET/POST /api/groups/ - List/create reading groups
    • GET/DELETE /api/groups/:id/ - Group detail
    • POST /api/groups/:id/add_member/ and remove_member/ - Member management
    • GET/POST /api/groups/:id/books/ - List/upload group books
    • POST .../books/:id/detect-sections/ - Auto-detect sections
    • POST .../books/:id/adjust-sections/ - Manual merge/split
    • GET/POST/DELETE .../books/:id/schedule/ - Reading schedule
    • GET/PATCH .../books/:id/progress/ - Member progress

Frontend (React/TypeScript)

  • GroupsPage (/groups) - Create and list reading groups
  • GroupDetailPage (/groups/:id) - Manage members, select and upload EPUB from personal library
  • GroupBookPage (/groups/:id/books/:id) - Three-tab view:
    • Sections: Auto-detect, merge (click to select), split with configurable count
    • Schedule: Generate 4-week reading plan with meeting breakdowns
    • Progress: Per-member progress bars with section tracking
  • API client (groupsApi), TypeScript types, i18n (en/es)

Files changed: 23 files, 2492 insertions

Closes #29

## Overview Implements the full Group EPUB Upload and Section Splitting feature (US #29). ### Backend (Django) - **New `groups` app** with models: ReadingGroup, GroupBook, Section, ReadingSchedule, MemberProgress - **EPUB section splitting service** (`section_splitting.py`): - Auto-detects sections from TOC structure or groups chapters into chunks - Estimates reading time per section (250 words/min) - Section recommendation engine for 4-week meeting schedules - **REST API**: - `GET/POST /api/groups/` - List/create reading groups - `GET/DELETE /api/groups/:id/` - Group detail - `POST /api/groups/:id/add_member/` and `remove_member/` - Member management - `GET/POST /api/groups/:id/books/` - List/upload group books - `POST .../books/:id/detect-sections/` - Auto-detect sections - `POST .../books/:id/adjust-sections/` - Manual merge/split - `GET/POST/DELETE .../books/:id/schedule/` - Reading schedule - `GET/PATCH .../books/:id/progress/` - Member progress ### Frontend (React/TypeScript) - **GroupsPage** (`/groups`) - Create and list reading groups - **GroupDetailPage** (`/groups/:id`) - Manage members, select and upload EPUB from personal library - **GroupBookPage** (`/groups/:id/books/:id`) - Three-tab view: - Sections: Auto-detect, merge (click to select), split with configurable count - Schedule: Generate 4-week reading plan with meeting breakdowns - Progress: Per-member progress bars with section tracking - API client (`groupsApi`), TypeScript types, i18n (en/es) ### Files changed: 23 files, 2492 insertions Closes #29
marko added 1 commit 2026-06-20 19:31:29 +00:00
Backend:
- Create hermes Django app with models: ReadingGroup, GroupBook, Section, ReadingSchedule, MemberProgress
- EPUB section splitting service with automatic detection and reading time estimation
- Section recommendation engine for 4-week meeting schedule
- REST API endpoints for groups, books, sections, schedule, and member progress
- Manual section adjustment (merge/split) support

Frontend:
- GroupsPage: list/create reading groups
- GroupDetailPage: manage members, upload EPUB to group, view group books
- GroupBookPage: section breakdown with merge/split controls, reading schedule, member progress
- API client and TypeScript types for all group operations
- i18n keys for English and Spanish

Shared:
- Group-related types and API endpoint constants in packages/shared
Owner

Test comment

Test comment
Owner

Reid's Review — PR #35

Verdict: 🔴 Changes Required


🔴 Blocking Issues

These MUST be resolved before this PR can be merged.

  • [File: backend/apps/groups/views.py | Line ~942] missing type hints
    The IsGroupAdmin.has_permission and IsGroupAdmin.has_object_permission methods use object as the type hint for the view parameter. This should be typed properly per the project's Python 3.10+ type hints standard.

  • [File: backend/apps/groups/views.py | Line ~1218] missing permission flexibility for progress endpoint
    The GroupBookViewSet has permission_classes = [permissions.IsAuthenticated, IsGroupAdmin] which means only group admins can access the progress endpoint. However, according to AC #6, "when I have confirmed the section recommendations, then all group members should be able to see the reading schedule with target sections per meeting." Members should be able to view and update their own progress, but the current permission class blocks them.

  • [File: frontend/src/pages/GroupBookPage.tsx | Throughout] inline styles
    Multiple React components use inline styles extensively. Per project standards, inline styles are not allowed. Must use CSS modules, styled-components, or a consistent styling solution.

  • [File: frontend/src/pages/GroupDetailPage.tsx | Throughout] inline styles
    Same inline styles issue as above. All React components have extensive inline styling.

  • [File: frontend/src/pages/GroupsPage.tsx | Throughout] inline styles
    Same inline styles issue. The entire component uses inline styles.

  • [File: backend/apps/groups/views.py | Lines ~1115-1191] business logic in views
    The adjust_sections action contains significant business logic for merging and splitting sections. Per Django review criteria, business logic should live in the service layer (section_splitting.py) rather than in views.


🟡 Suggestions (Non-Blocking)

These are recommendations for improvement.

  • [File: backend/apps/groups/services/section_splitting.py] Add docstrings to the _fetch_chapter_text and _estimate_reading_minutes helper functions.

  • [File: frontend/src/api/groups.ts | Line ~1318] The listGroups API returns either a paginated response or an array; consider adding explicit type guard handling.

  • [File: backend/apps/groups/models.py | Line ~337] Consider adding a db_index to estimated_reading_minutes field.

  • [File: backend/apps/groups/views.py | Line ~1242] The _renumber_sections function makes N individual queries for each section. Consider using bulk_update for efficiency.


📋 AC Coverage

Based on linked issue #29

  • Given I am a group admin, When I navigate to the group book section, Then I should see an option to upload an EPUB file.
  • Given I have selected an EPUB file to upload, When I confirm the upload, Then the system should parse the EPUB and identify chapter/section boundaries.
  • Given the EPUB has been parsed, When I view the section breakdown, Then I should see a list of detected sections with titles and estimated reading time for each.
  • Given I am viewing the section breakdown, When I choose to adjust section boundaries, Then I should be able to merge or split sections manually.
  • Given the EPUB has been split into sections, When I request section recommendations for meetings, Then the system should suggest which sections to assign to each weekly meeting.
  • Given I have confirmed the section recommendations, When I finalize the group book schedule, Then all group members should be able to see the reading schedule. (BLOCKING: Permission issue)
  • Given I am a group admin, When I want to replace the current book, Then I should be able to upload a new EPUB and restart the section splitting process without losing group membership.
## Reid's Review — PR #35 **Verdict:** 🔴 Changes Required --- ### 🔴 Blocking Issues > These MUST be resolved before this PR can be merged. - **[File: backend/apps/groups/views.py | Line ~942]** `missing type hints` The `IsGroupAdmin.has_permission` and `IsGroupAdmin.has_object_permission` methods use `object` as the type hint for the `view` parameter. This should be typed properly per the project's Python 3.10+ type hints standard. - **[File: backend/apps/groups/views.py | Line ~1218]** `missing permission flexibility for progress endpoint` The `GroupBookViewSet` has `permission_classes = [permissions.IsAuthenticated, IsGroupAdmin]` which means only group admins can access the progress endpoint. However, according to AC #6, "when I have confirmed the section recommendations, then all group members should be able to see the reading schedule with target sections per meeting." Members should be able to view and update their own progress, but the current permission class blocks them. - **[File: frontend/src/pages/GroupBookPage.tsx | Throughout]** `inline styles` Multiple React components use inline styles extensively. Per project standards, inline styles are not allowed. Must use CSS modules, styled-components, or a consistent styling solution. - **[File: frontend/src/pages/GroupDetailPage.tsx | Throughout]** `inline styles` Same inline styles issue as above. All React components have extensive inline styling. - **[File: frontend/src/pages/GroupsPage.tsx | Throughout]** `inline styles` Same inline styles issue. The entire component uses inline styles. - **[File: backend/apps/groups/views.py | Lines ~1115-1191]** `business logic in views` The `adjust_sections` action contains significant business logic for merging and splitting sections. Per Django review criteria, business logic should live in the service layer (`section_splitting.py`) rather than in views. --- ### 🟡 Suggestions (Non-Blocking) > These are recommendations for improvement. - **[File: backend/apps/groups/services/section_splitting.py]** Add docstrings to the `_fetch_chapter_text` and `_estimate_reading_minutes` helper functions. - **[File: frontend/src/api/groups.ts | Line ~1318]** The `listGroups` API returns either a paginated response or an array; consider adding explicit type guard handling. - **[File: backend/apps/groups/models.py | Line ~337]** Consider adding a `db_index` to `estimated_reading_minutes` field. - **[File: backend/apps/groups/views.py | Line ~1242]** The `_renumber_sections` function makes N individual queries for each section. Consider using `bulk_update` for efficiency. --- ### 📋 AC Coverage > Based on linked issue #29 - [x] Given I am a group admin, When I navigate to the group book section, Then I should see an option to upload an EPUB file. - [x] Given I have selected an EPUB file to upload, When I confirm the upload, Then the system should parse the EPUB and identify chapter/section boundaries. - [x] Given the EPUB has been parsed, When I view the section breakdown, Then I should see a list of detected sections with titles and estimated reading time for each. - [x] Given I am viewing the section breakdown, When I choose to adjust section boundaries, Then I should be able to merge or split sections manually. - [x] Given the EPUB has been split into sections, When I request section recommendations for meetings, Then the system should suggest which sections to assign to each weekly meeting. - [ ] Given I have confirmed the section recommendations, When I finalize the group book schedule, Then all group members should be able to see the reading schedule. (BLOCKING: Permission issue) - [x] Given I am a group admin, When I want to replace the current book, Then I should be able to upload a new EPUB and restart the section splitting process without losing group membership.
max closed this pull request 2026-07-21 22:15:54 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No labels
2 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: HermesFactory/cloud-reader#35