Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Delivering: Dev Hiring Challenge #107

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[
import_deps: [:ecto, :phoenix],
inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"],
subdirectories: ["priv/*/migrations"]
]
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
highlight_repo-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

127 changes: 111 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,117 @@
# Desafio técnico para desenvolvedores
# HighlightRepo

Construa uma nova aplicação, utilizando o framework de sua preferência (Ruby on Rails, Elixir Phoenix, Python Django ou Flask, NodeJS Sails, Java Spring, ASP.NET ou outro), a qual deverá conectar na API do GitHub e disponibilizar as seguintes funcionalidades:
HighlighRepo is a fullstack application to show you the top 10 highlighted git repos
languages built in Elixir, Python, Javascript, PHP and Rust.

- Botão para buscar e armazenar os repositórios destaques de 5 linguagens à sua escolha;
- Listar os repositórios encontrados;
- Visualizar os detalhes de cada repositório.
**Application deployed and available at: [Gigalixir](https://highlight-repo.gigalixirapp.com/)**

Alguns requisitos:
This application was built with the stack:

- Deve ser uma aplicação totalmente nova;
- A solução deve estar em um repositório público do GitHub;
- A aplicação deve armazenar as informações encontradas;
- Utilizar PostgreSQL, MySQL ou SQL Server;
- O deploy deve ser realizado, preferencialmente, no Heroku, AWS ou no Azure;
- A aplicação precisa ter testes automatizados;
- Preferenciamente dockerizar a aplicação;
- Por favor atualizar o readme da aplicação com passo a passo com instrução para subir o ambiente.
**Backend: [Elixir](https://elixir-lang.org) ([Phoenix](https://www.phoenixframework.org))**

Quando terminar, faça um Pull Request neste repo e avise-nos por email.
**Frontend: [Javascript](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript) (No framework)**

**IMPORTANTE:** se você não conseguir finalizar o teste, por favor nos diga o motivo e descreva quais foram as suas dificuldades. Você pode também sugerir uma outra abordagem para avaliarmos seus skills técnicos, vender seu peixe, mostrar-nos do que é capaz.
**Database: [Postgres](https://www.postgresql.org)**

**Environment: [Docker](https://www.docker.com)**

*Note: since this project's API is using the free githup repositories API, multiple searches at the same time
or too much requests in a short period may exceed the Github's rate limit per request and an error will be returned.*

## **Installation**

To use this service you'll need [Elixir](https://elixir-lang.org/install.html),
[Phoenix](https://hexdocs.pm/phoenix/installation.html) e [PostgreSql](https://www.postgresql.org/).

You may want to use postgres from a docker container.
For that, type the following command to create an "up and running" postgres container automatically for you `docker-compose -f postgres-compose.yml up -d`

* Install dependencies by using `mix deps.get`
* Setup your database structure by using `mix ecto.setup`
* Initialize Phoenix locally by typing `mix phx.server`

Now you can visit [`localhost:4000`](http://localhost:4000) from your browser or api tool to access routes.

## **Tests**

This application has 100% tests coverage. So in order to run follow the below:

* Run the tests using the command `mix test`

* Check tests coverage with the command `mix coveralls.html`

## **API**

Here's a little bit about the api in case you want to use it alone without the frontend.

Why not? It's a open source project.

*Note: Using the api, you can search for ANY languages to get highlighted repos on github*

## **Routes**

### **Repos Info**

endpoint: `/repos`

type: `POST`

**Params**

* Language to be searched on Git: `language string`

**Body Params (JSON)**

```json
{
"language": "elixir"
}
```

**Response**

```json
{
"data": [
{
"description": "Elixir is a dynamic, functional language designed for building scalable and maintainable applications",
"forks": 2833,
"name": "elixir",
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/1481354?v=4",
"name": "elixir-lang",
"url": "https://github.com/elixir-lang"
},
"stars": 19799,
"url": "https://github.com/elixir-lang/elixir"
}
]
}
```

### **Get Repo**

endpoint: `/repo?name={name}`

**Params**

* Repo name: `name string`

type: `GET`

**Response**

```json
{
"description": "Elixir is a dynamic, functional language designed for building scalable and maintainable applications",
"forks": 2833,
"name": "elixir",
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/1481354?v=4",
"name": "elixir-lang",
"url": "https://github.com/elixir-lang"
},
"stars": 19799,
"url": "https://github.com/elixir-lang/elixir"
}
```
120 changes: 120 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* This file is for your main application CSS */
@import "../node_modules/materialize-css/dist/css/materialize.min.css";

/* Alerts and form errors used by phx.new */
.alert {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-info {
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
}
.alert-warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
}
.alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
.alert p {
margin-bottom: 0;
}
.alert:empty {
display: none;
}
.invalid-feedback {
color: #a94442;
display: block;
margin: -1rem 0 2rem;
}

/* LiveView specific classes for your customization */
.phx-no-feedback.invalid-feedback,
.phx-no-feedback .invalid-feedback {
display: none;
}

.phx-click-loading {
opacity: 0.5;
transition: opacity 1s ease-out;
}

.phx-loading{
cursor: wait;
}

.phx-modal {
opacity: 1!important;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
}

.phx-modal-content {
background-color: #fefefe;
margin: 15vh auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}

.phx-modal-close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}

.phx-modal-close:hover,
.phx-modal-close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}

.fade-in-scale {
animation: 0.2s ease-in 0s normal forwards 1 fade-in-scale-keys;
}

.fade-out-scale {
animation: 0.2s ease-out 0s normal forwards 1 fade-out-scale-keys;
}

.fade-in {
animation: 0.2s ease-out 0s normal forwards 1 fade-in-keys;
}
.fade-out {
animation: 0.2s ease-out 0s normal forwards 1 fade-out-keys;
}

@keyframes fade-in-scale-keys{
0% { scale: 0.95; opacity: 0; }
100% { scale: 1.0; opacity: 1; }
}

@keyframes fade-out-scale-keys{
0% { scale: 1.0; opacity: 1; }
100% { scale: 0.95; opacity: 0; }
}

@keyframes fade-in-keys{
0% { opacity: 0; }
100% { opacity: 1; }
}

@keyframes fade-out-keys{
0% { opacity: 1; }
100% { opacity: 0; }
}
101 changes: 101 additions & 0 deletions assets/css/phoenix.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* Includes some default style for the starter application.
* This can be safely deleted to start fresh.
*/

/* Milligram v1.4.1 https://milligram.github.io
* Copyright (c) 2020 CJ Patoilo Licensed under the MIT license
*/

*,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#000000;font-family:'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#0069d9;border:0.1rem solid #0069d9;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#0069d9;border-color:#0069d9}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#0069d9}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#0069d9}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#0069d9}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#0069d9}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #0069d9;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='color'],input[type='date'],input[type='datetime'],input[type='datetime-local'],input[type='email'],input[type='month'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],input[type='week'],input:not([type]),textarea,select{-webkit-appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem .7rem;width:100%}input[type='color']:focus,input[type='date']:focus,input[type='datetime']:focus,input[type='datetime-local']:focus,input[type='email']:focus,input[type='month']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,input[type='week']:focus,input:not([type]):focus,textarea:focus,select:focus{border-color:#0069d9;outline:0}select{background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%23d1d1d1" d="M0,0l6,8l6-8"/></svg>') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%230069d9" d="M0,0l6,8l6-8"/></svg>')}select[multiple]{background:none;height:auto}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.container{margin:0 auto;max-width:112.0rem;padding:0 2.0rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-40{margin-left:40%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-60{margin-left:60%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#0069d9;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;display:block;overflow-x:auto;text-align:left;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}@media (min-width: 40rem){table{display:table;overflow-x:initial}}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}

/* General style */
h1{font-size: 3.6rem; line-height: 1.25}
h2{font-size: 2.8rem; line-height: 1.3}
h3{font-size: 2.2rem; letter-spacing: -.08rem; line-height: 1.35}
h4{font-size: 1.8rem; letter-spacing: -.05rem; line-height: 1.5}
h5{font-size: 1.6rem; letter-spacing: 0; line-height: 1.4}
h6{font-size: 1.4rem; letter-spacing: 0; line-height: 1.2}
pre{padding: 1em;}

.container{
margin: 0 auto;
max-width: 80.0rem;
padding: 0 2.0rem;
position: relative;
width: 100%
}
select {
width: auto;
}

/* Phoenix promo and logo */
.phx-hero {
text-align: center;
border-bottom: 1px solid #e3e3e3;
background: #eee;
border-radius: 6px;
padding: 3em 3em 1em;
margin-bottom: 3rem;
font-weight: 200;
font-size: 120%;
}
.phx-hero input {
background: #ffffff;
}
.phx-logo {
min-width: 300px;
margin: 1rem;
display: block;
}
.phx-logo img {
width: auto;
display: block;
}

/* Headers */
header {
width: 100%;
background: #fdfdfd;
border-bottom: 1px solid #eaeaea;
margin-bottom: 2rem;
}
header section {
align-items: center;
display: flex;
flex-direction: column;
justify-content: space-between;
}
header section :first-child {
order: 2;
}
header section :last-child {
order: 1;
}
header nav ul,
header nav li {
margin: 0;
padding: 0;
display: block;
text-align: right;
white-space: nowrap;
}
header nav ul {
margin: 1rem;
margin-top: 0;
}
header nav a {
display: block;
}

@media (min-width: 40.0rem) { /* Small devices (landscape phones, 576px and up) */
header section {
flex-direction: row;
}
header nav ul {
margin: 1rem;
}
.phx-logo {
flex-basis: 527px;
margin: 2rem 1rem;
}
}
Loading