foreman_content 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/app/assets/javascripts/content/content.js +23 -12
- data/app/assets/javascripts/content/repository.js +19 -0
- data/app/controllers/content/content_views_controller.rb +19 -6
- data/app/controllers/content/products_controller.rb +1 -1
- data/app/controllers/content/repositories_controller.rb +9 -3
- data/app/helpers/content/content_views_helper.rb +24 -4
- data/app/helpers/content/repositories_helper.rb +28 -0
- data/app/models/concerns/content/host_extensions.rb +1 -1
- data/app/models/concerns/content/operatingsystem_extensions.rb +1 -1
- data/app/models/concerns/content/orchestration/pulp.rb +1 -1
- data/app/models/concerns/content/orchestration/pulp/sync.rb +37 -2
- data/app/models/concerns/content/redhat_extensions.rb +19 -3
- data/app/models/concerns/content/repository_common.rb +13 -0
- data/app/models/content/content_view.rb +21 -15
- data/app/models/content/content_view_repository_clone.rb +2 -2
- data/app/models/content/product.rb +1 -1
- data/app/models/content/repository.rb +24 -8
- data/app/models/content/repository/operating_system.rb +11 -2
- data/app/models/content/repository/product.rb +8 -3
- data/app/models/content/repository_clone.rb +5 -10
- data/app/services/content/content_view_factory.rb +46 -25
- data/app/services/content/pulp/repository.rb +13 -0
- data/app/services/content/pulp/repository_sync_history.rb +8 -2
- data/app/views/content/content_views/{_step2.html.erb → _composite.html.erb} +1 -1
- data/app/views/content/content_views/_form.html.erb +17 -14
- data/app/views/content/content_views/index.html.erb +4 -3
- data/app/views/content/content_views/new.html.erb +1 -7
- data/app/views/content/content_views/show.erb +22 -0
- data/app/views/content/products/_form.html.erb +3 -9
- data/app/views/content/repositories/_fields.html.erb +9 -0
- data/app/views/content/repositories/_os_form.html.erb +6 -11
- data/app/views/content/repositories/_product_form.html.erb +7 -11
- data/app/views/content/repositories/_repository.html.erb +4 -0
- data/app/views/content/repositories/_sync_schedule.erb +10 -0
- data/app/views/content/repositories/edit.html.erb +2 -0
- data/app/views/content/repositories/index.html.erb +14 -16
- data/app/views/content/repositories/new.html.erb +2 -0
- data/app/views/content/repositories/show.html.erb +51 -37
- data/db/migrate/20130807121629_create_content_content_views.rb +1 -1
- data/db/migrate/20130828173006_change_content_view_index_name.rb +10 -0
- data/db/migrate/20130901070945_add_publish_boolean_to_content_repository.rb +6 -0
- data/db/migrate/20130902130445_change_repository_to_polymorphic.rb +42 -0
- data/db/migrate/20130902142326_add_polymorphic_repo_to_content_view_repository_clone.rb +8 -0
- data/lib/content/version.rb +1 -1
- metadata +14 -18
@@ -1,5 +1,5 @@
|
|
1
1
|
class Content::ContentViewRepositoryClone < ActiveRecord::Base
|
2
2
|
belongs_to :content_view
|
3
|
-
belongs_to :
|
4
|
-
validate :content_view_id, :
|
3
|
+
belongs_to :repository, :polymorphic => true
|
4
|
+
validate :content_view_id, :repository_id, :repository_type, :presence => true
|
5
5
|
end
|
@@ -2,24 +2,29 @@ module Content
|
|
2
2
|
class Repository < ActiveRecord::Base
|
3
3
|
include Content::Orchestration::Pulp::Sync
|
4
4
|
include Foreman::STI
|
5
|
+
include Content::RepositoryCommon
|
5
6
|
|
6
7
|
YUM_TYPE = 'yum'
|
7
8
|
KICKSTART_TYPE = 'kickstart'
|
8
9
|
FILE_TYPE = 'iso'
|
9
10
|
TYPES = [YUM_TYPE, KICKSTART_TYPE, FILE_TYPE]
|
10
11
|
|
11
|
-
belongs_to :
|
12
|
-
belongs_to :operatingsystem
|
12
|
+
belongs_to :originator, :polymorphic => true
|
13
13
|
belongs_to :gpg_key
|
14
14
|
belongs_to :architecture
|
15
15
|
has_many :repository_clones
|
16
|
+
has_many :content_view_repository_clones, :dependent => :destroy, :as => :repository
|
16
17
|
|
18
|
+
before_validation :set_originator_type
|
17
19
|
before_destroy EnsureNotUsedBy.new(:repository_clones)
|
18
20
|
|
19
21
|
validates_presence_of :type # can't create this object, only child
|
20
22
|
|
23
|
+
validates_presence_of :originator_id, :originator_type
|
24
|
+
|
21
25
|
validates :name, :presence => true
|
22
|
-
validates_uniqueness_of :name, :scope => [:
|
26
|
+
validates_uniqueness_of :name, :scope => [:originator_type, :originator_id]
|
27
|
+
validates :feed, :presence => true, :uniqueness => true
|
23
28
|
validates_inclusion_of :content_type,
|
24
29
|
:in => TYPES,
|
25
30
|
:allow_blank => false,
|
@@ -27,19 +32,30 @@ module Content
|
|
27
32
|
|
28
33
|
scoped_search :on => [:name, :enabled], :complete_value => :true
|
29
34
|
scoped_search :in => :architecture, :on => :name, :rename => :architecture, :complete_value => :true
|
30
|
-
|
31
|
-
|
35
|
+
belongs_to :search_operatingsystems, :class_name => 'Operatingsystem', :foreign_key => :originator_id,
|
36
|
+
:conditions => '"content_repositories"."originator_type" = "Operatingsystem"'
|
37
|
+
belongs_to :search_products, :class_name => 'Content::Product', :foreign_key => :originator_id,
|
38
|
+
:conditions => '"content_repositories"."originator_type" = "Content::Product"'
|
39
|
+
scoped_search :in => :search_products, :on => :name, :rename => :product,
|
40
|
+
:complete_value => :true, :only_explicit => true
|
41
|
+
scoped_search :in => :search_operatingsystems, :on => :name, :rename => :operatingsystem,
|
42
|
+
:complete_value => :true, :only_explicit => true
|
32
43
|
|
33
44
|
scope :kickstart, where(:content_type => KICKSTART_TYPE)
|
34
45
|
scope :yum, where(:content_type => YUM_TYPE)
|
35
46
|
|
47
|
+
scope :for_content_views, lambda { |ids|
|
48
|
+
joins(:content_view_repository_clones).
|
49
|
+
where('content_content_view_repository_clones' => {:content_view_id => ids})
|
50
|
+
}
|
51
|
+
|
36
52
|
def content_types
|
37
53
|
TYPES
|
38
54
|
end
|
39
55
|
|
40
56
|
# The label is used as a repository label in a yum repo file.
|
41
57
|
def to_label
|
42
|
-
"#{entity_name}
|
58
|
+
"#{entity_name}/#{name}"
|
43
59
|
end
|
44
60
|
|
45
61
|
#inhariters are expected to override this method
|
@@ -47,11 +63,11 @@ module Content
|
|
47
63
|
''
|
48
64
|
end
|
49
65
|
|
50
|
-
def
|
66
|
+
def clone content_view
|
51
67
|
repository_clones.create!(
|
52
68
|
:content_views => [content_view],
|
53
69
|
:name => self.name + "_clone",
|
54
|
-
:relative_path => "content_views/#{
|
70
|
+
:relative_path => "content_views/#{entity_name}/#{name}/#{Foreman.uuid}"
|
55
71
|
)
|
56
72
|
end
|
57
73
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Content
|
2
2
|
class Repository::OperatingSystem < Repository
|
3
|
-
|
4
|
-
validates_presence_of :operatingsystem
|
3
|
+
alias_method :operatingsystem, :originator
|
5
4
|
|
6
5
|
def self.model_name
|
7
6
|
Repository.model_name
|
@@ -10,5 +9,15 @@ module Content
|
|
10
9
|
def entity_name
|
11
10
|
operatingsystem.to_label
|
12
11
|
end
|
12
|
+
|
13
|
+
def description
|
14
|
+
entity_name
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_originator_type
|
20
|
+
self.originator_type ||= 'Operatingsystem'
|
21
|
+
end
|
13
22
|
end
|
14
23
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module Content
|
2
2
|
class Repository::Product < Repository
|
3
|
-
|
3
|
+
alias_method :product, :originator
|
4
4
|
has_many :operatingsystem_repositories, :foreign_key => :repository_id, :dependent => :destroy, :uniq => true
|
5
5
|
has_many :operatingsystems, :through => :operatingsystem_repositories
|
6
|
-
|
7
|
-
validates_presence_of :product
|
6
|
+
delegate :description, :to => :product
|
8
7
|
|
9
8
|
def self.model_name
|
10
9
|
Repository.model_name
|
@@ -17,5 +16,11 @@ module Content
|
|
17
16
|
def entity_name
|
18
17
|
product.name
|
19
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def set_originator_type
|
23
|
+
self.originator_type = 'Content::Product'
|
24
|
+
end
|
20
25
|
end
|
21
26
|
end
|
@@ -1,29 +1,24 @@
|
|
1
1
|
module Content
|
2
2
|
class RepositoryClone < ActiveRecord::Base
|
3
3
|
include Content::Orchestration::Pulp::Clone
|
4
|
-
|
5
|
-
REPO_PREFIX = '/pulp/repos/'
|
4
|
+
include Content::RepositoryCommon
|
6
5
|
|
7
6
|
belongs_to :repository
|
8
|
-
has_many :content_view_repository_clones, :dependent => :destroy
|
7
|
+
has_many :content_view_repository_clones, :dependent => :destroy, :as => :repository
|
9
8
|
has_many :content_views, :through => :content_view_repository_clones
|
10
9
|
before_destroy EnsureNotUsedBy.new(:content_views)
|
11
10
|
|
12
11
|
attr_accessible :description, :last_published, :name, :pulp_id, :relative_path, :status, :content_views
|
13
12
|
validate :relative_path, :repository_id, :presence => true
|
14
13
|
|
15
|
-
delegate :content_type, :architecture, :unprotected, :gpg_key, :product, :to => :repository
|
14
|
+
delegate :content_type, :architecture, :unprotected, :gpg_key, :product, :operatingsystem, :enabled, :to => :repository
|
16
15
|
|
17
16
|
scope :for_content_views, lambda { |ids|
|
18
17
|
joins(:content_view_repository_clones).
|
19
18
|
where('content_content_view_repository_clones' => {:content_view_id => ids})
|
20
19
|
}
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
scheme = (unprotected ? 'http' : 'https')
|
25
|
-
port = (pulp_url.port == 443 || pulp_url.port == 80 ? "" : ":#{pulp_url.port}")
|
26
|
-
"#{scheme}://#{pulp_url.host}#{port}#{REPO_PREFIX}#{relative_path}"
|
27
|
-
end
|
21
|
+
default_scope { includes(:repository) }
|
22
|
+
|
28
23
|
end
|
29
24
|
end
|
@@ -1,32 +1,11 @@
|
|
1
1
|
module Content
|
2
2
|
class ContentViewFactory
|
3
3
|
include ActiveModel::Conversion
|
4
|
-
|
4
|
+
include ActiveModel::Validations
|
5
|
+
extend ActiveModel::Naming
|
5
6
|
|
6
|
-
attr_accessor :
|
7
|
-
|
8
|
-
def self.create_product_content_view(product_id)
|
9
|
-
product = Product.find_by_id(product_id)
|
10
|
-
ContentView.new(:source_repositories => product.repositories, :originator => product)
|
11
|
-
end
|
12
|
-
|
13
|
-
# create a content view of an operating system
|
14
|
-
def self.create_os_content_view(operatingsystem_id)
|
15
|
-
os = Operatingsystem.find_by_id(operatingsystem_id)
|
16
|
-
ContentView.new(:source_repositories => os.repositories, :originator => os)
|
17
|
-
end
|
18
|
-
|
19
|
-
# create a composite content view of a hostgroup (the hostgroup may have a list of products) and a parent
|
20
|
-
# content view. The parent content view is one of the hostgroup parent content views.
|
21
|
-
# A hostgroup may have number of content views representing different versions of that hostgroup content.
|
22
|
-
def self.create_composite_content_view(options = {})
|
23
|
-
factory = new(options)
|
24
|
-
hostgroup = Hostgroup.find_by_id(factory.originator_id)
|
25
|
-
clone_ids = Content::RepositoryClone.for_content_views([factory.product_cv, factory.os_cv]).
|
26
|
-
pluck(:id)
|
27
|
-
ContentView.new(:source_repositories=> [], :originator => hostgroup,
|
28
|
-
:repository_clone_ids => clone_ids, :parent_id => factory.parent_cv)
|
29
|
-
end
|
7
|
+
attr_accessor :originator_type, :originator_id, :parent_cv, :product_cv, :os_cv, :source_repositories
|
8
|
+
validates_presence_of :originator_type, :originator_id
|
30
9
|
|
31
10
|
def initialize(attributes = {})
|
32
11
|
attributes.each do |name, value|
|
@@ -37,5 +16,47 @@ module Content
|
|
37
16
|
def persisted?
|
38
17
|
false
|
39
18
|
end
|
19
|
+
|
20
|
+
def content_view
|
21
|
+
case originator_type
|
22
|
+
when 'Hostgroup'
|
23
|
+
create_composite_content_view
|
24
|
+
else
|
25
|
+
ContentView.new(:repository_ids_to_clone => originator.repositories, :originator => originator)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def repositories
|
30
|
+
originator.repositories
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def originator
|
36
|
+
originator ||= case originator_type
|
37
|
+
when 'Content::Product'
|
38
|
+
Product.find(originator_id)
|
39
|
+
when 'Operatingsystem'
|
40
|
+
Operatingsystem.find(originator_id)
|
41
|
+
when 'Hostgroup'
|
42
|
+
Hostgroup.find(originator_id)
|
43
|
+
else
|
44
|
+
raise _('Unknown type')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# create a composite content view of a hostgroup (the hostgroup may have a list of products) and a parent
|
49
|
+
# content view. The parent content view is one of the hostgroup parent content views.
|
50
|
+
# A hostgroup may have number of content views representing different versions of that hostgroup content.
|
51
|
+
def create_composite_content_view
|
52
|
+
clone_ids = Content::RepositoryClone.for_content_views([product_cv, os_cv]).pluck(:id)
|
53
|
+
source_ids = Content::Repository.for_content_views([product_cv, os_cv]).pluck(:id)
|
54
|
+
ContentView.new(:originator => originator,
|
55
|
+
:repository_clone_ids => clone_ids,
|
56
|
+
:repository_source_ids => source_ids,
|
57
|
+
:parent_id => parent_cv)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
40
61
|
end
|
41
62
|
end
|
@@ -126,6 +126,19 @@ class Content::Pulp::Repository
|
|
126
126
|
true
|
127
127
|
end
|
128
128
|
|
129
|
+
def sync_schedule=(schedule)
|
130
|
+
type = Runcible::Extensions::YumImporter::ID
|
131
|
+
if schedule.present?
|
132
|
+
Runcible::Resources::RepositorySchedule.create(pulp_id, type, schedule)
|
133
|
+
else
|
134
|
+
Runcible::Extensions::Repository.remove_schedules(pulp_id, type)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def sync_schedule
|
139
|
+
Runcible::Resources::RepositorySchedule.list(pulp_id, Runcible::Extensions::YumImporter::ID)
|
140
|
+
end
|
141
|
+
|
129
142
|
private
|
130
143
|
|
131
144
|
def create_repository pulp_distributors = []
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Content::Pulp::RepositorySyncHistory
|
2
|
-
attr_reader :exception, :removed_count, :started, :completed,
|
2
|
+
attr_reader :exception, :removed_count, :started, :completed,
|
3
3
|
:error_message, :added_count, :updated_count, :details, :result
|
4
4
|
|
5
5
|
def initialize(attrs)
|
@@ -12,7 +12,7 @@ class Content::Pulp::RepositorySyncHistory
|
|
12
12
|
{
|
13
13
|
:comps => summary[:time_total_sec],
|
14
14
|
:errata => summary[:errata_time_total_sec],
|
15
|
-
:packages => summary[:packages][:time_total_sec]
|
15
|
+
:packages => (summary[:packages][:time_total_sec] rescue 0)
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
@@ -32,4 +32,10 @@ class Content::Pulp::RepositorySyncHistory
|
|
32
32
|
}
|
33
33
|
end
|
34
34
|
|
35
|
+
private
|
36
|
+
|
37
|
+
def summary
|
38
|
+
@summary ||= Hash.new(0)
|
39
|
+
end
|
40
|
+
|
35
41
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= wizard_header 2, _("Select source type"), _("Select content"), _("Create") %>
|
2
|
-
<%= form_for
|
2
|
+
<%= form_for @factory, :url => hash_for_new_content_view_path, :class => 'form-horizontal well', :method => :get do |f| %>
|
3
3
|
<%= f.hidden_field :originator_id, :value => @hostgroup.id %>
|
4
4
|
<%= f.hidden_field :originator_type, :value => @hostgroup.class.name %>
|
5
5
|
<%= select_f f, :parent_cv, @hostgroup.parent.try(:content_views) || [], "id", "name",
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<%= wizard_header 2, _('Select source type'), _('Select content'), _('Create') %>
|
2
|
+
|
1
3
|
<%= form_for @content_view, :url => (@content_view.new_record? ? content_views_path : content_view_path(@content_view)) do |f| %>
|
2
4
|
<%= base_errors_for @content_view %>
|
3
5
|
|
@@ -11,30 +13,31 @@
|
|
11
13
|
<%= text_f f, :name, :value => @content_view.to_label %>
|
12
14
|
|
13
15
|
<% if @content_view.new_record? %>
|
14
|
-
<% @content_view.source_repositories.each do |repo| %>
|
15
|
-
<%= f.hidden_field :source_repositories, :multiple => true, :value => repo.id %>
|
16
|
-
<% end if @content_view.source_repositories %>
|
17
|
-
<% @content_view.repository_clones.each do |repo| %>
|
18
|
-
<%= f.hidden_field :repository_clone_ids, :multiple => true, :value => repo.id %>
|
19
|
-
<% end if @content_view.repository_clones %>
|
20
|
-
|
21
16
|
<%= f.hidden_field :originator_id, :value => @content_view.originator_id %>
|
22
17
|
<%= f.hidden_field :originator_type, :value => @content_view.originator_type %>
|
23
18
|
<% end %>
|
24
19
|
|
25
20
|
<table class="table table-bordered">
|
26
21
|
<tr>
|
22
|
+
<th></th>
|
27
23
|
<th><%= _("Name") %></th>
|
28
24
|
<th><%= _("State") %></th>
|
29
|
-
<th><%= _(
|
25
|
+
<th><%= f.object.kind_of?(Content::Repository) ? _('Last Sync') : _('Last Publish') %></th>
|
30
26
|
<th><%= _("Content type") %></th>
|
31
27
|
</tr>
|
32
|
-
<% repositories
|
33
|
-
<tr>
|
34
|
-
<td
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
<% repositories.each do |repository| %>
|
29
|
+
<tr class='repository_selection'>
|
30
|
+
<td>
|
31
|
+
<% if @content_view.new_record? %>
|
32
|
+
<%= check_box_tag nil, repository.id, true %>
|
33
|
+
<%= f.hidden_field :repository_ids_to_clone, :value => repository.id, :multiple => true, :id => "clone-#{repository.id}",
|
34
|
+
:disabled => true %>
|
35
|
+
<%= f.hidden_field :repository_source_ids, :value => repository.id, :multiple => true, :id => "latest-#{repository.id}",
|
36
|
+
:disabled => true %>
|
37
|
+
<%= select_tag(nil, options_for_type_selection(repository), {:class => 'cv-repo-selection span2', :id => "select-#{repository.id}"}) %>
|
38
|
+
<% end %>
|
39
|
+
</td>
|
40
|
+
<%= render :partial => 'content/repositories/repository', :locals => {:repository => repository} %>
|
38
41
|
</tr>
|
39
42
|
<% end %>
|
40
43
|
</table>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<% title_actions select_action_button( _('New content view'),
|
3
3
|
display_link_if_authorized(_("Product view"), hash_for_new_content_view_path(:type=>'product')),
|
4
4
|
display_link_if_authorized(_("Operating system view"), hash_for_new_content_view_path(:type=>'operatingsystem')),
|
5
|
-
display_link_if_authorized(_("
|
5
|
+
display_link_if_authorized(_("Composite hostgroup view"), hash_for_new_content_view_path(:type=>'hostgroup'))) %>
|
6
6
|
|
7
7
|
|
8
8
|
<table class="table table-bordered table-striped">
|
@@ -14,11 +14,12 @@
|
|
14
14
|
</tr>
|
15
15
|
<% @content_views.each do |content_view| %>
|
16
16
|
<tr>
|
17
|
-
<td><%= link_to_if_authorized(h(content_view.name),
|
17
|
+
<td><%= link_to_if_authorized(h(content_view.name), hash_for_content_view_path(content_view)) %></td>
|
18
18
|
<td><%= @counter[content_view.id] || '0' %></td>
|
19
19
|
<td><%= _("%s ago") % time_ago_in_words(content_view.created_at) %></td>
|
20
20
|
<td><%= action_buttons(
|
21
|
-
|
21
|
+
display_link_if_authorized(_("Edit"), hash_for_edit_content_view_path(content_view)),
|
22
|
+
display_delete_if_authorized(hash_for_content_view_path(content_view), :confirm => "Delete #{content_view}?")
|
22
23
|
)%></td>
|
23
24
|
</tr>
|
24
25
|
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% title @content_view.to_label %>
|
2
|
+
|
3
|
+
<%= title_actions(button_group(
|
4
|
+
link_to_if_authorized(_("Edit"), hash_for_edit_content_view_path(@content_view)),
|
5
|
+
display_delete_if_authorized(hash_for_content_view_path(@content_view), :class => 'btn-danger', :confirm => "Delete #{@content_view.name}?")
|
6
|
+
)) %>
|
7
|
+
|
8
|
+
<h3><%= _('Repositories') %></h3>
|
9
|
+
<table class="table table-bordered table-striped">
|
10
|
+
<tr>
|
11
|
+
<th><%= sort :name, :as => s_("Name") %></th>
|
12
|
+
<th><%= _("State") %></th>
|
13
|
+
<th><%= _("Last sync status") %></th>
|
14
|
+
<th><%= _("Content type") %></th>
|
15
|
+
</tr>
|
16
|
+
<% @content_view.repository_clones.each do |repository| %>
|
17
|
+
<tr>
|
18
|
+
<%= render :partial => 'content/repositories/repository', :locals => { :repository => repository } %>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</table>
|
22
|
+
|
@@ -1,15 +1,9 @@
|
|
1
1
|
<%= javascript 'content/content.js' %>
|
2
2
|
<%= form_for @product, :url => (@product.new_record? ? products_path : product_path(@product)) do |f| %>
|
3
3
|
<%= base_errors_for @product %>
|
4
|
-
<ul class="nav nav-tabs" data-tabs="tabs">
|
5
|
-
<li class="active"><a href="#primary" data-toggle="tab"><%= _("Product") %></a></li>
|
6
|
-
</ul>
|
7
|
-
<div class="tab-content">
|
8
|
-
<div class="tab-pane active" id="primary">
|
9
|
-
<%= text_f f, :name %>
|
10
|
-
<%= textarea_f f, :description, :class => "input-xlarge" , :rows=> '3' %>
|
11
|
-
</div>
|
12
4
|
|
13
|
-
|
5
|
+
<%= text_f f, :name %>
|
6
|
+
<%= textarea_f f, :description, :class => "input-xlarge", :rows => '3' %>
|
7
|
+
|
14
8
|
<%= submit_or_cancel f %>
|
15
9
|
<% end %>
|