homeland 0.0.9 → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -0
- data/README.md +139 -43
- data/Rakefile +23 -0
- data/app/assets/javascripts/homeland/application.coffee +31 -0
- data/app/assets/javascripts/homeland/bootstrap.min.js +7 -0
- data/{lib/generators/homeland/install/templates/javascripts → app/assets/javascripts/homeland}/jquery.timeago.js +13 -13
- data/app/assets/javascripts/homeland/tether.min.js +1 -0
- data/app/assets/stylesheets/homeland/application.scss +114 -0
- data/app/assets/stylesheets/homeland/bootstrap-theme.scss +165 -0
- data/app/assets/stylesheets/homeland/bootstrap.min.css +5 -0
- data/app/assets/stylesheets/homeland/markdown.scss +13 -0
- data/app/assets/stylesheets/homeland/tether.min.css +1 -0
- data/app/controllers/homeland/application_controller.rb +37 -12
- data/app/controllers/homeland/replies_controller.rb +25 -11
- data/app/controllers/homeland/topics_controller.rb +50 -58
- data/app/helpers/homeland/application_helper.rb +45 -13
- data/app/models/homeland/concerns/markdown_body.rb +17 -0
- data/app/models/homeland/concerns/pagination.rb +14 -0
- data/app/models/homeland/concerns/soft_delete.rb +29 -0
- data/app/models/homeland/concerns/user_methods.rb +23 -0
- data/app/models/homeland/node.rb +10 -25
- data/app/models/homeland/reply.rb +16 -17
- data/app/models/homeland/topic.rb +19 -29
- data/app/views/homeland/replies/_reply.html.erb +35 -0
- data/app/views/homeland/replies/edit.html.erb +17 -27
- data/app/views/homeland/shared/_error_messages.html.erb +2 -4
- data/app/views/homeland/topics/_form.html.erb +21 -24
- data/app/views/homeland/topics/_node_info.html.erb +9 -0
- data/app/views/homeland/topics/_reply_form.html.erb +16 -0
- data/app/views/homeland/topics/_topic.html.erb +17 -26
- data/app/views/homeland/topics/edit.html.erb +6 -10
- data/app/views/homeland/topics/index.html.erb +28 -51
- data/app/views/homeland/topics/new.html.erb +5 -10
- data/app/views/homeland/topics/show.html.erb +16 -89
- data/app/views/layouts/homeland/application.html.erb +42 -0
- data/config/locales/homeland.en.yml +40 -0
- data/config/locales/homeland.zh-CN.yml +8 -0
- data/config/routes.rb +6 -8
- data/db/migrate/20160321125035_create_homeland_nodes.rb +15 -0
- data/db/migrate/20160321125610_create_homeland_topics.rb +25 -0
- data/db/migrate/20160321125920_create_homeland_replies.rb +16 -0
- data/db/migrate/20160322062228_add_reply_to_id_to_replies.rb +7 -0
- data/lib/generators/homeland/controllers_generator.rb +14 -0
- data/lib/generators/homeland/i18n_generator.rb +22 -0
- data/lib/generators/homeland/install_generator.rb +8 -54
- data/lib/generators/homeland/templates/config/initializers/homeland.rb +34 -0
- data/lib/generators/homeland/views_generator.rb +3 -10
- data/lib/homeland.rb +29 -3
- data/lib/homeland/action_view/will_paginate.rb +38 -0
- data/lib/homeland/configuration.rb +66 -0
- data/lib/homeland/engine.rb +4 -27
- data/lib/homeland/markup.rb +17 -0
- data/lib/homeland/markup/base.rb +11 -0
- data/lib/homeland/markup/html.rb +12 -0
- data/lib/homeland/markup/markdown.rb +17 -0
- data/lib/homeland/markup/simple.rb +14 -0
- data/lib/homeland/version.rb +3 -0
- data/lib/tasks/homeland_tasks.rake +4 -0
- metadata +119 -38
- data/Changelogs.md +0 -29
- data/app/assets/images/reply.png +0 -0
- data/app/assets/javascripts/homeland.coffee +0 -51
- data/app/assets/stylesheets/homeland.scss +0 -100
- data/app/helpers/homeland/topics_helper.rb +0 -14
- data/app/models/homeland/section.rb +0 -21
- data/app/views/homeland/topics/_base.html.erb +0 -4
- data/app/views/homeland/topics/_sidebar.html.erb +0 -49
- data/app/views/homeland/topics/feed.builder +0 -20
- data/lib/generators/homeland/install/templates/images/jquery.chosen.png +0 -0
- data/lib/generators/homeland/install/templates/initializer.rb +0 -8
- data/lib/generators/homeland/install/templates/javascripts/jquery.chosen.js +0 -898
- data/lib/generators/homeland/install/templates/javascripts/jquery.hotkeys.js +0 -99
- data/lib/generators/homeland/install/templates/locales/homeland.zh-CN.yml +0 -14
- data/lib/generators/homeland/install/templates/stylesheets/jquery.chosen.scss +0 -367
- data/lib/homeland/setting.rb +0 -37
@@ -1,10 +1,11 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
module Homeland
|
3
2
|
module ApplicationHelper
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
DEFAULT_AVATAR = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAMAAAAJixmgAAAAFVBMVEWkpKSnp6eqqqq3t7fS0tLV1dXZ2dmshcKEAAAAtklEQVR4Ae3XsRGAAAjAQFRk/5HtqaTz5H+DlInvAQAAAAAAAAAAAAAAAAAAAACymiveO6o7BQsWLFiwYMGCBS8PFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBc4IFCxYsWLBgwYIFC14ZfOeAPRQ8IliwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQv+JQAAAAAAAAAAAAAAAAAAAOAB4KJfdHmj+kwAAAAASUVORK5CYII='
|
4
|
+
|
5
|
+
def render_errors(target)
|
6
|
+
if target.errors.present?
|
7
|
+
render partial: '/homeland/shared/error_messages', locals: { target: target }
|
8
|
+
end
|
8
9
|
end
|
9
10
|
|
10
11
|
def timeago(time, options = {})
|
@@ -12,16 +13,47 @@ module Homeland
|
|
12
13
|
content_tag(:abbr, time.to_s, options.merge(:title => time.getutc.iso8601)) if time
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
return
|
17
|
-
|
16
|
+
def node_tag(node)
|
17
|
+
return '' if node.blank?
|
18
|
+
|
19
|
+
label = [node.badge_html, content_tag(:span, node.name, class: 'name')].join(' ')
|
20
|
+
|
21
|
+
link_to raw(label), homeland.node_topics_path(node.id), class: 'node'
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
21
|
-
return
|
22
|
-
|
23
|
-
|
24
|
+
def user_name_tag(obj)
|
25
|
+
return '' if obj.blank?
|
26
|
+
return '' if obj.user_name.blank?
|
27
|
+
|
28
|
+
link_to obj.user_name, obj.user_profile_url, class: 'user-name'
|
24
29
|
end
|
25
30
|
|
31
|
+
def user_avatar_tag(obj, opts = {})
|
32
|
+
default = image_tag(DEFAULT_AVATAR, class: 'avatar media-object')
|
33
|
+
return default if obj.blank?
|
34
|
+
return default if obj.user.blank?
|
35
|
+
|
36
|
+
if obj.user_avatar_url == nil
|
37
|
+
img = default
|
38
|
+
else
|
39
|
+
img = image_tag(obj.user_avatar_url, class: 'avatar media-object')
|
40
|
+
end
|
41
|
+
|
42
|
+
link_to img, obj.user_profile_url, title: obj.user_name, class: 'user-avatar'
|
43
|
+
end
|
44
|
+
|
45
|
+
def notice_message
|
46
|
+
flash_messages = []
|
47
|
+
|
48
|
+
flash.each do |type, message|
|
49
|
+
type = :danger
|
50
|
+
type = :success if type.to_sym == :notice
|
51
|
+
close_button = raw %(<button type="button" class="close" data-dismiss="alert">×</button>)
|
52
|
+
text = content_tag(:div, close_button + message, class: "alert alert-dismissible alert-#{type}")
|
53
|
+
flash_messages << text if message
|
54
|
+
end
|
55
|
+
|
56
|
+
flash_messages.join("\n").html_safe
|
57
|
+
end
|
26
58
|
end
|
27
|
-
end
|
59
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Homeland
|
2
|
+
module Concerns
|
3
|
+
module MarkdownBody
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_save :render_markup
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_markup
|
11
|
+
if self.body_changed?
|
12
|
+
self.body_html = Homeland::Markup.render(self.body)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Homeland
|
2
|
+
module Concerns
|
3
|
+
module SoftDelete
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
default_scope -> { where(deleted_at: nil) }
|
8
|
+
|
9
|
+
alias_method :destroy!, :destroy
|
10
|
+
end
|
11
|
+
|
12
|
+
def destroy
|
13
|
+
run_callbacks(:destroy) do
|
14
|
+
if persisted?
|
15
|
+
t = Time.now.utc
|
16
|
+
update_columns(deleted_at: t, updated_at: t)
|
17
|
+
end
|
18
|
+
|
19
|
+
@destroyed = true
|
20
|
+
end
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def deleted?
|
25
|
+
deleted_at.present?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Homeland
|
2
|
+
module Concerns
|
3
|
+
module UserMethods
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
end
|
8
|
+
|
9
|
+
%w(user_name user_avatar_url user_profile_url).each do |method|
|
10
|
+
define_method(method) do
|
11
|
+
user_method = Homeland.config.send([method, "method"].join("_"))
|
12
|
+
return nil if user_method.blank?
|
13
|
+
return nil if self.user.blank?
|
14
|
+
self.user.send(user_method)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def user_admin?
|
19
|
+
@user_admin ||= self.user && self.user.send(Homeland.config.user_admin_method) || false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/app/models/homeland/node.rb
CHANGED
@@ -1,31 +1,16 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
module Homeland
|
3
|
-
class Node
|
4
|
-
|
5
|
-
|
2
|
+
class Node < ActiveRecord::Base
|
3
|
+
validates :name, :description, presence: true
|
4
|
+
validates :name, uniqueness: true
|
6
5
|
|
7
|
-
|
8
|
-
field :summary
|
9
|
-
field :sort, :type => Integer, :default => 0
|
10
|
-
field :topics_count, :type => Integer, :default => 0
|
6
|
+
has_many :topics, class_name: 'Homeland::Topic'
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
validates_presence_of :name, :summary
|
16
|
-
validates_uniqueness_of :name
|
17
|
-
|
18
|
-
index :topics_count => 1
|
19
|
-
index :sort => -1
|
20
|
-
|
21
|
-
scope :hots, desc(:topics_count)
|
22
|
-
scope :sorted, desc(:sort)
|
8
|
+
def badge_color
|
9
|
+
self.color || '#AAA'
|
10
|
+
end
|
23
11
|
|
24
|
-
|
25
|
-
|
26
|
-
Rails.cache.fetch("node:node_collection:#{CacheVersion.section_node_updated_at}") do
|
27
|
-
Node.all.collect { |n| [n.name,n.id] }
|
28
|
-
end
|
12
|
+
def badge_html
|
13
|
+
%(<i class="node-badge" style="background: #{self.badge_color};"></i>)
|
29
14
|
end
|
30
15
|
end
|
31
|
-
end
|
16
|
+
end
|
@@ -1,29 +1,28 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
module Homeland
|
3
|
-
class Reply
|
4
|
-
include
|
5
|
-
include
|
6
|
-
include
|
2
|
+
class Reply < ActiveRecord::Base
|
3
|
+
include Homeland::Concerns::SoftDelete
|
4
|
+
include Homeland::Concerns::MarkdownBody
|
5
|
+
include Homeland::Concerns::UserMethods
|
6
|
+
include Homeland::Concerns::Pagination
|
7
7
|
|
8
|
-
|
8
|
+
belongs_to :user, class_name: Homeland.config.user_class.to_s
|
9
|
+
belongs_to :topic, class_name: 'Homeland::Topic'
|
10
|
+
belongs_to :reply_to, class_name: 'Homeland::Reply'
|
9
11
|
|
10
|
-
|
11
|
-
belongs_to :topic, :inverse_of => :replies, :class_name => "Homeland::Topic"
|
12
|
+
has_many :replies, class_name: "Homeland::Reply", foreign_key: "reply_to_id"
|
12
13
|
|
13
|
-
|
14
|
+
validates :user_id, :body, :topic_id, presence: true
|
14
15
|
|
15
|
-
|
16
|
-
index :user_id => 1
|
16
|
+
scope :recent, -> { order('id desc') }
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
after_create :update_parent_last_replied
|
22
|
-
def update_parent_last_replied
|
18
|
+
after_commit :update_topic_last_reply_at, on: [:create, :update]
|
19
|
+
def update_topic_last_reply_at
|
20
|
+
return if self.topic.blank?
|
23
21
|
self.topic.replied_at = Time.now
|
22
|
+
self.topic.last_active_mark = Time.now.to_i
|
24
23
|
self.topic.last_reply_user_id = self.user_id
|
25
24
|
self.topic.replies_count = self.topic.replies.count
|
26
25
|
self.topic.save
|
27
26
|
end
|
28
27
|
end
|
29
|
-
end
|
28
|
+
end
|
@@ -1,38 +1,28 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
module Homeland
|
3
|
-
class Topic
|
4
|
-
include
|
5
|
-
include
|
6
|
-
include
|
2
|
+
class Topic < ActiveRecord::Base
|
3
|
+
include Homeland::Concerns::SoftDelete
|
4
|
+
include Homeland::Concerns::MarkdownBody
|
5
|
+
include Homeland::Concerns::UserMethods
|
6
|
+
include Homeland::Concerns::Pagination
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
belongs_to :user, class_name: Homeland.config.user_class.to_s
|
9
|
+
belongs_to :last_reply_user, class_name: Homeland.config.user_class.to_s
|
10
|
+
belongs_to :node, class_name: 'Homeland::Node'
|
11
|
+
has_many :replies, class_name: 'Homeland::Reply'
|
12
12
|
|
13
|
-
|
14
|
-
belongs_to :node, :class_name => "Homeland::Node"
|
15
|
-
belongs_to :last_reply_user, :class_name => Homeland.user_class.to_s
|
16
|
-
has_many :replies, :class_name => "Homeland::Reply"
|
13
|
+
validates :user_id, :title, :body, :node_id, presence: true
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
scope :recent, -> { order('id desc') }
|
16
|
+
scope :latest, -> { order('last_active_mark desc, id desc') }
|
17
|
+
scope :features, -> { where('replies_count >= 20').latest }
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# scopes
|
26
|
-
scope :last_actived, desc(:replied_at).desc(:_id)
|
27
|
-
scope :recent, desc(:_id)
|
28
|
-
before_save :set_replied_at
|
29
|
-
def set_replied_at
|
30
|
-
self.replied_at = Time.now
|
19
|
+
before_create :set_last_active_mark
|
20
|
+
def set_last_active_mark
|
21
|
+
self.last_active_mark = Time.now.to_i
|
31
22
|
end
|
32
23
|
|
33
|
-
def
|
34
|
-
|
35
|
-
self.node.name
|
24
|
+
def activity_at
|
25
|
+
self.replied_at || self.updated_at || self.created_at
|
36
26
|
end
|
37
27
|
end
|
38
|
-
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<%
|
2
|
+
is_reply = reply.respond_to?(:reply_to_id)
|
3
|
+
%>
|
4
|
+
<div class="reply media" id="reply-<%= reply.id %>" data-id="<%= reply.id %>">
|
5
|
+
<div class="media-left">
|
6
|
+
<%= user_avatar_tag(reply) %>
|
7
|
+
</div>
|
8
|
+
<div class="media-body">
|
9
|
+
<div class="media-heading">
|
10
|
+
<%= user_name_tag(reply) %>
|
11
|
+
|
12
|
+
<span class="date pull-xs-right"><i class="fa fa-clock-o"></i> <%= timeago reply.created_at %></span>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="markdown">
|
16
|
+
<%= raw reply.body_html %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="media-footer clearfix">
|
20
|
+
<% if owner?(reply) %>
|
21
|
+
<a href="<%= is_reply ? edit_reply_path(reply) : edit_topic_path(reply) %>" class="btn-opt"><i class="fa fa-pencil"></i></a>
|
22
|
+
<a href="<%= is_reply ? reply_path(reply) : topic_path(reply) %>" data-method="DELETE" data-confirm="<%= t('homeland.are_you_sure_to_delete') %>" class="btn-opt"><i class="fa fa-trash"></i></a>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% if is_reply && reply.reply_to_id %>
|
26
|
+
<a href="#reply-<%= reply.reply_to_id %>" title="<%= t('homeland.topics.reply_to') %>" class="btn-opt"><i class="fa fa-quote-left"></i></a>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<span class="pull-xs-right">
|
30
|
+
<a href="<%= homeland.topic_path(@topic, anchor: "reply-#{reply.id}") %>" class="btn-opt anchor"><i class="fa fa-link"></i></a>
|
31
|
+
<a href="#" class="btn-opt" data-action="reply" data-reply-id="<%= is_reply ? reply.id : '' %>"><i class="fa fa-reply"></i> <%= t('homeland.reply') %></a>
|
32
|
+
</span>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
@@ -1,28 +1,18 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
<ol class="breadcrumb">
|
2
|
+
<li><a href="<%= homeland.root_path %>"><%= t('homeland.nav.home') %></a></li>
|
3
|
+
<li><a href="<%= homeland.topic_path(@reply.topic_id) %>" title="<%= @reply.topic.title %>"><%= truncate @reply.topic.title, length: 20 %></a></li>
|
4
|
+
<li class="active"><%= t('homeland.nav.edit') %></li>
|
5
|
+
</ol>
|
6
|
+
<%= form_for(@reply) do |f| %>
|
7
|
+
<%= render_errors @reply %>
|
8
|
+
|
9
|
+
<div class="form-group">
|
10
|
+
<%= f.label :body %>
|
11
|
+
<%= f.text_area :body, class: "form-control", rows: "10" %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="form-group">
|
15
|
+
<button type="submit" class="btn btn-primary btn-lg" data-disable-with="<%= t('homeland.submiting') %>"><%= t('homeland.submit') %></button>
|
16
|
+
<a href="<%= homeland.topic_path(@reply.topic_id) %>" class="btn btn-lg btn-default"><%= t('homeland.cancel') %></a>
|
8
17
|
</div>
|
9
|
-
|
10
|
-
<div class="content">
|
11
|
-
<div class="box">
|
12
|
-
<%= form_for(@reply) do |f| %>
|
13
|
-
<fieldset>
|
14
|
-
<legend>修改回帖</legend>
|
15
|
-
<%= render "homeland/shared/error_messages", :target => @reply %>
|
16
|
-
<div class="clearfix">
|
17
|
-
<%= f.label :body %>
|
18
|
-
<div class="input">
|
19
|
-
<%= f.text_area :body, :class => "topic_body_text_area", :rows => "20" %>
|
20
|
-
</div>
|
21
|
-
</div>
|
22
|
-
<div class="actions">
|
23
|
-
<button class="btn primary">保存更新</button>
|
24
|
-
<a href="<%= topic_path(@reply.topic_id) %>" class="btn">取消</a>
|
25
|
-
</div>
|
26
|
-
<% end %>
|
27
|
-
</div>
|
28
|
-
</div>
|
18
|
+
<% end %>
|
@@ -1,7 +1,5 @@
|
|
1
|
-
<% if target.errors.any? %>
|
2
|
-
<div class="alert
|
3
|
-
<a class="close" href="#">×</a>
|
4
|
-
<p><strong>有 <%= target.errors.count %> 处问题导至无法提交:</strong></p>
|
1
|
+
<% if target.errors.any? %>
|
2
|
+
<div class="alert alert-danger">
|
5
3
|
<ul>
|
6
4
|
<% target.errors.full_messages.each do |msg| %>
|
7
5
|
<li><%= msg %></li>
|
@@ -1,26 +1,23 @@
|
|
1
1
|
<%= form_for(@topic) do |f| %>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
<%= f.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
<
|
22
|
-
|
23
|
-
<a href="<%= @topic.id.blank? ? topics_path : topic_path(@topic) %>" class="btn">取消</a>
|
24
|
-
</div>
|
25
|
-
</fieldset>
|
2
|
+
<%= render_errors @topic %>
|
3
|
+
<%= f.hidden_field :node_id %>
|
4
|
+
<div class="form-group">
|
5
|
+
<%= f.label :node %>
|
6
|
+
<%= f.select :node_id, Homeland::Node.all.collect { |n| [n.name, n.id] }, {}, { class: 'form-control' } %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="form-group">
|
10
|
+
<%= f.label :title %>
|
11
|
+
<%= f.text_field :title, class: "form-control" %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="form-group">
|
15
|
+
<%= f.label :body %>
|
16
|
+
<%= f.text_area :body, class: "form-control", rows: "10" %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="form-group">
|
20
|
+
<button type="submit" class="btn btn-primary btn-lg" data-disable-with="<%= t('homeland.submiting') %>"><%= t('homeland.submit') %></button>
|
21
|
+
<a href="<%= @topic.id.blank? ? homeland.topics_path : homeland.topic_path(@topic) %>" class="btn btn-lg btn-default"><%= t('homeland.cancel') %></a>
|
22
|
+
</div>
|
26
23
|
<% end %>
|