dokno 1.2.1 → 1.4.3
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 +4 -6
- data/app/assets/javascripts/dokno.js +22 -8
- data/app/assets/stylesheets/dokno/application.css +1 -1
- data/app/controllers/dokno/application_controller.rb +1 -1
- data/app/controllers/dokno/articles_controller.rb +14 -6
- data/app/controllers/dokno/categories_controller.rb +10 -7
- data/app/controllers/dokno/pagination_concern.rb +5 -5
- data/app/controllers/dokno/user_concern.rb +1 -1
- data/app/helpers/dokno/application_helper.rb +1 -1
- data/app/models/dokno/application_record.rb +3 -0
- data/app/models/dokno/article.rb +90 -42
- data/app/models/dokno/category.rb +18 -45
- data/app/views/dokno/articles/_article_form.html.erb +47 -8
- data/app/views/dokno/articles/show.html.erb +21 -13
- data/app/views/dokno/categories/_category_form.html.erb +17 -6
- data/app/views/dokno/categories/index.html.erb +40 -12
- data/app/views/layouts/dokno/application.html.erb +29 -30
- data/app/views/partials/_category_header.html.erb +6 -5
- data/app/views/partials/_logs.html.erb +6 -4
- data/app/views/partials/_pagination.html.erb +20 -17
- data/config/routes.rb +1 -0
- 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 +55 -40
- data/lib/dokno/engine.rb +5 -5
- data/lib/dokno/version.rb +1 -1
- data/lib/generators/dokno/templates/config/initializers/dokno.rb +18 -5
- metadata +23 -21
@@ -1,41 +1,33 @@
|
|
1
1
|
module Dokno
|
2
2
|
class Category < ApplicationRecord
|
3
|
-
belongs_to :parent,
|
4
|
-
|
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
|
-
|
26
|
-
|
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 =
|
34
|
-
crumbs.prepend parent_category
|
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(" > ").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,12 +37,7 @@ 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
|
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
|
@@ -59,7 +46,7 @@ module Dokno
|
|
59
46
|
|
60
47
|
# Used to invalidate the fragment cache of the hierarchical category select options
|
61
48
|
def self.cache_key
|
62
|
-
|
49
|
+
[maximum(:updated_at), Article.maximum(:updated_at)].compact.max
|
63
50
|
end
|
64
51
|
|
65
52
|
# The given Category and all child Categories. Useful for filtering associated articles.
|
@@ -78,26 +65,14 @@ module Dokno
|
|
78
65
|
categories.flatten
|
79
66
|
end
|
80
67
|
|
81
|
-
def self.select_option_markup(selected_category_codes: nil,
|
68
|
+
def self.select_option_markup(selected_category_codes: nil, context_category: nil, level: 0)
|
82
69
|
return '' if level.positive? && context_category.blank?
|
83
70
|
|
84
71
|
options = []
|
85
72
|
level_categories = where(category_id: context_category&.id).alpha_order
|
86
|
-
|
87
73
|
level_categories.each do |category|
|
88
|
-
options << option_markup(
|
89
|
-
|
90
|
-
selected_category_codes: selected_category_codes,
|
91
|
-
exclude_category_id: exclude_category_id,
|
92
|
-
level: level
|
93
|
-
)
|
94
|
-
|
95
|
-
options << select_option_markup(
|
96
|
-
selected_category_codes: selected_category_codes,
|
97
|
-
exclude_category_id: exclude_category_id,
|
98
|
-
context_category: category,
|
99
|
-
level: (level + 1)
|
100
|
-
)
|
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))
|
101
76
|
end
|
102
77
|
|
103
78
|
options.join
|
@@ -105,9 +80,7 @@ module Dokno
|
|
105
80
|
|
106
81
|
private
|
107
82
|
|
108
|
-
def self.option_markup(category:, selected_category_codes:,
|
109
|
-
return '' if category.id == exclude_category_id
|
110
|
-
|
83
|
+
def self.option_markup(category:, selected_category_codes:, level: 0)
|
111
84
|
selected = selected_category_codes&.include?(category.code)
|
112
85
|
article_count = category.articles_in_branch.size
|
113
86
|
%(<option value="#{category.code}" #{'selected="selected"' if selected}>#{(' ' * level)}#{category.name}#{' (' + article_count.to_s + ')' if article_count.positive?}</option>)
|
@@ -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>
|
@@ -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="
|
18
|
-
<select name="category_code[]" id="category_code" multiple="multiple" size="<%= (cat_count = Dokno::Category.count) <=
|
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="
|
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>
|
@@ -52,11 +75,27 @@
|
|
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">
|
56
92
|
<span class="text-lg mr-5"><a class="no-underline" href="<%= article.persisted? ? article_path(article.slug) : root_path %>">Cancel</a></span>
|
57
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>
|
58
94
|
</div>
|
59
95
|
|
60
96
|
</section>
|
61
97
|
|
62
|
-
<script>
|
98
|
+
<script>
|
99
|
+
elem('input#slug').focus();
|
100
|
+
setReviewForm();
|
101
|
+
</script>
|
@@ -2,7 +2,12 @@
|
|
2
2
|
|
3
3
|
<% if @category.present? %>
|
4
4
|
<div class="no-print text-gray-500 mb-5">
|
5
|
-
<div>
|
5
|
+
<div>
|
6
|
+
<% if request.referrer&.include? article_index_path %>
|
7
|
+
<a class="fixed left-0 ml-6" title="Back" href="javascript:history.back();"><i data-feather="chevrons-left" class="text-gray-300 h-5 align-text-bottom inline"></i></a>
|
8
|
+
<% end %>
|
9
|
+
<span class="text-gray-500 mr-1">Under</span> <%= @category.breadcrumb(search_term: @search_term, order: @order) %>
|
10
|
+
</div>
|
6
11
|
</div>
|
7
12
|
<% end %>
|
8
13
|
|
@@ -13,7 +18,10 @@
|
|
13
18
|
<section>
|
14
19
|
<div class="flex">
|
15
20
|
<div id="dokno-article-sidebar" class="w-2/5 pr-10">
|
16
|
-
<h1 class="dokno-article-content-highlight text-4xl mb-8 leading-tight font-light"
|
21
|
+
<h1 class="dokno-article-content-highlight text-4xl mb-8 leading-tight font-light">
|
22
|
+
<%= @article.title %>
|
23
|
+
<% if @article.starred %><i title="Starred article" data-feather="star" class="inline align-middle"></i><% end %>
|
24
|
+
</h1>
|
17
25
|
|
18
26
|
<div>
|
19
27
|
<div class="mb-8 no-print">
|
@@ -23,7 +31,7 @@
|
|
23
31
|
</div>
|
24
32
|
|
25
33
|
<div class="flex">
|
26
|
-
<div class="no-print w-8"><i data-feather="clock" class="inline-block h-5"></i></div>
|
34
|
+
<div class="no-print w-8"><i data-feather="clock" class="inline-block h-5 mr-2"></i></div>
|
27
35
|
<div class="w-full">
|
28
36
|
Last updated:<br />
|
29
37
|
<%= time_ago_in_words @article.updated_at %> ago
|
@@ -34,7 +42,7 @@
|
|
34
42
|
</div>
|
35
43
|
|
36
44
|
<div class="mt-5 flex no-print">
|
37
|
-
<div class="no-print w-8"><i data-feather="eye" class="inline-block h-5"></i></div>
|
45
|
+
<div class="no-print w-8"><i data-feather="eye" class="inline-block h-5 mr-2"></i></div>
|
38
46
|
<div class="w-full">
|
39
47
|
Views:<br />
|
40
48
|
<%= number_with_delimiter(@article.views, delimiter: ',') %>
|
@@ -43,7 +51,7 @@
|
|
43
51
|
|
44
52
|
<% if @article.contributors.present? %>
|
45
53
|
<div class="mt-5 flex">
|
46
|
-
<div class="no-print w-8"><i data-feather="user-check" class="inline-block h-5"></i></div>
|
54
|
+
<div class="no-print w-8"><i data-feather="user-check" class="inline-block h-5 mr-2"></i></div>
|
47
55
|
<div class="w-full">
|
48
56
|
Contributors:<br />
|
49
57
|
<%= @article.contributors %>
|
@@ -53,7 +61,7 @@
|
|
53
61
|
|
54
62
|
<% if @article.reading_time.present? %>
|
55
63
|
<div class="mt-5 flex no-print">
|
56
|
-
<div class="no-print w-8"><i data-feather="watch" class="inline-block h-5"></i></div>
|
64
|
+
<div class="no-print w-8"><i data-feather="watch" class="inline-block h-5 mr-2"></i></div>
|
57
65
|
<div class="w-full">
|
58
66
|
Reading time:<br />
|
59
67
|
<%= @article.reading_time %>
|
@@ -62,7 +70,7 @@
|
|
62
70
|
<% end %>
|
63
71
|
|
64
72
|
<div class="mt-5 flex">
|
65
|
-
<div class="no-print w-8"><i data-feather="link" class="inline-block h-5"></i></div>
|
73
|
+
<div class="no-print w-8"><i data-feather="link" class="inline-block h-5 mr-2"></i></div>
|
66
74
|
<div class="w-full">
|
67
75
|
Permalink:<br />
|
68
76
|
<a class="inline-block mt-1 -ml-2 px-2 py-1 bg-blue-100 rounded" title="Copy to clipboard" href="javascript:;" onclick="copyToClipboard('<%= @article.permalink(request.base_url) %>');"><%= @article.permalink(request.base_url) %></a>
|
@@ -71,7 +79,7 @@
|
|
71
79
|
|
72
80
|
<% if can_edit? %>
|
73
81
|
<div class="mt-5 flex no-print">
|
74
|
-
<div class="no-print w-8"><i data-feather="crosshair" class="inline-block h-5"></i></div>
|
82
|
+
<div class="no-print w-8"><i data-feather="crosshair" class="inline-block h-5 mr-2"></i></div>
|
75
83
|
<div class="w-full">
|
76
84
|
Unique slug:<br />
|
77
85
|
<a class="inline-block mt-1 -ml-2 px-2 py-1 bg-blue-100 rounded" title="Copy to clipboard" href="javascript:;" onclick="copyToClipboard('<%= j @article.slug %>');"><%= @article.slug %></a>
|
@@ -90,7 +98,7 @@
|
|
90
98
|
|
91
99
|
<% if (category_name_list = @article.category_name_list(context_category_id: @category&.id)).present? %>
|
92
100
|
<div class="mt-5 flex no-print">
|
93
|
-
<div class="no-print w-8"><i data-feather="folder" class="inline-block h-5"></i></div>
|
101
|
+
<div class="no-print w-8"><i data-feather="folder" class="inline-block h-5 mr-2"></i></div>
|
94
102
|
<div class="w-full">
|
95
103
|
<%= category_name_list.sub(':', ':<br />').html_safe %>
|
96
104
|
</div>
|
@@ -120,14 +128,14 @@
|
|
120
128
|
<div class="no-print">
|
121
129
|
<hr class="mt-5 mb-10" />
|
122
130
|
<div class="text-right">
|
123
|
-
<button title="Edit article" class="bg-blue-900 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-sm" onclick="location.href='<%= edit_article_path(@article.slug) %>';"><i data-feather="edit" class="inline h-5"></i> EDIT</button>
|
131
|
+
<button title="Edit article" class="bg-blue-900 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-sm" onclick="location.href='<%= edit_article_path(@article.slug) %>';"><i data-feather="edit-2" class="inline h-5"></i> EDIT</button>
|
124
132
|
|
125
133
|
<% if @article.active %>
|
126
|
-
<button title="Deactivate article" id="article-deactivate-button" class="bg-yellow-700 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-base" onclick="
|
134
|
+
<button title="Deactivate article" id="article-deactivate-button" class="bg-yellow-700 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-base" onclick="setArticleStatus('<%= @article.slug %>', false);"><i data-feather="file-minus" class="inline h-5"></i> DEACTIVATE</button>
|
127
135
|
<% else %>
|
128
|
-
<button title="Re-activate article" id="article-activate-button" class="bg-green-700 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-base" onclick="
|
136
|
+
<button title="Re-activate article" id="article-activate-button" class="bg-green-700 text-gray-300 hover:text-white rounded mr-5 py-2 px-3 font-bold text-base" onclick="setArticleStatus('<%= @article.slug %>', true);"><i data-feather="file-plus" class="inline h-5"></i> RE-ACTIVATE</button>
|
129
137
|
<% end %>
|
130
|
-
<button title="Permanently delete article" class="bg-red-700 text-gray-300 hover:text-white rounded py-2 px-3 font-bold text-base" onclick="deleteArticle('<%= @article.id %>');"><i data-feather="
|
138
|
+
<button title="Permanently delete article" class="bg-red-700 text-gray-300 hover:text-white rounded py-2 px-3 font-bold text-base" onclick="deleteArticle('<%= @article.id %>');"><i data-feather="slash" class="inline h-5"></i> DELETE</button>
|
131
139
|
</div>
|
132
140
|
</div>
|
133
141
|
<% end %>
|
@@ -10,13 +10,20 @@
|
|
10
10
|
</div>
|
11
11
|
|
12
12
|
<% if Dokno::Category.exists? %>
|
13
|
-
<div class="mb-5">
|
13
|
+
<div class="mb-5 w-1/2">
|
14
14
|
<div class="text-lg font-semibold"><label for="parent_category_code">Parent Category</label></div>
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
|
16
|
+
<select name="parent_category_code" id="parent_category_code" size="1" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full max-w-full">
|
17
|
+
<option value="">No Parent Category</option>
|
18
|
+
|
19
|
+
<optgroup label="Categories">
|
20
|
+
<% cache Dokno::Category do %>
|
21
|
+
<%= Dokno::Category.select_option_markup.html_safe %>
|
22
|
+
<% end %>
|
23
|
+
</optgroup>
|
18
24
|
</select>
|
19
|
-
|
25
|
+
|
26
|
+
<div class="text-gray-500 mt-2">
|
20
27
|
The existing category to which this category belongs.
|
21
28
|
<% if (article_count = category.articles.count).positive? %>
|
22
29
|
There <%= article_count > 1 ? "are #{article_count} articles" : 'is an article' %> currently in this category.
|
@@ -35,4 +42,8 @@
|
|
35
42
|
</div>
|
36
43
|
</section>
|
37
44
|
|
38
|
-
<script>
|
45
|
+
<script>
|
46
|
+
// Client-side select of cached select list
|
47
|
+
selectOption('parent_category_code', '<%= j @parent_category_code %>');
|
48
|
+
elem('input#name').focus();
|
49
|
+
</script>
|
@@ -1,10 +1,31 @@
|
|
1
|
+
<% if !current_page?(up_for_review_path) && (@category.blank? || @search_term.present?) %>
|
2
|
+
<div class="text-center m-auto mb-10 w-full max-w-screen-xl">
|
3
|
+
<% if @search_term.present? %>
|
4
|
+
<div class="text-gray-600 text-2xl uppercase">
|
5
|
+
<%= @total_records.positive? ? "#{@total_records} #{'article'.pluralize(@total_records)}" : 'No articles' %>
|
6
|
+
found containing the search term
|
7
|
+
<div class="text-4xl leading-tight"><span class="font-serif">“</span> <%= @search_term %> <span class="font-serif">”</span> </div>
|
8
|
+
</div>
|
9
|
+
<% else %>
|
10
|
+
<div class="text-gray-600 text-2xl">
|
11
|
+
Browse or search
|
12
|
+
<% if (article_count = Dokno::Article.count) > 1 %>
|
13
|
+
<%= number_with_delimiter(article_count, delimiter: ',') %> articles in
|
14
|
+
<% end %>
|
15
|
+
the
|
16
|
+
</div>
|
17
|
+
<div class="text-gray-800 text-4xl leading-tight uppercase"><%= Dokno.config.app_name %> knowledgebase</div>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
|
1
22
|
<% if @category&.parent.present? %>
|
2
23
|
<div class="text-gray-500 mb-5">
|
3
|
-
<div
|
24
|
+
<div><span class="text-gray-500 mr-1">Under</span> <%= @category.breadcrumb(search_term: @search_term, order: @order, hide_self: true) %></div>
|
4
25
|
</div>
|
5
26
|
<% end %>
|
6
27
|
|
7
|
-
<% if Dokno::Category.exists? || Dokno::Article.exists? %>
|
28
|
+
<% if !current_page?(up_for_review_path) && (Dokno::Category.exists? || Dokno::Article.exists?) %>
|
8
29
|
<%= render 'partials/category_header' %>
|
9
30
|
<% end %>
|
10
31
|
|
@@ -44,19 +65,13 @@
|
|
44
65
|
<section class="border-t border-gray-300 py-10 text-xl flex">
|
45
66
|
<div class="w-1/3 pr-10">
|
46
67
|
<div class="flex">
|
47
|
-
<div class="no-print w-10 text-gray-300"><i data-feather="chevron-right" class="inline-block"></i></div>
|
68
|
+
<div title="<%= 'Starred article' if article.starred %>" class="no-print w-10 text-gray-300"><i data-feather="<%= article.starred ? 'star' : 'chevron-right' %>" class="inline-block"></i></div>
|
48
69
|
<div class="w-full">
|
49
70
|
<a class="dokno-article-title <% unless article.active %>text-gray-500 italic<% end %>" href="<%= article_path article.slug %>?search_term=<%= @search_term %>&cat_code=<%= @category&.code %>&order=<%= @order %>" title="View article"><%= article.title %></a>
|
50
71
|
</div>
|
51
72
|
</div>
|
52
73
|
</div>
|
53
74
|
<div class="dokno-article-summary w-2/3 <% unless article.active %>text-gray-500 italic<% end %>">
|
54
|
-
<% unless article.active %>
|
55
|
-
<div class="bg-yellow-700 p-4 mb-5 rounded text-lg border-t-4 border-yellow-900 text-white font-base not-italic">
|
56
|
-
<i data-feather="alert-circle" class="inline-block"></i> This article is no longer active
|
57
|
-
</div>
|
58
|
-
<% end %>
|
59
|
-
|
60
75
|
<div class="dokno-article-content-highlight mb-2"><%= article.summary.presence || 'No summary provided' %></div>
|
61
76
|
|
62
77
|
<div class="text-base text-gray-500">
|
@@ -66,14 +81,27 @@
|
|
66
81
|
<% unless @order == 'alpha' %>
|
67
82
|
<div class="text-base">
|
68
83
|
<% if @order == 'views' %>
|
69
|
-
<div class="text-gray-500">
|
84
|
+
<div class="text-gray-500">This article was viewed <%= number_with_delimiter(article.views, delimiter: ',') %> <%= 'time'.pluralize(article.views) %></div>
|
70
85
|
<% elsif @order == 'updated' %>
|
71
|
-
<div class="text-gray-500">
|
86
|
+
<div class="text-gray-500">This article was last updated <%= time_ago_in_words article.updated_at %> ago</div>
|
72
87
|
<% elsif @order == 'newest' %>
|
73
|
-
<div class="text-gray-500">
|
88
|
+
<div class="text-gray-500">This article was added <%= time_ago_in_words article.created_at %> ago</div>
|
74
89
|
<% end %>
|
75
90
|
</div>
|
76
91
|
<% end %>
|
92
|
+
|
93
|
+
<% if !article.active %>
|
94
|
+
<div class="bg-yellow-700 p-4 mt-5 rounded text-lg border-t-4 border-yellow-900 text-white font-base not-italic">
|
95
|
+
<i data-feather="info" class="inline-block mr-1"></i> This article is no longer active
|
96
|
+
</div>
|
97
|
+
<% end %>
|
98
|
+
|
99
|
+
<% if article.up_for_review? %>
|
100
|
+
<div class="bg-<%= article.review_due_days.negative? ? 'red' : 'gray' %>-800 p-4 mt-5 rounded text-lg border-t-4 border-<%= article.review_due_days.negative? ? 'red' : 'gray' %>-900 text-white font-base not-italic">
|
101
|
+
<i data-feather="bell" class="inline-block mr-1"></i> <%= article.review_due_days_string %>
|
102
|
+
</div>
|
103
|
+
<% end %>
|
104
|
+
|
77
105
|
</div>
|
78
106
|
</section>
|
79
107
|
<% end %>
|
@@ -2,6 +2,8 @@
|
|
2
2
|
<html>
|
3
3
|
<head>
|
4
4
|
<title><%= Dokno.config.app_name %> KNOWLEDGEBASE</title>
|
5
|
+
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
5
7
|
<%= csrf_meta_tags %>
|
6
8
|
<%= csp_meta_tag %>
|
7
9
|
|
@@ -14,6 +16,7 @@
|
|
14
16
|
</head>
|
15
17
|
<body class="bg-white font-sans font-light subpixel-antialiased text-lg">
|
16
18
|
|
19
|
+
|
17
20
|
<nav id="dokno-nav-container" class="bg-blue-900 text-white py-10 px-16 text-lg">
|
18
21
|
<div class="flex items-center m-auto w-full max-w-screen-xl">
|
19
22
|
<div class="w-1/3">
|
@@ -24,12 +27,12 @@
|
|
24
27
|
<div class="w-2/3 text-right">
|
25
28
|
<% if can_edit? %>
|
26
29
|
<% if action_name != 'new' %>
|
27
|
-
<button title="Add a new article" class="bg-gray-700 text-gray-300 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= new_article_path %>/?category_code=<%= @category&.code %>';"><i data-feather="plus
|
28
|
-
<button title="Add a new category" class="bg-gray-700 text-gray-300 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= new_category_path %>/?parent_category_code=<%= @category&.code %>';"><i data-feather="plus
|
30
|
+
<button title="Add a new article" class="bg-gray-700 text-gray-300 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= new_article_path %>/?category_code=<%= @category&.code %>';"><i data-feather="plus" class="inline h-5"></i> ARTICLE</button>
|
31
|
+
<button title="Add a new category" class="bg-gray-700 text-gray-300 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= new_category_path %>/?parent_category_code=<%= @category&.code %>';"><i data-feather="plus" class="inline h-5"></i> CATEGORY</button>
|
29
32
|
<% end %>
|
30
33
|
|
31
34
|
<% if @category&.persisted? && action_name != 'edit' %>
|
32
|
-
<button title="Edit this category" class="bg-gray-700 text-gray-100 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= edit_category_path(@category) %>';"><i data-feather="edit" class="inline h-5"></i> CATEGORY</button>
|
35
|
+
<button title="Edit this category" class="bg-gray-700 text-gray-100 hover:text-white hover:bg-gray-900 rounded ml-3 py-2 px-3 font-bold text-base" onclick="location.href='<%= edit_category_path(@category) %>';"><i data-feather="edit-2" class="inline h-5"></i> CATEGORY</button>
|
33
36
|
<% end %>
|
34
37
|
<% end %>
|
35
38
|
|
@@ -40,40 +43,22 @@
|
|
40
43
|
</div>
|
41
44
|
</nav>
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
<%=
|
46
|
+
|
47
|
+
<% flash.each do |type, msg| %>
|
48
|
+
<div class="bg-<%= type %>-800 text-lg text-white font-base py-10 px-16 text-center">
|
49
|
+
<i data-feather="<%= (type == 'green' ? 'smile' : (type == 'yellow' ? 'info' : (type == 'gray' ? 'bell' : 'frown'))) %>" class="inline mr-1"></i>
|
50
|
+
<%= sanitize(msg, tags: %w[a], attributes: %w[href class]) %>
|
47
51
|
</div>
|
48
52
|
<% end %>
|
49
53
|
|
50
|
-
<main class="py-10 px-16">
|
51
|
-
<% if @article.blank? && (@category.blank? || @search_term.present?) %>
|
52
|
-
<div class="text-center m-auto mb-10 w-full max-w-screen-xl">
|
53
|
-
<% if @search_term.present? %>
|
54
|
-
<div class="text-gray-600 text-2xl uppercase">
|
55
|
-
<%= @total_records.positive? ? "#{@total_records} #{'article'.pluralize(@total_records)}" : 'No articles' %>
|
56
|
-
found containing the search term
|
57
|
-
<div class="text-4xl leading-tight"><span class="font-serif">“</span> <%= @search_term %> <span class="font-serif">”</span> </div>
|
58
|
-
</div>
|
59
|
-
<% else %>
|
60
|
-
<div class="text-gray-600 text-2xl">
|
61
|
-
Browse or search
|
62
|
-
<% if (article_count = Dokno::Article.count) > 1 %>
|
63
|
-
<%= number_with_delimiter(article_count, delimiter: ',') %> articles in
|
64
|
-
<% end %>
|
65
|
-
the
|
66
|
-
</div>
|
67
|
-
<div class="text-gray-800 text-4xl leading-tight uppercase"><%= Dokno.config.app_name %> knowledgebase</div>
|
68
|
-
<% end %>
|
69
|
-
</div>
|
70
|
-
<% end %>
|
71
54
|
|
55
|
+
<main class="py-10 px-16">
|
72
56
|
<div id="dokno-content-container" class="w-full max-w-screen-xl m-auto print-this">
|
73
57
|
<%= yield %>
|
74
58
|
</div>
|
75
59
|
</main>
|
76
60
|
|
61
|
+
|
77
62
|
<footer id="dokno-footer-container">
|
78
63
|
<% if @article.present? && action_name == 'show' %>
|
79
64
|
<div id="dokno-article-log-container" data-category-id="<%= @category&.id %>" data-article-id="<%= @article.id %>">
|
@@ -81,10 +66,24 @@
|
|
81
66
|
</div>
|
82
67
|
<% end %>
|
83
68
|
|
69
|
+
<% if @show_up_for_review && (up_for_review_count = Dokno::Article.up_for_review.count).positive? %>
|
70
|
+
<div id="dokno-articles-up-for-review-container">
|
71
|
+
<div class="py-10 px-16 bg-gray-900">
|
72
|
+
<div class="w-full max-w-screen-xl m-auto">
|
73
|
+
<div class="text-xl text-white cursor-pointer" onclick="location.href='<%= up_for_review_path %>';">
|
74
|
+
<i data-feather="bell" class="inline mr-1"></i>
|
75
|
+
There <%= "#{up_for_review_count == 1 ? 'is' : 'are'} #{up_for_review_count}" %> <%= 'article'.pluralize(up_for_review_count) %> up for accuracy / relevance review
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
<% end %>
|
81
|
+
|
84
82
|
<div class="py-10 px-16 text-gray-400 bg-blue-900">
|
85
83
|
<div class="w-full max-w-screen-xl m-auto flex">
|
86
84
|
<div class="w-1/2">
|
87
|
-
<
|
85
|
+
<i data-feather="github" class="inline mr-1"></i>
|
86
|
+
<a target="_blank" href="https://github.com/cpayne624/dokno" title="Dokno on GitHub">dokno</a>
|
88
87
|
</div>
|
89
88
|
<div class="w-1/2 text-right">
|
90
89
|
<% if user.present? %>
|
@@ -103,7 +102,7 @@
|
|
103
102
|
<%= javascript_include_tag 'init' %>
|
104
103
|
|
105
104
|
<% if @search_term.present? %>
|
106
|
-
<script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight')
|
105
|
+
<script> highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight'); </script>
|
107
106
|
<% end %>
|
108
107
|
</body>
|
109
108
|
</html>
|