dokno 1.1.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -6
  3. data/app/assets/javascripts/dokno.js +67 -31
  4. data/app/assets/stylesheets/dokno/application.css +1 -1
  5. data/app/controllers/dokno/application_controller.rb +1 -1
  6. data/app/controllers/dokno/articles_controller.rb +19 -11
  7. data/app/controllers/dokno/categories_controller.rb +10 -7
  8. data/app/controllers/dokno/pagination_concern.rb +5 -5
  9. data/app/controllers/dokno/user_concern.rb +6 -4
  10. data/app/helpers/dokno/application_helper.rb +1 -1
  11. data/app/models/dokno/application_record.rb +3 -0
  12. data/app/models/dokno/article.rb +91 -42
  13. data/app/models/dokno/category.rb +24 -45
  14. data/app/views/dokno/_article_formatting.html.erb +17 -18
  15. data/app/views/dokno/_article_panel.html.erb +10 -19
  16. data/app/views/dokno/_panel_formatting.html.erb +47 -57
  17. data/app/views/dokno/articles/_article_form.html.erb +49 -10
  18. data/app/views/dokno/articles/show.html.erb +48 -45
  19. data/app/views/dokno/categories/_category_form.html.erb +18 -7
  20. data/app/views/dokno/categories/index.html.erb +59 -40
  21. data/app/views/layouts/dokno/application.html.erb +36 -35
  22. data/app/views/partials/_category_header.html.erb +30 -0
  23. data/app/views/partials/_form_errors.html.erb +0 -1
  24. data/app/views/partials/_logs.html.erb +7 -5
  25. data/app/views/partials/_pagination.html.erb +20 -18
  26. data/config/routes.rb +1 -1
  27. data/db/migrate/20201203190330_baseline.rb +4 -4
  28. data/db/migrate/20201211192306_add_review_due_at_to_articles.rb +6 -0
  29. data/db/migrate/20201213165700_add_starred_to_article.rb +5 -0
  30. data/lib/dokno/config/config.rb +53 -40
  31. data/lib/dokno/engine.rb +5 -5
  32. data/lib/dokno/version.rb +1 -1
  33. data/lib/generators/dokno/templates/config/initializers/dokno.rb +18 -5
  34. metadata +82 -11
@@ -1,41 +1,33 @@
1
1
  module Dokno
2
2
  class Category < ApplicationRecord
3
- belongs_to :parent,
4
- class_name: 'Dokno::Category',
5
- primary_key: 'id',
6
- foreign_key: 'category_id',
7
- optional: true,
8
- inverse_of: :children
9
- has_many :children,
10
- class_name: 'Dokno::Category',
11
- primary_key: 'id',
12
- foreign_key: 'category_id',
13
- dependent: :nullify,
14
- inverse_of: :parent
3
+ belongs_to :parent, class_name: 'Dokno::Category', primary_key: 'id', foreign_key: 'category_id', inverse_of: :children, optional: true
4
+ has_many :children, class_name: 'Dokno::Category', primary_key: 'id', foreign_key: 'category_id', inverse_of: :parent, dependent: :nullify
15
5
 
16
6
  has_and_belongs_to_many :articles
17
7
 
8
+ before_validation :set_code
18
9
  validates :name, :code, presence: true, uniqueness: true
19
10
  validate :circular_parent_check
20
11
 
21
- before_validation :set_code
22
-
23
12
  scope :alpha_order, -> { order(:name) }
24
13
 
25
- # The display breadcrumb for the Category
26
- def breadcrumb
27
- crumbs = [name]
14
+ def breadcrumb(**args)
15
+ crumbs = [(category_link(self, args) unless args[:hide_self])]
28
16
  parent_category_id = category_id
29
17
 
30
18
  loop do
31
19
  break if parent_category_id.blank?
32
20
 
33
- parent_category = self.class.find(parent_category_id)
34
- crumbs.prepend parent_category.name
21
+ parent_category = Category.find(parent_category_id)
22
+ crumbs.prepend category_link(parent_category, args)
35
23
  parent_category_id = parent_category.category_id
36
24
  end
37
25
 
