dokno 1.0.0 → 1.3.0
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 -6
- data/app/assets/javascripts/dokno.js +79 -27
- data/app/assets/stylesheets/dokno/application.css +1 -1
- data/app/controllers/dokno/application_controller.rb +3 -0
- data/app/controllers/dokno/articles_controller.rb +22 -8
- data/app/controllers/dokno/categories_controller.rb +15 -2
- data/app/controllers/dokno/user_concern.rb +5 -3
- data/app/helpers/dokno/application_helper.rb +1 -3
- data/app/models/dokno/article.rb +87 -38
- data/app/models/dokno/category.rb +39 -15
- data/app/views/dokno/_article_formatting.html.erb +17 -18
- data/app/views/dokno/_article_panel.html.erb +16 -18
- data/app/views/dokno/_panel_formatting.html.erb +47 -57
- data/app/views/dokno/articles/_article_form.html.erb +47 -6
- data/app/views/dokno/articles/show.html.erb +45 -39
- data/app/views/dokno/categories/_category_form.html.erb +6 -1
- data/app/views/dokno/categories/index.html.erb +40 -37
- data/app/views/layouts/dokno/application.html.erb +34 -9
- data/app/views/partials/_category_header.html.erb +29 -0
- data/app/views/partials/_form_errors.html.erb +0 -1
- data/app/views/partials/_logs.html.erb +7 -5
- data/app/views/partials/_pagination.html.erb +20 -18
- data/config/routes.rb +1 -1
- data/db/migrate/20201203190330_baseline.rb +4 -4
- data/db/migrate/20201211192306_add_review_due_at_to_articles.rb +6 -0
- data/db/migrate/20201213165700_add_starred_to_article.rb +5 -0
- data/lib/dokno/config/config.rb +53 -40
- data/lib/dokno/engine.rb +4 -4
- data/lib/dokno/version.rb +1 -1
- data/lib/generators/dokno/templates/config/initializers/dokno.rb +18 -5
- metadata +87 -17
@@ -20,6 +20,8 @@ module Dokno
|
|
20
20
|
|
21
21
|
before_validation :set_code
|
22
22
|
|
23
|
+
scope :alpha_order, -> { order(:name) }
|
24
|
+
|
23
25
|
# The display breadcrumb for the Category
|
24
26
|
def breadcrumb
|
25
27
|
crumbs = [name]
|
@@ -43,18 +45,18 @@ module Dokno
|
|
43
45
|
.joins(:categories)
|
44
46
|
.where(dokno_categories: { id: self.class.branch(parent_category_id: id).pluck(:id) })
|
45
47
|
|
46
|
-
records
|
47
|
-
records = records.newest_order if order == :newest
|
48
|
-
records = records.view_order if order == :views
|
49
|
-
records = records.alpha_order if order == :alpha
|
50
|
-
|
51
|
-
records
|
48
|
+
Article.apply_sort(records, order: order)
|
52
49
|
end
|
53
50
|
|
54
51
|
def branch
|
55
52
|
self.class.branch(parent_category_id: id)
|
56
53
|
end
|
57
54
|
|
55
|
+
# Used to invalidate the fragment cache of the hierarchical category select options
|
56
|
+
def self.cache_key
|
57
|
+
[maximum(:updated_at), Article.maximum(:updated_at)].compact.max
|
58
|
+
end
|
59
|
+
|
58
60
|
# The given Category and all child Categories. Useful for filtering associated articles.
|
59
61
|
def self.branch(parent_category_id:, at_top: true)
|
60
62
|
return if parent_category_id.blank?
|
@@ -71,19 +73,41 @@ module Dokno
|
|
71
73
|
categories.flatten
|
72
74
|
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
def self.select_option_markup(selected_category_codes: nil, exclude_category_id: nil, context_category: nil, level: 0)
|
77
|
+
return '' if level.positive? && context_category.blank?
|
78
|
+
|
79
|
+
options = []
|
80
|
+
level_categories = where(category_id: context_category&.id).alpha_order
|
81
|
+
|
82
|
+
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
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
options.join
|
83
99
|
end
|
84
100
|
|
85
101
|
private
|
86
102
|
|
103
|
+
def self.option_markup(category:, selected_category_codes:, exclude_category_id:, level: 0)
|
104
|
+
return '' if category.id == exclude_category_id
|
105
|
+
|
106
|
+
selected = selected_category_codes&.include?(category.code)
|
107
|
+
article_count = category.articles_in_branch.size
|
108
|
+
%(<option value="#{category.code}" #{'selected="selected"' if selected}>#{(' ' * level)}#{category.name}#{' (' + article_count.to_s + ')' if article_count.positive?}</option>)
|
109
|
+
end
|
110
|
+
|
87
111
|
# Never allow setting of parent to self
|
88
112
|
def circular_parent_check
|
89
113
|
return unless persisted? && id.to_i == category_id.to_i
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<style>
|
2
2
|
/* Article formatting */
|
3
3
|
.dokno-article-content-markup {
|
4
|
-
font-weight:
|
5
|
-
line-height: 1.
|
6
|
-
font-size:
|
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.
|
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.
|
35
|
+
margin-bottom: 1.25em;
|
36
36
|
font-weight: 600;
|
37
37
|
}
|
38
38
|
|
39
39
|
.dokno-article-content-markup h1 {
|
40
|
-
font-size:
|
40
|
+
font-size: 1.625em;
|
41
41
|
}
|
42
42
|
|
43
43
|
.dokno-article-content-markup h2 {
|
44
|
-
font-size: 1.
|
44
|
+
font-size: 1.25em;
|
45
45
|
}
|
46
46
|
|
47
|
-
.dokno-article-content-markup h3
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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.
|
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:
|
80
|
-
padding-right:
|
81
|
-
padding-top: 0.
|
82
|
-
padding-bottom: 0.
|
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
|
-
|
34
|
-
|
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,11 +57,9 @@
|
|
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);
|
62
|
+
document.addEventListener('click', dokno__click_listener, false);
|
70
63
|
}
|
71
64
|
};
|
72
65
|
|
@@ -74,10 +67,13 @@
|
|
74
67
|
}
|
75
68
|
|
76
69
|
function doknoClosePanel() {
|
77
|
-
|
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
|
+
|
78
73
|
dokno__panel.classList.remove('open');
|
79
74
|
document.body.classList.remove('dokno-no-scroll');
|
80
75
|
document.removeEventListener('keydown', dokno__keydown_listener, false);
|
76
|
+
document.removeEventListener('click', dokno__click_listener, false);
|
81
77
|
|
82
78
|
dokno__slug = null;
|
83
79
|
}
|
@@ -96,7 +92,6 @@
|
|
96
92
|
}
|
97
93
|
|
98
94
|
const dokno__panel = document.getElementById('dokno-panel-container');
|
99
|
-
const dokno__close = document.querySelector('div#dokno-panel-close');
|
100
95
|
const dokno__panel_title = document.getElementById('dokno-panel-title');
|
101
96
|
const dokno__panel_summary = document.getElementById('dokno-panel-summary');
|
102
97
|
const dokno__panel_footer = document.getElementById('dokno-panel-footer');
|
@@ -106,7 +101,10 @@
|
|
106
101
|
if (e.key === 'Escape') { doknoClosePanel(); }
|
107
102
|
}
|
108
103
|
|
109
|
-
|
104
|
+
const dokno__click_listener = function(e) {
|
105
|
+
var isClickInside = dokno__panel.contains(e.target);
|
106
|
+
if (!isClickInside) { doknoClosePanel(); }
|
107
|
+
}
|
110
108
|
|
111
|
-
var dokno__id, dokno__slug;
|
109
|
+
var dokno__id, dokno__slug, dokno__link_just_clicked;
|
112
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
|
-
|
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:
|
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:
|
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:
|
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
|
7
|
-
<hr class="mb-
|
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>
|
@@ -27,7 +50,7 @@
|
|
27
50
|
</div>
|
28
51
|
<% end %>
|
29
52
|
|
30
|
-
<hr class="
|
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,14 +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="
|
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 & <a target="_blank" href="https://commonmark.org/help/" title="Markdown formatting examples">markdown</a> OK.</div>
|
53
76
|
</div>
|
54
77
|
|
55
|
-
<div class="
|
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>
|
97
|
+
|
98
|
+
<script>
|
99
|
+
elem('input#slug').focus();
|
100
|
+
setReviewForm();
|
101
|
+
</script>
|