Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@use "components/dropdown";
@use "components/shop-item-card";
@use "components/post";
@use "components/modal";

// Pages
@use "pages/projects/index";
Expand Down
238 changes: 238 additions & 0 deletions app/assets/stylesheets/components/_modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
padding: var(--space-m);
animation: fadeIn 0.2s ease-out;
}

.modal-content {
background: var(--color-bg);
border: 14px solid var(--color-brown-400);
border-radius: calc(var(--border-radius) * 1.8);
width: 100%;
max-width: 900px;
max-height: 85vh;
display: flex;
flex-direction: column;
box-shadow: var(--shadow);
animation: slideUp 0.2s ease-out;
overflow: hidden;
}

.modal-header {
padding: var(--space-m) var(--space-l);
background-color: var(--color-brown-500);
display: flex;
justify-content: space-between;
align-items: center;
color: var(--color-bg);
border-bottom: 4px solid var(--color-brown-400);

h2 {
margin: 0;
font-family: var(--font-family-subtitle);
font-size: var(--font-size-xxl);
color: var(--color-bg);
}
}

.modal-close {
background: none;
border: none;
cursor: pointer;
color: var(--color-bg);
padding: var(--space-xs);
border-radius: var(--border-radius);
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.1s;

&:hover {
transform: scale(1.1);
background-color: rgba(255, 255, 255, 0.1);
}

svg {
width: 32px;
height: 32px;
}
}

.modal-body {
padding: var(--space-xl);
overflow-y: auto;
color: var(--color-brown-700);
font-weight: normal;
font-family: var(--font-family-text);
line-height: 1.6;
font-size: 1.1rem;

/* Markdown Content Styles */

> *:first-child {
margin-top: 0;
}

h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-family-subtitle);
color: var(--color-brown-700);
margin-top: 1.5em;
margin-bottom: 0.5em;
line-height: 1.2;
}

h1 {
font-size: 2.5rem;
border-bottom: 4px solid var(--color-brown-200);
padding-bottom: 0.2em;
}

h2 {
font-size: 2rem;
border-bottom: 2px solid var(--color-brown-200);
padding-bottom: 0.2em;
}

h3 {
font-size: 1.5rem;
}

a {
color: var(--color-blue-500);
text-decoration: underline;
font-weight: bold;

&:hover {
color: var(--color-blue-600);
}
}

p {
margin-bottom: 1em;
}

img {
max-width: 100%;
height: auto;
border-radius: var(--border-radius);
border: 4px solid var(--color-brown-200);
margin: 1em 0;
}

pre {
background-color: var(--color-brown-700);
color: var(--color-bg);
padding: var(--space-m);
border-radius: var(--border-radius);
overflow-x: auto;
font-family: monospace;
margin: 1em 0;
border: 4px solid var(--color-brown-600);
}

code {
background-color: var(--color-brown-100);
color: var(--color-brown-700);
padding: 0.2em 0.4em;
border-radius: 4px;
font-family: monospace;
font-size: 0.9em;
}

pre code {
background-color: transparent;
color: inherit;
padding: 0;
font-size: 1em;
}

blockquote {
border-left: 6px solid var(--color-brown-400);
background-color: var(--color-brown-100);
margin: 1.5em 0;
padding: 1em;
border-radius: 0 var(--border-radius) var(--border-radius) 0;
font-style: italic;

p:last-child {
margin-bottom: 0;
}
}

ul,
ol {
padding-left: 1.5em;
margin-bottom: 1em;

li {
margin-bottom: 0.5em;
&::marker {
color: var(--color-brown-500);
font-weight: bold;
}
}
}

hr {
border: 0;
border-top: 4px dashed var(--color-brown-300);
margin: 2em 0;
}

table {
width: 100%;
border-collapse: collapse;
margin: 1.5em 0;
display: block;
overflow-x: auto;

th,
td {
padding: 0.75em;
border: 2px solid var(--color-brown-200);
}

th {
background-color: var(--color-brown-100);
font-family: var(--font-family-subtitle);
color: var(--color-brown-700);
text-align: left;
}

tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.02);
}
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

@keyframes slideUp {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
5 changes: 3 additions & 2 deletions app/components/project_show_card_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,11 @@
<% if project.readme_url.present? %>
<%= render ButtonComponent.new(
text: "Readme",
href: project.readme_url,
href: helpers.readme_project_path(project),
color: :brown,
variant: :borderless,
icon: "icons/paper.svg"
icon: "icons/paper.svg",
data: { turbo_frame: "readme_modal" }
) %>
<% end %>
</div>
Expand Down
34 changes: 33 additions & 1 deletion app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class ProjectsController < ApplicationController
before_action :set_project_minimal, only: [ :edit, :update, :destroy ]
before_action :set_project, only: [ :show ]
before_action :set_project, only: [ :show, :readme ]

def index
authorize Project
Expand All @@ -15,6 +15,38 @@ def show
.includes(:user, postable: [ { attachments_attachments: :blob } ])
end

def readme
authorize @project

unless turbo_frame_request?
redirect_to project_path(@project)
return
end

url = @project.readme_url

if url.present?
begin
response = Faraday.get(url) do |req|
req.options.timeout = 5
req.options.open_timeout = 2
end

if response.success?
@content = response.body.force_encoding("UTF-8")
else
@content = "Failed to load README from #{url}: (HTTP #{response.status})"
end
rescue Faraday::Error => e
content = "Error loading README: #{e.message}"
end
else
@content = "Couldn't find README! Make sure ya set it up!"
end

render layout: false
end

def new
@project = Project.new
authorize @project
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ application.register(
import HelloController from "./hello_controller";
application.register("hello", HelloController);

import ModalController from "./modal_controller";
application.register("modal", ModalController);

import ProjectFormController from "./project_form_controller";
application.register("project-form", ProjectFormController);

Expand Down
28 changes: 28 additions & 0 deletions app/javascript/controllers/modal_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
connect() {
document.body.style.overflow = "hidden";
}

disconnect() {
document.body.style.overflow = "";
}

close(e) {
if (e) e.preventDefault();
this.element.remove();
}

closeBackground(e) {
if (e.target === this.element) {
this.close(e);
}
}

closeWithEsc(e) {
if (e.key === "Escape") {
this.close(e);
}
}
}
23 changes: 23 additions & 0 deletions app/models/vote.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# == Schema Information
#
# Table name: votes
#
# id :bigint not null, primary key
# category :integer default("originality"), not null
# score :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# project_id :bigint not null
# user_id :bigint not null
#
# Indexes
#
# index_votes_on_project_id (project_id)
# index_votes_on_user_id (user_id)
# index_votes_on_user_id_and_project_id_and_category (user_id,project_id,category) UNIQUE
#
# Foreign Keys
#
# fk_rails_... (project_id => projects.id)
# fk_rails_... (user_id => users.id)
#
class Vote < ApplicationRecord
belongs_to :user
belongs_to :project
Expand Down
4 changes: 4 additions & 0 deletions app/policies/project_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def show?
true
end

def readme?
show?
end

def new?
logged_in?
end
Expand Down
Loading