From ed6e2715775b7b065397fb94116c547be37de7c1 Mon Sep 17 00:00:00 2001 From: Max Wofford Date: Tue, 20 May 2025 13:32:17 -0400 Subject: [PATCH] Add project cloning --- app/controllers/projects_controller.rb | 9 ++- app/models/project.rb | 91 +++++++++++++++++++++----- app/views/projects/index.html.erb | 54 +++++++++++---- config/routes.rb | 2 +- 4 files changed, 121 insertions(+), 35 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 616deb4..0e58b5d 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,14 +1,13 @@ class ProjectsController < ApplicationController - include MarkdownRenderable - require "yaml" - def index @projects = Project.all + + CloneProjectsJob.perform_later if @projects.empty? end def show - @project = Project.find(params[:repo], params[:project_name]) - render_not_found unless @project + @project = Project.find(params[:user], params[:project_name]) + not_found unless @project end def new diff --git a/app/models/project.rb b/app/models/project.rb index 5ae1933..5f7204b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,9 +1,9 @@ class Project include MarkdownRenderable - attr_reader :repo, :project_name, :title, :author, :description, :created_at, :content + attr_reader :user, :project_name, :title, :author, :description, :created_at, :content def initialize(attributes = {}) - @repo = attributes[:repo] + @user = attributes[:user] @project_name = attributes[:project_name] @title = attributes[:title] @author = attributes[:author] @@ -13,55 +13,112 @@ class Project end def name - title + title.presence || project_name.titleize end def github_slug - "#{repo}/#{project_name}" + "#{user}/#{project_name}" end def github_repo "https://github.com/#{github_slug}" end + def author_display + return "@#{user}" if author.blank? + author + end + + def user_link + "https://github.com/#{user}" + end + def created_at_date + return nil unless created_at Date.parse(created_at) + rescue Date::Error + nil end def formatted_created_at + return nil unless created_at_date created_at_date.strftime("%B %d, %Y") end - def self.all - Dir.glob(Rails.root.join("content/projects/*/*/journal.md")).map do |file| - content = File.read(file) - metadata, _ = parse_frontmatter(content) + def has_creation_date? + created_at_date.present? + end - # Extract repo and project name from path - path_parts = file.split("/") - repo = path_parts[-3] - project_name = path_parts[-2] + def has_journal? + # Find journal file, case-insensitive + dir = Rails.root.join("content/projects", user, project_name) + Dir.glob(File.join(dir, "*")).any? { |f| File.basename(f).downcase == "journal.md" } + end + + def self.all + Dir.glob(Rails.root.join("content/projects/*/*")).map do |dir| + next unless File.directory?(dir) + + # Extract user and project name from path + path_parts = dir.split("/") + user = path_parts[-2] + project_name = path_parts[-1] + + # Find journal file, case-insensitive + journal_path = Dir.glob(File.join(dir, "*")).find { |f| File.basename(f).downcase == "journal.md" } + + metadata = {} + if journal_path && File.exist?(journal_path) + content = File.read(journal_path) + metadata, _ = parse_frontmatter(content) + end + + unless Rails.env.development? + next if user == "hackclub" && project_name == "awesome-project" + end new( - repo: repo, + user: user, project_name: project_name, title: metadata["title"], author: metadata["author"], description: metadata["description"], created_at: metadata["created_at"] ) - end.sort_by(&:created_at_date).reverse + end.compact end - def self.find(repo, project_name) - file_path = Rails.root.join("content/projects", repo, project_name, "journal.md") + def self.working + all.select do |project| + journal_path = Rails.root.join("content/projects", project.user, project.project_name, "journal.md") + next false unless File.exist?(journal_path) + + content = File.read(journal_path) + metadata, _ = parse_frontmatter(content) + + # Check if all required metadata is present + required_fields = [ "title", "author", "description", "created_at" ] + next false unless required_fields.all? { |field| metadata[field].present? } + + # Update the project with metadata + project.instance_variable_set(:@title, metadata["title"]) + project.instance_variable_set(:@author, metadata["author"]) + project.instance_variable_set(:@description, metadata["description"]) + project.instance_variable_set(:@created_at, metadata["created_at"]) + + true + end + end + + def self.find(user, project_name) + file_path = Rails.root.join("content/projects", user, project_name, "journal.md") return nil unless File.exist?(file_path) content = File.read(file_path) metadata, markdown_content = parse_frontmatter(content) new( - repo: repo, + user: user, project_name: project_name, title: metadata["title"], author: metadata["author"], diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 3a718e5..104549a 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -1,19 +1,49 @@
-
-

Check out what others are building!

-

<%= pluralize(@projects.count, "project") %> <%= @projects.count == 1 ? "has" : "have" %> been started:

+

Check out what others are building!

+

<%= pluralize(@projects.count, "project") %> <%= @projects.count == 1 ? "has" : "have" %> been started:

-
- <% @projects.each do |project| %> - <%= link_to project_path(repo: project.repo, project_name: project.project_name), class: "block bg-[#2E2A54] border-2 border-[#544FFF] max-w-4xl py-8 px-8 rounded-lg text-white hover:bg-[#3A3A6D] transition duration-100 transition-transform hover:scale-102" do %> -

<%= project.name %> (<%= project.github_slug %>)

-

created by [<%= project.author %>]

-

<%= project.description %>

-

Started on <%= project.formatted_created_at %>

+
+ <% @projects.each do |project| %> +
+ <% if project.has_journal? %> + <%= link_to project_path(user: project.user, project_name: project.project_name), class: "block mb-2" do %> +

<%= project.name.truncate(25) %>

+ <% end %> + <% else %> +

+ <%= project.name.truncate(25) %> +

+

⚠️ This project lacks a journal.md file.

<% end %> - <% end %> -
+ <%= link_to project.github_repo, target: "_blank", class: "text-base text-[#96ABF9] text-sm rounded px-2 py-1 inline-block" do %> + [<%= project.github_slug %>] + <% end %> +
+ Created by + <% if project.author.present? %> + <%= link_to project.user_link, target: "_blank", class: "text-base text-[#96ABF9] text-sm rounded px-2 py-1 inline-block" do %> + [<%= project.author %>] + <% end %> + <% else %> + <%= project.author_display %> + <% end %> + <% if project.has_creation_date? %> + • Started on <%= project.formatted_created_at %> + <% end %> +
+ <% if project.description.present? %> +

<%= project.description.truncate(120) %>

+ <% end %> + <% if Rails.env.development? %> + +
+ <%= project.inspect %> +
+
+ <% end %> +
+ <% end %>
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index c11cc61..c491e6b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,7 +13,7 @@ Rails.application.routes.draw do root "landing#index" resources :users get "/projects", to: "projects#index" - get "/projects/:repo/:project_name", to: "projects#show", as: :project + get "/projects/:user/:project_name", to: "projects#show", as: :project get "/info", to: "info#show"