Skip to content

Commit

Permalink
Merge pull request #117 from TreinaDev/feature/usuario-ve-postagens-n…
Browse files Browse the repository at this point in the history
…o-forum

Feature/postagens no forum
  • Loading branch information
adoniranfranceh authored Feb 16, 2024
2 parents 637a31c + bb4baa2 commit 8b74bcb
Show file tree
Hide file tree
Showing 23 changed files with 510 additions and 21 deletions.
40 changes: 40 additions & 0 deletions app/controllers/api/v1/posts_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Api
module V1
class PostsController < Api::V1::ApiController
before_action :set_project
before_action :check_contributor

def create
@post = @project.posts.build(post_params)
@post.user_role = UserRole.find_by(user: current_user, project: @project)

return render status: :created, json: json_response(@post) if @post.save

render json: { errors: @post.errors.full_messages }, status: :conflict
end

private

def json_response(post)
{ id: post.id, title: post.title, body: post.body, author: post.user.full_name,
date: I18n.t('posts.posted_now') }
end

def set_project
@project = Project.find(params[:project_id])
end

def check_contributor
return if @project.member?(current_user)

response = { error: I18n.t('posts.no_permission') }

render status: :unauthorized, json: response
end

def post_params
params.require(:post).permit(:title, :body)
end
end
end
end
17 changes: 17 additions & 0 deletions app/controllers/forums_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class ForumsController < ApplicationController
before_action :set_project
before_action :check_contributor
def index
@posts = @project.posts.order(created_at: :desc)
end

private

def set_project
@project = Project.find(params[:project_id])
end

def check_contributor
redirect_to root_path, alert: t('.not_contributor') unless @project.member?(current_user)
end
end
4 changes: 2 additions & 2 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
import "@hotwired/turbo-rails"
import * as bootstrap from "bootstrap"
import { createApp } from 'vue/dist/vue.esm-bundler.js'
import HelloComponent from './components/hello_vue.js'
import ForumComponent from './components/forum_vue.js'

createApp(HelloComponent).mount('#vue-app')
createApp(ForumComponent).mount('#vue-app')
78 changes: 78 additions & 0 deletions app/javascript/components/forum_vue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@


