Add project cloning

This commit is contained in:
Max Wofford 2025-05-20 13:32:17 -04:00
parent edcdb98d18
commit ed6e271577
4 changed files with 121 additions and 35 deletions

View file

@ -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

View file

@ -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"],

View file

@ -1,19 +1,49 @@
<div class="mt-16 md:mt-12 p-8 md:p-12">
<div class = "">
<p class="font-bold text-3xl">Check out what others are building!</p>
<p class="font-bold opacity-70 mt-8"><i><%= pluralize(@projects.count, "project") %> <%= @projects.count == 1 ? "has" : "have" %> been started:</i></p>
<p class="font-bold text-3xl">Check out what others are building!</p>
<p class="font-bold opacity-70 mt-8"><i><%= pluralize(@projects.count, "project") %> <%= @projects.count == 1 ? "has" : "have" %> been started:</i></p>
<div class="grid md:grid-cols-3 gap-4 mt-4 sm:grid-cols-2 grid-cols-1">
<% @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 %>
<h1 class="text-2xl"><%= project.name %> <span class="text-base text-[#96ABF9]">(<%= project.github_slug %>)</span></h1>
<p class="mb-2">created by <span class="text-[#96ABF9]">[<%= project.author %>]</span></p>
<p class="opacity-70"><%= project.description %></p>
<p class="opacity-70 mt-2">Started on <%= project.formatted_created_at %></p>
<div class="grid md:grid-cols-3 gap-4 mt-4 sm:grid-cols-2 grid-cols-1">
<% @projects.each do |project| %>
<div class="bg-[#2E2A54] border-2 border-[#544FFF] rounded-lg text-white hover:bg-[#3A3A6D] transition duration-100 transition-transform hover:scale-102 p-8 h-full flex flex-col">
<% if project.has_journal? %>
<%= link_to project_path(user: project.user, project_name: project.project_name), class: "block mb-2" do %>
<h1 class="text-2xl font-bold"><%= project.name.truncate(25) %></h1>
<% end %>
<% else %>
<h1 class="text-2xl font-bold mb-2">
<%= project.name.truncate(25) %>
</h1>
<p class="text-sm font-bold text-yellow-300">⚠️ This project lacks a <code>journal.md</code> file.</p>
<% end %>
<% end %>
</div>
<%= 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 %>
<div class="mb-4 text-[#b3aaff] text-sm opacity-70">
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? %>
<span class="ml-2">• Started on <%= project.formatted_created_at %></span>
<% end %>
</div>
<% if project.description.present? %>
<p class="opacity-80 mt-auto"><%= project.description.truncate(120) %></p>
<% end %>
<% if Rails.env.development? %>
<summary>
<details>
<%= project.inspect %>
</details>
</summary>
<% end %>
</div>
<% end %>
</div>
</div>

View file

@ -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"