38
- crumbs.join(' > ')
26
+ crumbs.compact.join("&nbsp;&nbsp;>&nbsp;&nbsp;").html_safe
27
+ end
28
+
29
+ def category_link(category, args={})
30
+ %(<a href="#{article_index_path(category.code)}?search_term=#{CGI.escape(args[:search_term].to_s)}&order=#{CGI.escape(args[:order].to_s)}">#{category.name}</a>)
39
31
  end
40
32
 
41
33
  # All Articles in the Category, including all child Categories
@@ -45,18 +37,18 @@ module Dokno
45
37
  .joins(:categories)
46
38
  .where(dokno_categories: { id: self.class.branch(parent_category_id: id).pluck(:id) })
47
39
 
48
- records = records.updated_order if order == :updated
49
- records = records.newest_order if order == :newest
50
- records = records.view_order if order == :views
51
- records = records.alpha_order if order == :alpha
52
-
53
- records
40
+ Article.apply_sort(records, order: order)
54
41
  end
55
42
 
56
43
  def branch
57
44
  self.class.branch(parent_category_id: id)
58
45
  end
59
46
 
47
+ # Used to invalidate the fragment cache of the hierarchical category select options
48
+ def self.cache_key
49
+ [maximum(:updated_at), Article.maximum(:updated_at)].compact.max
50
+ end
51
+
60
52
  # The given Category and all child Categories. Useful for filtering associated articles.
61
53
  def self.branch(parent_category_id:, at_top: true)
62
54
  return if parent_category_id.blank?
@@ -73,26 +65,14 @@ module Dokno
73
65
  categories.flatten
74
66
  end
75
67
 
76
- def self.select_option_markup(selected_category_codes: nil, exclude_category_id: nil, context_category: nil, level: 0)
68
+ def self.select_option_markup(selected_category_codes: nil, context_category: nil, level: 0)
77
69
  return '' if level.positive? && context_category.blank?
78
70
 
79
71
  options = []
80
72
  level_categories = where(category_id: context_category&.id).alpha_order
81
-
82
73
  level_categories.each do |category|
83
- options << option_markup(
84
- category: category,
85
- selected_category_codes: selected_category_codes,
86
- exclude_category_id: exclude_category_id,
87
- level: level
88
- )
89
-
90
- options << select_option_markup(
91
- selected_category_codes: selected_category_codes,
92
- exclude_category_id: exclude_category_id,
93
- context_category: category,
94
- level: (level + 1)
95
- )
74
+ options << option_markup(category: category, selected_category_codes: selected_category_codes, level: level)
75
+ options << select_option_markup(selected_category_codes: selected_category_codes, context_category: category, level: (level + 1))
96
76
  end
97
77
 
98
78
  options.join
@@ -100,11 +80,10 @@ module Dokno
100
80
 
101
81
  private
102
82
 
103
- def self.option_markup(category:, selected_category_codes:, exclude_category_id:, level: 0)
104
- return '' if category.id == exclude_category_id
105
-
83
+ def self.option_markup(category:, selected_category_codes:, level: 0)
106
84
  selected = selected_category_codes&.include?(category.code)
107
- %(<option value="#{category.code}" #{'selected="selected"' if selected}>#{('&nbsp;&nbsp;' * level)}#{category.name}</option>)
85
+ article_count = category.articles_in_branch.size
86
+ %(<option value="#{category.code}" #{'selected="selected"' if selected}>#{('&nbsp;&nbsp;' * level)}#{category.name}#{' (' + article_count.to_s + ')' if article_count.positive?}</option>)
108
87
  end
109
88
 
110
89
  # Never allow setting of parent to self
@@ -1,9 +1,9 @@
1
1
  <style>
2
2
  /* Article formatting */
3
3
  .dokno-article-content-markup {
4
- font-weight: 300;
5
- line-height: 1.75rem;
6
- font-size: 1rem;
4
+ font-weight: 400;
5
+ line-height: 1.75em;
6
+ font-size: 1em;
7
7
  }
8
8
 
9
9
  .dokno-article-content-markup code {
@@ -23,7 +23,7 @@
23
23
  .dokno-article-content-markup ol,
24
24
  .dokno-article-content-markup hr,
25
25
  .dokno-article-content-markup table {
26
- margin-bottom: 1.25rem;
26
+ margin-bottom: 1.25em;
27
27
  }
28
28
 
29
29
  .dokno-article-content-markup h1,
@@ -32,29 +32,28 @@
32
32
  .dokno-article-content-markup h4,
33
33
  .dokno-article-content-markup h5,
34
34
  .dokno-article-content-markup h6 {
35
- margin-bottom: 1.25rem;
35
+ margin-bottom: 1.25em;
36
36
  font-weight: 600;
37
37
  }
38
38
 
39
39
  .dokno-article-content-markup h1 {
40
- font-size: 2rem;
40
+ font-size: 1.625em;
41
41
  }
42
42
 
43
43
  .dokno-article-content-markup h2 {
44
- font-size: 1.625rem;
44
+ font-size: 1.25em;
45
45
  }
46
46
 
47
- .dokno-article-content-markup h3 {
48
- font-size: 1.25rem;
49
- }
50
-
51
- .dokno-article-content-markup h4 {
52
- font-size: 1rem;
47
+ .dokno-article-content-markup h3,
48
+ .dokno-article-content-markup h4,
49
+ .dokno-article-content-markup h5,
50
+ .dokno-article-content-markup h6 {
51
+ font-size: 1em;
53
52
  }
54
53
 
55
54
  .dokno-article-content-markup blockquote {
56
55
  border-left: 4px solid #edf2f7;
57
- padding-left: 1.25rem;
56
+ padding-left: 1.25em;
58
57
  }
59
58
 
60
59
  .dokno-article-content-markup ul,
@@ -76,10 +75,10 @@
76
75
 
77
76
  .dokno-article-content-markup table th,
78
77
  .dokno-article-content-markup table td {
79
- padding-left: 1rem;
80
- padding-right: 1rem;
81
- padding-top: 0.5rem;
82
- padding-bottom: 0.5rem;
78
+ padding-left: 1em;
79
+ padding-right: 1em;
80
+ padding-top: 0.5em;
81
+ padding-bottom: 0.5em;
83
82
  font-weight: normal;
84
83
  }
85
84
 
@@ -13,13 +13,6 @@
13
13
 
14
14
  <!-- Slide-out panel markup -->
15
15
  <div id="dokno-panel-container">
16
- <div id="dokno-panel-close" class="dokno-hidden">
17
- <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="#eee" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x-circle">
18
- <circle cx="12" cy="12" r="10"></circle>
19
- <line x1="15" y1="9" x2="9" y2="15"></line>
20
- <line x1="9" y1="9" x2="15" y2="15"></line>
21
- </svg>
22
- </div>
23
16
  <div id="dokno-panel-title"></div>
24
17
  <div id="dokno-panel-summary"></div>
25
18
  <div id="dokno-panel-markdown" class="dokno-article-content-markup"></div>
@@ -29,10 +22,12 @@
29
22
  <!-- Slide-out panel behavior -->
30
23
  <script>
31
24
  function doknoOpenPanel(slug) {
32
- if (slug == dokno__slug) {
33
- doknoClosePanel();
34
- return true;
35
- }
25
+ if (slug == dokno__slug) { return true; }
26
+
27
+ // Set flag to avoid flicker when closing the panel before opening the panel
28
+ dokno__link_just_clicked = true;
29
+ setTimeout(function() { dokno__link_just_clicked = false; }, 200);
30
+
36
31
  dokno__slug = slug;
37
32
 
38
33
  // Can't use fetch API; IE
@@ -62,9 +57,6 @@
62
57
  dokno__panel.classList.add('open');
63
58
  document.body.classList.add('dokno-no-scroll');
64
59
 
65
- // Reveal fixed close icon
66
- setTimeout(function() { dokno__close.classList.remove('dokno-hidden'); }, 200);
67
-
68
60
  // Close on escape
69
61
  document.addEventListener('keydown', dokno__keydown_listener, false);
70
62
  document.addEventListener('click', dokno__click_listener, false);
@@ -75,7 +67,9 @@
75
67
  }
76
68
 
77
69
  function doknoClosePanel() {
78
- dokno__close.classList.add('dokno-hidden');
70
+ // Just clicked a link to open a panel, so don't close to avoid flicker
71
+ if (dokno__link_just_clicked) { return true; }
72
+
79
73
  dokno__panel.classList.remove('open');
80
74
  document.body.classList.remove('dokno-no-scroll');
81
75
  document.removeEventListener('keydown', dokno__keydown_listener, false);
@@ -98,7 +92,6 @@
98
92
  }
99
93
 
100
94
  const dokno__panel = document.getElementById('dokno-panel-container');
101
- const dokno__close = document.querySelector('div#dokno-panel-close');
102
95
  const dokno__panel_title = document.getElementById('dokno-panel-title');
103
96
  const dokno__panel_summary = document.getElementById('dokno-panel-summary');
104
97
  const dokno__panel_footer = document.getElementById('dokno-panel-footer');
@@ -113,7 +106,5 @@
113
106
  if (!isClickInside) { doknoClosePanel(); }
114
107
  }
115
108
 
116
- dokno__close.onclick = function() { doknoClosePanel(); }
117
-
118
- var dokno__id, dokno__slug;
109
+ var dokno__id, dokno__slug, dokno__link_just_clicked;
119
110
  </script>
@@ -9,87 +9,77 @@
9
9
 
10
10
  div#dokno-panel-container {
11
11
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
12
- font-size: 1rem;
13
- line-height: 1.5rem;
14
- right: -600px;
15
- z-index: 9999;
16
- position: fixed;
17
- top: 0;
18
- bottom: 0;
19
- width: 600px;
20
- max-width: 100vw;
21
- overflow: hidden;
22
- overflow-y: auto;
23
- background-color: #fff;
24
- color: #2d3748;
25
- transition: all .15s ease-in-out;
26
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
12
+ font-size: 1rem !important;
13
+ line-height: 1.5rem !important;
14
+ right: -600px !important;
15
+ z-index: 9999 !important;
16
+ position: fixed !important;
17
+ top: 0 !important;
18
+ bottom: 0 !important;
19
+ width: 600px !important;
20
+ max-width: 100vw !important;
21
+ overflow: hidden !important;
22
+ overflow-y: auto !important;
23
+ background-color: #fff !important;
24
+ color: #2d3748 !important;
25
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) !important;
27
26
  }
28
27
 
29
28
  div#dokno-panel-container.open {
30
- right: 0;
31
- }
32
-
33
- div#dokno-panel-close {
34
- position: fixed;
35
- background-color: transparent;
36
- color: #222;
37
- cursor: pointer;
38
- top: 1.5rem;
39
- right: 2.5rem;
29
+ right: 0 !important;
40
30
  }