export default {
data() {
return {
searchText: '',
selectedFilter: '',
project: {},
posts: [],
newPost: {
title: '',
body: ''
},
errors: []
}
},

async mounted() {
this.loadPosts();
this.project = { id: window.project.id,
title: window.project.title };
this.errors = []
},

computed: {
filteredPosts() {
const searchType = this.selectedFilter
return this.posts.filter(post => {
if (searchType === '') {
return (
post.title.toLowerCase().includes(this.searchText.toLowerCase()) ||
post.body.toLowerCase().includes(this.searchText.toLowerCase())
)
} else {
return post[searchType].toLowerCase().includes(this.searchText.toLowerCase());
}
})
}
},

methods: {
loadPosts(){
this.posts = window.posts.map(item => ({ id: item.id,
title: item.title,
body: item.body,
author: item.author,
date: item.date }));

this.activePage = 'postsIndex'

},

async submitForm() {
try {

const response = await fetch(`/api/v1/projects/${this.project.id}/posts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.newPost)
});


const data = await response.json()
if (response.ok) {
this.posts.unshift(data);
this.newPost.title = ''
this.newPost.body = ''
} else {
this.errors = data.errors;
}
} catch (error) {
console.error('Erro ao enviar o formulário:', error);
}
}
}
}
16 changes: 0 additions & 16 deletions app/javascript/components/hello_vue.js

This file was deleted.

7 changes: 7 additions & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Post < ApplicationRecord
belongs_to :user_role
belongs_to :project
delegate :user, to: :user_role

validates :title, :body, presence: true
end
1 change: 1 addition & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Project < ApplicationRecord
has_many :meetings, dependent: :destroy
has_many :project_job_categories, dependent: :destroy
has_many :proposals, dependent: :destroy
has_many :posts, dependent: :destroy

validates :title, :description, :category, presence: true

Expand Down
54 changes: 54 additions & 0 deletions app/views/forums/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<%= render 'shared/project_header', project: @project %>
<div id="vue-app">
<forum-vue>
<div class="row">
<div class="col-md-8 mx-auto mt-3">
<label class="form-label visually-hidden" for="searchText"><%= t('forums.search') %></label>
<input class="form-control mb-3" v-model="searchText" type="text" name="searchText" id="searchText" placeholder="<%= t('forums.search_posts')%>">
<form @submit.prevent="submitForm">
<div v-if="errors.length > 0" class="alert alert-danger" v-for="error in errors">
{{ error }}
</div>
<div>
<label for="title" class="form-label"><%= Post.human_attribute_name('title') %></label>
<input type="text" id="title" v-model="newPost.title" class="form-control">
</div>
<div>
<label for="body" class="form-label"><%= Post.human_attribute_name('body') %></label>
<textarea id="body" v-model="newPost.body" class="form-control"></textarea>
</div>
<div>
<button type="submit" class="btn btn-primary mb-3 mt-1"><%= t('forums.post') %></button>
</div>
</form>
<div v-if="filteredPosts.length === 0">
<h3><%= t('forums.no_posts') %></h3>
</div>
<div class="card h-20 mb-3" v-for="item in filteredPosts" :key="item.id">
<div class="card-header border-bottom border-3 border-success text-success bg-light bg-gradient display-6 fs-5">
{{ item.title }}
</div>
<div class="card-body bg-light bg-gradient">
<p class="card-text">
{{ item.body }}
</p>
</div>
<div class="card-footer text-muted ">
<small >
<span class="text-end">por {{ item.author }} - {{ item.date }}</span>
</small>
</div>
</div>
</div>
</div>
</forum-vue>
</div>
<script>
var project = <%= { id: @project.id, title: @project.title }.to_json.html_safe %>
var posts = <%= @posts.map { |post| { id: post.id,
title: post.title,
body: post.body,
date: t('forums.posted_in', time: time_ago_in_words(post.created_at)),
author: post.user.full_name } }.to_json.html_safe %>;
var errors = <%= { error: @errors }.to_json.html_safe %>;
</script>
6 changes: 5 additions & 1 deletion app/views/shared/_project_header.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<div class="mt-3">
<h1><%= Project.model_name.human %>: <%= project.title %></h1>
</div>

<div class="nav-scroller py-1 mb-3 border-bottom">
<nav id="project-navbar" class="nav nav-underline">
<%= link_to I18n.t(:details),
Expand All @@ -28,6 +27,11 @@
class: "nav-item nav-link link-body-emphasis
#{'active' if request.path.include?('/members') ||
request.path.include?('/user_roles') }" %>
<%= link_to t('forum.title'),
project_forum_path(project),
class: "nav-item nav-link link-body-emphasis
#{'active' if request.path.include?('/forum')}",
data: { turbo: false } %>
<% if project.leader?(current_user) %>
<%= link_to t(:search_users_btn),
search_project_portfoliorrr_profiles_path(project),
Expand Down
10 changes: 10 additions & 0 deletions config/locales/forum.pt-BR.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pt-BR:
forum:
title: Fórum
forums:
not_contributor: Você não é um colaborador desse projeto
search: Pesquisar
search_posts: Busque por postagens
post: Postar
posted_in: Postado há %{time}
no_posts: Não existem postagens.
14 changes: 14 additions & 0 deletions config/locales/models/post.pt-BR.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pt-BR:
activerecord:
models:
post:
one: Postagem
other: Postagens
attributes:
post:
title: Título
body: Corpo
posts:
not_contributor: Você não é um colaborador desse projeto.
posted_now: Postado agora
no_permission: Você não possui permissão.
7 changes: 6 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
resources :user_roles, only: %i[edit update]
resources :proposals, only: %i[index]
resources :calendars, only: %i[index]

get 'forum', to: 'forums#index'

resources :invitations, only: %i[index], to: 'projects#invitations'
end

Expand All @@ -55,7 +58,9 @@

namespace :api do
namespace :v1 do
resources :projects, only: %i[index]
resources :projects, only: %i[index] do
resources :posts, only: %i[create]
end
resources :invitations, only: %i[index update]
resources :proposals, only: %i[create update]
end
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20240212192630_create_posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreatePosts < ActiveRecord::Migration[7.1]
def change
create_table :posts do |t|
t.string :title
t.string :body
t.references :user_role, null: false, foreign_key: true
t.references :project, null: false, foreign_key: true

t.timestamps
end
end
end
15 changes: 14 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,23 @@
status: :accepted,
email: '[email protected]',
message: 'Aceite minha proposta e sua jornada será bem recompensada!')

FactoryBot.create(:post, title: 'Vencer o ginásio de pedra',
body: 'Precisamos evoluir uma Butterfree e usar o ataque confusão para vencer a Ônix',
project: pikachu_project,
user_role: UserRole.find_by(user: brock, project: pikachu_project))

FactoryBot.create(:post, title: 'Capturar um Pokémon lendário',
body: 'Procurar em todos os matos altos por um Mew.',
project: pikachu_project,
user_role: UserRole.find_by(user: brock, project: pikachu_project))

FactoryBot.create(:post, title: 'Vencer a Elite 4',
body: 'Criar um time com 6 Pokémon capazes de vencer qualquer batalha.',
project: pikachu_project,
user_role: UserRole.find_by(user: brock, project: pikachu_project))

FactoryBot.create(:post, title: 'Voltar para casa como campeão',
body: 'Derrotar o Charizard do treinador Leon e me tornar o campeão mundial.',
project: pikachu_project,
user_role: UserRole.find_by(user: brock, project: pikachu_project))
8 changes: 8 additions & 0 deletions spec/factories/posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FactoryBot.define do
factory :post do
title { 'A arte de criar' }
body { 'Estive desenvolvendo um novo método para acelerar a resolução de tarefas do o projeto' }
user_role
project
end
end
Loading

0 comments on commit 8b74bcb

Please sign in to comment.