Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

[Frontend]: Redesign Open Source page adding "highlight/recomendado" tag #479

Merged
merged 31 commits into from Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0558f6d
Implement new repository card component
joaoGabriel55 Jul 18, 2023
c390836
Co-authored-by: Guilherme Nunes Lopes <Guilherme-NL@users.noreply.git…
joaoGabriel55 Jul 28, 2023
dc96493
feat: implement update_repository_stats method
joaoGabriel55 Jul 28, 2023
7eb34b7
feat: rename task
joaoGabriel55 Jul 28, 2023
ba9b571
feat: add issues and stars into repositories table
joaoGabriel55 Jul 28, 2023
5c4c176
feat: update RepositoryDecorator
joaoGabriel55 Jul 28, 2023
30cfbb9
feat: update app/views/repositories/_card.html.erb
joaoGabriel55 Jul 28, 2023
f6a3c72
chore: remove unused locale key
joaoGabriel55 Jul 31, 2023
1f4c532
feat: code review
joaoGabriel55 Jul 31, 2023
03ed32f
feat: update new icons
joaoGabriel55 Aug 1, 2023
49a3f3e
resolve conflicts
Guilherme-NL Aug 3, 2023
6780794
Merge branch 'master' into redesign-open-source-page
joaoGabriel55 Aug 3, 2023
91724a8
refactor: create repository with issues and stars as an interger
Guilherme-NL Aug 3, 2023
ecc98fc
refactor: move before bloc to a upper context, and define issues and …
Guilherme-NL Aug 3, 2023
0815ce4
refactor: code review
joaoGabriel55 Aug 4, 2023
b4275f1
Merge branch 'redesign-open-source-page' of https://github.com/Codemi…
joaoGabriel55 Aug 4, 2023
79f8cce
refactor: use render collection
joaoGabriel55 Aug 4, 2023
bd0bf09
Merge branch 'master' into redesign-open-source-page
joaoGabriel55 Aug 8, 2023
ef99de8
refactor: app/services/github/repositories/sync.rb + tests
joaoGabriel55 Aug 11, 2023
b424f4f
Merge branch 'master' of https://github.com/Codeminer42/Punchclock in…
joaoGabriel55 Aug 11, 2023
0257ea0
Merge branch 'redesign-open-source-page' of https://github.com/Codemi…
joaoGabriel55 Aug 11, 2023
8f3fa1f
style: rubocop
joaoGabriel55 Aug 11, 2023
9de6863
refactor: app/decorators/repository_decorator.rb + tests
joaoGabriel55 Aug 11, 2023
512c116
refactor: code review + tests
joaoGabriel55 Aug 11, 2023
0b9df0d
style: code style fix
joaoGabriel55 Aug 11, 2023
bb3e430
refactor: app/services/github/repositories/sync.rb
joaoGabriel55 Aug 11, 2023
974bbbe
chore: update repositories table on schema.rb
joaoGabriel55 Aug 11, 2023
5992e4f
refactor: code review + tests (part II)
joaoGabriel55 Aug 11, 2023
226d7fa
style: rubocop
joaoGabriel55 Aug 11, 2023
e3a9d9b
Merge branch 'master' into redesign-open-source-page
joaoGabriel55 Aug 25, 2023
924440b
Merge branch 'master' into redesign-open-source-page
adbatista Aug 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/assets/images/issues.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/stars.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 20 additions & 2 deletions app/decorators/repository_decorator.rb
@@ -1,19 +1,37 @@
# frozen_string_literal: true

class RepositoryDecorator < ApplicationDecorator
include ActionView::Helpers::NumberHelper

delegate_all

def self.collection_decorator_class
PaginatingDecorator
end

def languages
return '' unless language
return [] unless language

language.split(',').first(3).to_sentence
language.split(', ').first(3).map(&:strip)
end

def name
link[/[\w_-]+$/]
end

def issues_formatted
format_number(model.issues)
end

def stars_formatted
format_number(model.stars)
end

private

def format_number(number)
return number.to_s if number <= 999
adbatista marked this conversation as resolved.
Show resolved Hide resolved

number_to_human(number, precision: 2, separator: '.', units: { thousand: "K", million: "M" }).gsub(/\s+/, '')
adbatista marked this conversation as resolved.
Show resolved Hide resolved
end
end
40 changes: 34 additions & 6 deletions app/services/github/repositories/sync.rb
Expand Up @@ -13,15 +13,14 @@ def call
Rails.logger.info("[GH] -- Repositories: #{repositories.count}")