41
31
 
42
32
  div#dokno-panel-title {
43
- padding: 2.5rem;
44
- font-size: 2.25rem;
45
- line-height: 2.75rem;
46
- font-weight: 300;
47
- background-color: rgb(42,67,101);
48
- color: #ebf8ff;
33
+ padding: 2.5rem !important;
34
+ font-size: 2.25rem !important;
35
+ line-height: 2.75rem !important;
36
+ font-weight: 600 !important;
37
+ background-color: rgb(42,67,101) !important;
38
+ color: #ebf8ff !important;
49
39
  }
50
40
 
51
41
  div#dokno-panel-title div#article-deprecated-alert {
52
- font-size: 1rem;
53
- line-height: 1.5rem;
54
- padding: 1rem;
55
- margin-bottom: 1rem;
56
- border-top-width: 4px;
57
- border-radius: .25rem;
58
- border-top-style: solid;
59
- border-color: rgb(116,66,16);
60
- background-color: rgb(183,121,31);
61
- color: rgb(255,255,255);
42
+ font-size: 1rem !important;
43
+ line-height: 1.5rem !important;
44
+ padding: 1rem !important;
45
+ margin-bottom: 1rem !important;
46
+ border-top-width: 4px !important;
47
+ border-radius: .25rem !important;
48
+ border-top-style: solid !important;
49
+ border-color: rgb(116,66,16) !important;
50
+ background-color: rgb(183,121,31) !important;
51
+ color: rgb(255,255,255) !important;
62
52
  }
