Skip to content

Activity API endpoint#77

Merged
travisdock merged 4 commits intomainfrom
api-endpoints
Jan 31, 2026
Merged

Activity API endpoint#77
travisdock merged 4 commits intomainfrom
api-endpoints

Conversation

@travisdock
Copy link
Owner

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a comprehensive Activity API endpoint that allows querying activity data across all models (todos, projects, milestones, events, thoughts, resources, journal entries) for any time period. The endpoint is designed specifically for AI agents to summarize productivity.

Changes:

  • Adds ActivityService with support for named periods (this_week, last_month, etc.) and custom date ranges
  • Adds new API endpoint GET /api/v1/activity with filtering, period selection, and summary statistics
  • Updates API documentation with detailed examples and usage patterns, including URL updates from placeholder domains to today.travserve.net

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
app/services/activity_service.rb New service implementing activity aggregation logic with period validation, date range handling, and data formatting across all entity types
app/controllers/api/v1/activity_controller.rb New controller exposing the activity endpoint with proper authentication (read scope required) and error handling
app/models/todo.rb Adds created_in_range and completed_in_range scopes for date-based filtering
app/models/project.rb Adds created_in_range, completed_in_range, and updated_in_range scopes
app/models/milestone.rb Adds created_in_range and completed_in_range scopes
app/models/thought.rb Adds created_in_range scope
app/models/resource.rb Adds created_in_range scope
app/models/journal_entry.rb Adds created_in_range scope
test/services/activity_service_test.rb Comprehensive service tests covering period validation, date range validation, data filtering, cross-references, and edge cases
test/controllers/api/v1/activity_controller_test.rb Controller tests verifying authentication, authorization, parameter handling, response structure, and data filtering
docs/API.md Extensive documentation of the new endpoint with examples, parameter descriptions, and response format; also updates example URLs throughout
config/routes.rb Adds the new activity route to the v1 API namespace

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

raise InvalidDateRangeError, "start_date is required for custom date range" if custom_start.blank?
raise InvalidDateRangeError, "end_date is required for custom date range" if custom_end.blank?

if (date_range.end.to_date - date_range.begin.to_date).to_i > MAX_RANGE_DAYS
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

The validation doesn't check if end_date is before start_date. When end_date is before start_date, the date range calculation will succeed but produce an invalid range (where range.end < range.begin). This could lead to unexpected behavior when querying the database, as the WHERE clause would search for records where created_at is in a backwards range. Consider adding explicit validation to ensure start_date is before or equal to end_date.

Suggested change
if (date_range.end.to_date - date_range.begin.to_date).to_i > MAX_RANGE_DAYS
start_time = parse_date(custom_start)
end_time = parse_date(custom_end)
if end_time < start_time
raise InvalidDateRangeError, "end_date cannot be before start_date"
end
if (end_time.to_date - start_time.to_date).to_i > MAX_RANGE_DAYS

Copilot uses AI. Check for mistakes.

scope :created_in_range, ->(range) { where(created_at: range) }
scope :completed_in_range, ->(range) { where(completed_at: range) }
scope :updated_in_range, ->(range) { where(updated_at: range) }
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

The updated_in_range scope is defined but not used anywhere in the codebase. This scope is not referenced in ActivityService or any other controller/service. Consider removing it to keep the codebase clean, or if it's intended for future use, consider adding it when it's actually needed.

Suggested change
scope :updated_in_range, ->(range) { where(updated_at: range) }

Copilot uses AI. Check for mistakes.

test "returns todos created in range" do
# Create a todo within this week
todo = @user.todos.create!(
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to todo is useless, since its value is never read.

Suggested change
todo = @user.todos.create!(
@user.todos.create!(

Copilot uses AI. Check for mistakes.
end

test "returns projects created in range" do
project = @user.projects.create!(
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to project is useless, since its value is never read.

Suggested change
project = @user.projects.create!(
@user.projects.create!(

Copilot uses AI. Check for mistakes.

test "returns milestones created in range" do
project = projects(:one)
milestone = project.milestones.create!(
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to milestone is useless, since its value is never read.

Suggested change
milestone = project.milestones.create!(
project.milestones.create!(

Copilot uses AI. Check for mistakes.

test "returns thoughts created in range" do
project = projects(:one)
thought = project.thoughts.create!(content: "Test thought")
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to thought is useless, since its value is never read.

Copilot uses AI. Check for mistakes.

test "thought includes project cross-reference" do
project = projects(:one)
thought = project.thoughts.create!(content: "Test thought")
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to thought is useless, since its value is never read.

Suggested change
thought = project.thoughts.create!(content: "Test thought")
project.thoughts.create!(content: "Test thought")

Copilot uses AI. Check for mistakes.

test "returns resources created in range" do
project = projects(:one)
resource = project.resources.create!(url: "https://example.com")
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to resource is useless, since its value is never read.

Suggested change
resource = project.resources.create!(url: "https://example.com")
project.resources.create!(url: "https://example.com")

Copilot uses AI. Check for mistakes.

test "returns journal entries created in range" do
project = projects(:one)
entry = project.journal_entries.create!(content: "Test journal entry")
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to entry is useless, since its value is never read.

Suggested change
entry = project.journal_entries.create!(content: "Test journal entry")
project.journal_entries.create!(content: "Test journal entry")

Copilot uses AI. Check for mistakes.

test "excludes other users data" do
other_user = users(:two)
other_todo = other_user.todos.create!(
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This assignment to other_todo is useless, since its value is never read.

Suggested change
other_todo = other_user.todos.create!(
other_user.todos.create!(

Copilot uses AI. Check for mistakes.
@travisdock travisdock merged commit a92ef09 into main Jan 31, 2026
5 checks passed
@travisdock travisdock deleted the api-endpoints branch January 31, 2026 22:00
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