repositories.map do |repository|
repository_owner, repository_name = repository.link.split('/')[-2..-1]
languages = fetch_repository_languages(repository.link)
joaoGabriel55 marked this conversation as resolved.
Show resolved Hide resolved
stats = fetch_repository_stats(repository.link)

request = client.repos.languages(repository_owner, repository_name)
params = build_update_params(languages, stats)

if request.success?
languages = request.body.keys[0..MAX_LANGUAGES_NUMBER-1].join(', ')
repository.update!(params)

repository.update(language: languages)
end
repository
end.compact
end

Expand All @@ -32,6 +31,35 @@ def call
def repositories
@repositories ||= Repository.all
end

def fetch_repository_languages(repository_link)
repository_owner, repository_name = repository_owner_and_name(repository_link)
request = client.repos.languages(repository_owner, repository_name)

return nil unless request.success?

request.body.keys[0..MAX_LANGUAGES_NUMBER - 1].join(', ')
end

def fetch_repository_stats(repository_link)
repository_owner, repository_name = repository_owner_and_name(repository_link)
request = client.repos.get(repository_owner, repository_name)

return {} unless request.success?

{
issues: request.body['open_issues_count'],
stars: request.body['stargazers_count']
}
end

def repository_owner_and_name(repository_link)
repository_link.split('/').last(2)
end

def build_update_params(languages, stats)
stats.slice(:issues, :stars).merge(language: languages).compact
end
end
end
end
38 changes: 38 additions & 0 deletions app/views/repositories/_repository.html.erb
@@ -0,0 +1,38 @@
<div id='repository-card' class='p-4 border-solid border-2 rounded-xl mb-3'>
<div class='flex justify-between items-start mb-4'>
<div class='flex flex-col gap-2'>
<%= link_to repository.link, target: "_blank" do %>
<h2 class="font-semibold text-lg m-0"><i class="fab fa-github mr-2"></i><%= repository.link %></h2>
<% end %>
<span class="d-block text-dark"><%= simple_format repository.description %></span>
</div>
<div class='flex gap-4 items-center'>
<% if repository.issues > 0 %>
<div class='flex gap-1 items-center text-gray-400' title="<%= "#{t("repositories.index.issues")}: #{repository.issues}" %>">
<%= inline_svg_tag 'issues.svg', class: 'h-4 w-4' %>
<span id='issues-tag' class='font-semibold'><%= repository.issues_formatted %></span>
</div>
<% end %>
<% if repository.stars > 0 %>
<div class='flex gap-1 items-center text-gray-400' title="<%= "#{t("repositories.index.stars")}: #{repository.stars}" %>">
<%= inline_svg_tag 'stars.svg', class: 'h-5 w-5' %>
<span id='stars-tag' class='font-semibold'><%= repository.stars_formatted %></span>
</div>
<%end%>
</div>
</div>
<div class='flex justify-between items-center'>
<div class="flex gap-2">
<% repository.languages.each do |language| %>
<span id='language-tag' class="bg-gray-300 text-gray-500 px-2 py-1 font-semibold text-sm rounded-lg">
<%= language %>
</span>
<% end %>
</div>
<% if repository.highlight? %>
<span class="bg-sky-500 px-2 py-1 text-white font-semibold text-sm rounded-lg">
<%= t("repositories.index.highlight") %>
</span>
<%end%>
</div>
</div>
12 changes: 1 addition & 11 deletions app/views/repositories/index.html.erb
Expand Up @@ -15,16 +15,6 @@
<% end %>
</div>

<div class="list-group">
<% @repositories.each do |repository| %>
<%= link_to repository.link, class: "list-group-item list-group-item-action", target: "_blank" do %>
<i class="fab fa-github"></i>
<span class="d-inline-block"><%= repository.link %></span>
<span class="d-inline-block float-right"> <%= repository.languages %></span>
<span class="d-block text-dark"><%= simple_format repository.description %></span>
<% end %>
<% end %>
</div>

<%= render @repositories %>
<%= paginate @repositories %>
</div>
3 changes: 3 additions & 0 deletions config/locales/pt-BR/pt-BR.yml
Expand Up @@ -96,6 +96,9 @@ pt-BR:
repositories:
index:
open_source_repositories: "Projetos Open Source"
highlight: 'Recomendado'
issues: 'Issues'
stars: 'Stars'
not_started: 'Não iniciado'
finished: 'Finalizado'
admin:
Expand Down
@@ -0,0 +1,6 @@
class AddIssuesAndStarsToRepositories < ActiveRecord::Migration[7.0]
def change
add_column :repositories, :issues, :integer, default: 0
add_column :repositories, :stars, :integer, default: 0
end
end
4 changes: 3 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_07_24_160449) do
ActiveRecord::Schema[7.0].define(version: 2023_07_28_175727) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -189,6 +189,8 @@
t.string "language"
t.boolean "highlight", default: false
t.text "description"
t.integer "issues", default: 0
t.integer "stars", default: 0
end