63
53
 
64
54
  div#dokno-panel-title > span,
65
55
  div#dokno-panel-footer > svg {
66
- cursor: pointer;
56
+ cursor: pointer !important;
67
57
  }
68
58
 
69
59
  div#dokno-panel-summary {
70
- font-size: 1.5rem;
71
- line-height: 2.25rem;
72
- padding: 2.5rem;
73
- font-weight: 300;
60
+ font-size: 1.5rem !important;
61
+ line-height: 2.25rem !important;
62
+ padding: 2.5rem !important;
63
+ font-weight: 400 !important;
74
64
  }
75
65
 
76
66
  div#dokno-panel-markdown {
77
- padding: 2.5rem;
78
- background-color: #f7fafc;
67
+ padding: 2.5rem !important;
68
+ background-color: #f7fafc !important;
79
69
  }
80
70
 
81
71
  div#dokno-panel-footer {
82
- text-align: center;
83
- position: relative;
84
- padding: 2.5rem;
85
- color: #999;
86
- background-color: #edf2f7;
87
- font-weight: 300;
88
- font-size: 1rem;
89
- line-height: 1.5rem;
72
+ text-align: center !important;
73
+ position: relative !important;
74
+ padding: 2.5rem !important;
75
+ color: #999 !important;
76
+ background-color: #edf2f7 !important;
77
+ font-weight: 400 !important;
78
+ font-size: 1rem !important;
79
+ line-height: 1.5rem !important;
90
80
  }
