From 3742942f0ef076889a3566649934269f692e88e4 Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 14 Jul 2025 11:07:21 -0400 Subject: [PATCH] goated projects api --- app/controllers/api/v1/stats_controller.rb | 86 +++++++++++++++++++--- config/routes.rb | 1 + 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/v1/stats_controller.rb b/app/controllers/api/v1/stats_controller.rb index ff77f60..026f484 100644 --- a/app/controllers/api/v1/stats_controller.rb +++ b/app/controllers/api/v1/stats_controller.rb @@ -1,6 +1,6 @@ class Api::V1::StatsController < ApplicationController before_action :ensure_authenticated!, only: [ :show ], unless: -> { Rails.env.development? } - before_action :set_user, only: [ :user_stats, :user_spans, :trust_factor, :user_projects, :user_project ] + before_action :set_user, only: [ :user_stats, :user_spans, :trust_factor, :user_projects, :user_project, :user_projects_details ] def show # take either user_id with a start date & end date @@ -127,19 +127,33 @@ class Api::V1::StatsController < ApplicationController project_name = params[:project_name] return render json: { error: "whats the name?" }, status: :bad_request unless project_name.present? - heartbeats = @user.heartbeats.where(project: project_name) - return render json: { error: "found nuthin" }, status: :not_found if heartbeats.empty? + project_data = get_project([ project_name ]).first + return render json: { error: "found nuthin" }, status: :not_found unless project_data - repo_url = nil - last_commit = nil - languages = heartbeats.where.not(language: [ nil, "" ]).distinct.pluck(:language) + render json: project_data + end - render json: { - project: project_name, - repo_url: repo_url, - last_commit: last_commit, - languages: languages - } + def user_projects_details + return render json: { error: "User not found" }, status: :not_found unless @user + + names = if params[:projects].present? + params[:projects].split(",").map(&:strip) + else + since = params[:since]&.to_datetime || 30.days.ago.beginning_of_day + until_date = params[:until]&.to_datetime || Time.current + + @user.heartbeats + .where(time: since..until_date) + .where.not(project: [ nil, "" ]) + .select(:project) + .distinct + .pluck(:project) + end + + return render json: { projects: [] } if names.empty? + + data = get_project(names) + render json: { projects: data } end private @@ -183,4 +197,52 @@ class Api::V1::StatsController < ApplicationController slack_id end + + def get_project(names) + start_date = params[:start_date]&.to_datetime || 1.year.ago + end_date = params[:end_date]&.to_datetime || Time.current + + query = @user.heartbeats + .where(time: start_date..end_date) + .where(project: names) + + return [] if query.empty? + + stats = query + .group(:project) + .select("project, + COUNT(*) as heartbeat_count, + MIN(time) as first_heartbeat, + MAX(time) as last_heartbeat") + + data = [] + + names.each do |name| + heartbeats = query.where(project: name) + next if heartbeats.empty? + + seconds = heartbeats.duration_seconds || 0 + stat = stats.find { |p| p.project == name } + + languages = heartbeats + .where.not(language: [ nil, "" ]) + .select(:language) + .distinct + .pluck(:language) + + repo = @user.project_repo_mappings.find_by(project_name: name) + + data << { + name: name, + total_seconds: seconds, + languages: languages, + repo_url: repo&.repo_url, + total_heartbeats: stat&.heartbeat_count || 0, + first_heartbeat: stat&.first_heartbeat ? Time.at(stat.first_heartbeat).strftime("%Y-%m-%dT%H:%M:%SZ") : nil, + last_heartbeat: stat&.last_heartbeat ? Time.at(stat.last_heartbeat).strftime("%Y-%m-%dT%H:%M:%SZ") : nil + } + end + + data.sort_by { |project| -project[:total_seconds] } + end end diff --git a/config/routes.rb b/config/routes.rb index e0d78c6..2423383 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -131,6 +131,7 @@ Rails.application.routes.draw do get "users/:username/trust_factor", to: "stats#trust_factor" get "users/:username/projects", to: "stats#user_projects" get "users/:username/project/:project_name", to: "stats#user_project" + get "users/:username/projects/details", to: "stats#user_projects_details" get "users/lookup_email/:email", to: "users#lookup_email", constraints: { email: /[^\/]+/ } get "users/lookup_slack_uid/:slack_uid", to: "users#lookup_slack_uid"