dokno 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>
|