91
81
 
92
82
  div#dokno-panel-footer p {
93
- margin: .5rem 0;
83
+ margin: .5rem 0 !important;
94
84
  }
95
85
  </style>
@@ -3,8 +3,31 @@
3
3
  <section class="mb-10">
4
4
 
5
5
  <div class="text-2xl mb-5 text-gray-500"><%= article.persisted? ? 'Edit' : 'New' %> Article</div>
6
- <h1 class="text-4xl mb-5 leading-tight font-light"><%= article.title %></h1>
7
- <hr class="mb-5" />
6
+ <h1 class="text-4xl leading-tight font-light"><%= article.title %></h1>
7
+ <hr class="mt-8 mb-10" />
8
+
9
+ <% if article.up_for_review? %>
10
+ <div class="bg-gray-800 text-gray-100 rounded mb-10">
11
+ <h2 class="bg-gray-900 p-10 rounded-t text-2xl leading-tight font-light">Review for Accuracy / Relevance</h2>
12
+
13
+ <div class="flex p-10">
14
+ <div class="w-1/2 pr-5">
15
+ <div>
16
+ <span class="text-lg font-semibold"><label for="reset_review_date">Reset the next review date?</label></span>
17
+ <input onchange="setReviewForm();" type="checkbox" name="reset_review_date" id="reset_review_date" value="true" class="ml-2 text-lg" <%= "checked='checked'" if @reset_review_date %> />
18
+ </div>
19
+ <div class="text-gray-400">
20
+ <%= article.review_due_days_string %>.
21
+ Check the box above to mark this article as reviewed and reset the next review date to <span class="px-2 py-1 bg-gray-900 rounded text-white font-semibold"><%= "#{Date.today + Dokno.config.article_review_period}" %></span>
22
+ </div>
23
+ </div>
24
+ <div class="w-1/2">
25
+ <div class="text-lg font-semibold"><label for="review_notes">Reviewer Notes</label></div>
26
+ <textarea placeholder="Any review notes here will be added to the change history for this article" name="review_notes" id="review_notes" class="rounded text-xl shadow-inner bg-gray-100 p-3 mt-2 w-full text-gray-900" rows="2"><%= @review_notes %></textarea>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <% end %>
8
31
 
9
32
  <div class="mb-5">
10
33
  <div class="text-lg font-semibold"><label for="slug">Slug</label></div>
@@ -13,9 +36,9 @@
13
36
  </div>
14
37
 
15
38
  <% if Dokno::Category.exists? %>