create_table "skills", force: :cascade do |t|
Expand Down
2 changes: 1 addition & 1 deletion lib/tasks/github.rake
@@ -1,6 +1,6 @@
namespace :github do
desc "Sync repository languages"
task sync_repository_languages: :environment do
task sync_repository_languages_and_stats: :environment do
Rails.logger = Logger.new(STDOUT)

client = Github.new(headers: {"Authorization" => "token #{ENV['GITHUB_OAUTH_TOKEN']}"})
Expand Down
107 changes: 103 additions & 4 deletions spec/decorators/repository_decorator_spec.rb
Expand Up @@ -6,23 +6,23 @@
let(:repository) { create(:repository, language: 'Javascript, Docker, Ruby, HTML, CSS').decorate }

it 'returns only the first three' do
expect(repository.languages).to eq('Javascript, Docker e Ruby')
expect(repository.languages).to eq(%w[Javascript Docker Ruby])
end
end

context 'when repository has less than three languages' do
let(:repository) { create(:repository, language: 'Javascript, Docker').decorate }

it 'returns available languages' do
expect(repository.languages).to eq('Javascript e Docker')
expect(repository.languages).to eq(%w[Javascript Docker])
end
end

context 'when repository has no languages' do
let(:repository) { create(:repository, language: nil).decorate }

it 'returns empty string' do
expect(repository.languages).to eq ''
expect(repository.languages).to be_empty
end
end
end
Expand All @@ -34,5 +34,104 @@
expect(repository.name).to eql "rails2-r_ruby"
end
end
end

describe '#issues_formatted' do
context 'when repository has less than 1_000 issues' do
let(:repository) { build(:repository, issues: 999).decorate }

it 'returns 999' do
expect(repository.issues_formatted).to eql '999'
end
end

context 'when repository has 1_000 issues' do
let(:repository) { build(:repository, issues: 1_000).decorate }

it 'returns 1K' do
expect(repository.issues_formatted).to eql '1K'
end
end

context 'when repository has more than 1_001 issues' do
let(:repository) { build(:repository, issues: 1_001).decorate }

it 'returns 1K' do
expect(repository.issues_formatted).to eql '1K'
end
end

context 'when repository has 1 million issues' do
let(:repository) { build(:repository, issues: 1_000_000).decorate }

it 'returns 1M' do
expect(repository.issues_formatted).to eql '1M'
end
end

context 'when repository has more than 1 million issues' do
let(:repository) { build(:repository, issues: 1_000_001).decorate }

it 'returns 1M' do
expect(repository.issues_formatted).to eql '1M'
end
end

context 'when repository has 0 issues' do
let(:repository) { build(:repository, issues: 0).decorate }

it 'returns 0' do
expect(repository.issues_formatted).to eql '0'
end
end
end

describe '#stars_formatted' do
context 'when repository has less than 1_000 stars' do
let(:repository) { build(:repository, stars: 999).decorate }

it 'returns 999' do
expect(repository.stars_formatted).to eql '999'
end
end

context 'when repository has 1_000 stars' do
let(:repository) { build(:repository, stars: 1_000).decorate }

it 'returns 1K' do
expect(repository.stars_formatted).to eql '1K'
end
end

context 'when repository has more than 1_001 stars' do
let(:repository) { build(:repository, stars: 1_001).decorate }

it 'returns 1K' do
expect(repository.stars_formatted).to eql '1K'
end
end

context 'when repository has 1 million stars' do
let(:repository) { build(:repository, stars: 1_000_000).decorate }

it 'returns 1M' do
expect(repository.stars_formatted).to eql '1M'
end
end

context 'when repository has more than 1 million stars' do
let(:repository) { build(:repository, stars: 1_000_001).decorate }

it 'returns 1M' do
expect(repository.stars_formatted).to eql '1M'
end
end

context 'when repository has 0 stars' do
let(:repository) { build(:repository, stars: 0).decorate }

it 'returns 0' do
expect(repository.stars_formatted).to eql '0'
end
end
end
end