16
- <div class="mb-5">
17
- <div class="text-lg font-semibold"><label for="category_id"><%= 'Category'.pluralize article.categories.count %></label></div>
18
- <select name="category_code[]" id="category_code" multiple="multiple" size="<%= (cat_count = Dokno::Category.count) <= 4 ? (cat_count + 1).to_s : '5' %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full mt-2 w-full max-w-full">
39
+ <div class="mb-5 w-2/3">
40
+ <div class="text-lg font-semibold"><label for="category_code"><%= 'Category'.pluralize article.categories.count %></label></div>
41
+ <select name="category_code[]" id="category_code" multiple="multiple" size="<%= (cat_count = Dokno::Category.count) <= 9 ? (cat_count + 1).to_s : '10' %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full mt-2 w-full max-w-full">
19
42
  <option></option>
20
43
  <%= Dokno::Category.select_option_markup(selected_category_codes: @category_codes).html_safe %>
21
44
  </select>
@@ -27,7 +50,7 @@
27
50
  </div>
28
51
  <% end %>
29
52
 
30
- <hr class="mb-5" />
53
+ <hr class="my-10" />
31
54
 
32
55
  <div class="mb-5">
33
56
  <div class="text-lg font-semibold"><label for="title">Title</label></div>
@@ -47,16 +70,32 @@
47
70
  <a id="markdown_write_link" href="javascript:;" onclick="writeArticleToggle();" class="float-right hidden"><i data-feather="pen-tool" class="inline"></i> Write</a>
48
71
  <a id="markdown_preview_link" href="javascript:;" onclick="previewArticleToggle();" class="float-right"><i data-feather="eye" class="inline"></i> Preview</a>
49
72
  </div>
50
- <textarea placeholder="Full article content" name="markdown" id="markdown" class="rounded text-xl shadow-inner bg-gray-100 p-3 mt-2 w-full" rows="10"><%= article.persisted? ? article.markdown : (article.markdown.presence || @template) %></textarea>
73
+ <textarea placeholder="Full article content" name="markdown" id="markdown" class="rounded text-xl shadow-inner bg-gray-100 p-3 mt-2 w-full" rows="20"><%= article.persisted? ? article.markdown : (article.markdown.presence || @template) %></textarea>
51
74
  <div id="markdown_preview" class="dokno-article-content-markup hidden text-lg overflow-hidden overflow-y-auto rounded p-10 mt-2 bg-gray-100 shadow-inner"></div>
52
75
  <div class="text-gray-500 mt-2">Detailed documentation of the described topic. Basic HTML &amp; <a target="_blank" href="https://commonmark.org/help/" title="Markdown formatting examples">markdown</a> OK.</div>
53
76
  </div>
54
77
 
55
- <div class="mt-10">
78
+ <div class="mb-5">
79
+ <div>
80
+ <span class="text-lg font-semibold"><label for="starred">Starred article?</label></span>
81
+ <input type="hidden" name="starred" value="false" />
82
+ <input type="checkbox" name="starred" id="starred" value="true" class="ml-2 text-lg" <%= "checked='checked'" if article.starred %> />
83
+ </div>
84
+ <div class="text-gray-400">
85
+ Starred articles are always listed first when browsing.
86
+ </div>
87
+ </div>
88
+
89
+ <hr class="my-10" />
90
+
91
+ <div class="text-right">
92
+ <span class="text-lg mr-5"><a class="no-underline" href="<%= article.persisted? ? article_path(article.slug) : root_path %>">Cancel</a></span>
56
93
  <button type="submit" class="bg-gray-700 text-gray-300 hover:bg-gray-900 hover:text-white rounded py-2 px-3 font-bold"><i data-feather="check" class="inline h-5"></i> SAVE ARTICLE</button>
57
- <span class="text-lg ml-5"><a class="no-underline" href="<%= article.persisted? ? article_path(article.slug) : root_path %>">Cancel</a></span>
58
94
  </div>
59
95
 
60
96
  </section>
61
97
 
62
- <script> elem('input#slug').focus(); </script>
98
+ <script>
99
+ elem('input#slug').focus();
100
+ setReviewForm();
101
+ </script>