dokno 1.0.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -6
  3. data/app/assets/javascripts/dokno.js +79 -27
  4. data/app/assets/stylesheets/dokno/application.css +1 -1
  5. data/app/controllers/dokno/application_controller.rb +3 -0
  6. data/app/controllers/dokno/articles_controller.rb +22 -8
  7. data/app/controllers/dokno/categories_controller.rb +15 -2
  8. data/app/controllers/dokno/user_concern.rb +5 -3
  9. data/app/helpers/dokno/application_helper.rb +1 -3
  10. data/app/models/dokno/article.rb +87 -38
  11. data/app/models/dokno/category.rb +39 -15
  12. data/app/views/dokno/_article_formatting.html.erb +17 -18
  13. data/app/views/dokno/_article_panel.html.erb +16 -18
  14. data/app/views/dokno/_panel_formatting.html.erb +47 -57
  15. data/app/views/dokno/articles/_article_form.html.erb +47 -6
  16. data/app/views/dokno/articles/show.html.erb +45 -39
  17. data/app/views/dokno/categories/_category_form.html.erb +6 -1
  18. data/app/views/dokno/categories/index.html.erb +40 -37
  19. data/app/views/layouts/dokno/application.html.erb +34 -9
  20. data/app/views/partials/_category_header.html.erb +29 -0
  21. data/app/views/partials/_form_errors.html.erb +0 -1
  22. data/app/views/partials/_logs.html.erb +7 -5
  23. data/app/views/partials/_pagination.html.erb +20 -18
  24. data/config/routes.rb +1 -1
  25. data/db/migrate/20201203190330_baseline.rb +4 -4
  26. data/db/migrate/20201211192306_add_review_due_at_to_articles.rb +6 -0
  27. data/db/migrate/20201213165700_add_starred_to_article.rb +5 -0
  28. data/lib/dokno/config/config.rb +53 -40
  29. data/lib/dokno/engine.rb +4 -4
  30. data/lib/dokno/version.rb +1 -1
  31. data/lib/generators/dokno/templates/config/initializers/dokno.rb +18 -5
  32. metadata +87 -17
@@ -1,26 +1,32 @@
1
1
  <%= render 'dokno/article_formatting' %>
2
2
 
3
+ <% if @category.present? %>
4
+ <div class="no-print text-gray-500 mb-5">
5
+ <div>Category: <a href="<%= article_index_path(@category.code) %>?search_term=<%= CGI.escape(@search_term.to_s) %>&order=<%= @order %>"><%= @category.breadcrumb %></a></div>
6
+ </div>
7
+ <% end %>
8
+
9
+ <%= render 'partials/category_header' %>
10
+
11
+ <div class="my-10 no-print"><hr /></div>
12
+
3
13
  <section>
4
14
  <div class="flex">
5
15
  <div id="dokno-article-sidebar" class="w-2/5 pr-10">
6
- <div id="article-deprecated-alert" class="<%= 'hidden' if @article.active %> bg-yellow-700 p-4 mb-5 rounded text-lg border-t-4 border-yellow-900 text-white font-base">
7
- <i data-feather="alert-circle" class="inline-block mr-2"></i> This article is no longer active
8
- </div>
9
-
10
- <h1 class="dokno-article-content-highlight text-4xl mb-10 leading-tight font-light"><%= @article.title %></h1>
16
+ <h1 class="dokno-article-content-highlight text-4xl mb-8 leading-tight font-light">
17
+ <%= @article.title %>
18
+ <% if @article.starred %><i title="Starred article" data-feather="star" class="inline align-middle"></i><% end %>
19
+ </h1>
11
20
 
12
21
  <div>
13
- <div class="mb-10 no-print">
14
- <button title="Email article" class="bg-gray-600 text-gray-300 hover:text-white rounded mr-3 py-2 px-3 font-bold text-xs" onclick="window.open('mailto:?subject=<%= CGI.escape(@article.title) %>&body=<%= CGI.escape(article_url(@article.slug)) %>');"><i data-feather="send" class="inline h-4"></i> EMAIL THIS</button>
15
- <button title="Print article" class="bg-gray-600 text-gray-300 hover:text-white rounded mr-3 py-2 px-3 font-bold text-xs" onclick="window.print();"><i data-feather="printer" class="inline h-4"></i> PRINT THIS</button>
16
-
17
- <% if can_edit? %>
18
- <button title="Edit article" class="bg-blue-900 text-gray-300 hover:text-white rounded py-2 px-3 font-bold text-xs" onclick="location.href='<%= edit_article_path(@article.slug) %>';"><i data-feather="edit" class="inline h-4"></i> EDIT THIS</button>
19
- <% end %>
22
+ <div class="mb-8 no-print">
23
+ <button title="Copy link" class="bg-gray-600 text-gray-300 hover:text-white rounded my-2 mr-2 py-2 px-3 font-bold text-sm" onclick="copyToClipboard('<%= @article.permalink(request.base_url) %>');"><i data-feather="clipboard" class="inline h-5"></i> COPY</button>
24
+ <button title="Email article" class="bg-gray-600 text-gray-300 hover:text-white rounded my-2 mr-2 py-2 px-3 font-bold text-sm" onclick="window.open('mailto:?subject=<%= CGI.escape(@article.title.to_s) %>&body=<%= CGI.escape(article_url(@article.slug)) %>');"><i data-feather="send" class="inline h-5"></i> EMAIL</button>
25
+ <button title="Print article" class="bg-gray-600 text-gray-300 hover:text-white rounded my-2 py-2 px-3 font-bold text-sm" onclick="window.print();"><i data-feather="printer" class="inline h-5"></i> PRINT</button>
20
26
  </div>
21
27
 
22
28
  <div class="flex">
23
- <div class="no-print w-8"><i data-feather="clock" class="inline-block h-5"></i></div>
29
+ <div class="no-print w-8"><i data-feather="clock" class="inline-block h-5 mr-2"></i></div>
24
30
  <div class="w-full">
25
31
  Last updated:<br />
26
32
  <%= time_ago_in_words @article.updated_at %> ago
@@ -30,8 +36,8 @@
30
36
  </div>
31
37
  </div>
32
38
 
33
- <div class="mt-5 flex">
34
- <div class="no-print w-8"><i data-feather="eye" class="inline-block h-5"></i></div>
39
+ <div class="mt-5 flex no-print">
40
+ <div class="no-print w-8"><i data-feather="eye" class="inline-block h-5 mr-2"></i></div>
35
41
  <div class="w-full">
36
42
  Views:<br />
37
43
  <%= number_with_delimiter(@article.views, delimiter: ',') %>
@@ -40,7 +46,7 @@
40
46
 
41
47
  <% if @article.contributors.present? %>
42
48
  <div class="mt-5 flex">
43
- <div class="no-print w-8"><i data-feather="user-check" class="inline-block h-5"></i></div>
49
+ <div class="no-print w-8"><i data-feather="user-check" class="inline-block h-5 mr-2"></i></div>
44
50
  <div class="w-full">
45
51
  Contributors:<br />
46
52
  <%= @article.contributors %>
@@ -49,8 +55,8 @@
49
55
  <% end %>
50
56
 
51
57
  <% if @article.reading_time.present? %>
52
- <div class="mt-5 flex">
53
- <div class="no-print w-8"><i data-feather="watch" class="inline-block h-5"></i></div>
58
+ <div class="mt-5 flex no-print">
59
+ <div class="no-print w-8"><i data-feather="watch" class="inline-block h-5 mr-2"></i></div>
54
60
  <div class="w-full">
55
61
  Reading time:<br />
56
62
  <%= @article.reading_time %>
@@ -59,7 +65,7 @@
59
65
  <% end %>
60
66
 
61
67
  <div class="mt-5 flex">
62
- <div class="no-print w-8"><i data-feather="link" class="inline-block h-5"></i></div>
68
+ <div class="no-print w-8"><i data-feather="link" class="inline-block h-5 mr-2"></i></div>
63
69
  <div class="w-full">
64
70
  Permalink:<br />
65
71
  <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>
@@ -67,8 +73,8 @@
67
73
  </div>
68
74
 
69
75
  <% if can_edit? %>
70
- <div class="mt-5 flex">
71
- <div class="no-print w-8"><i data-feather="crosshair" class="inline-block h-5"></i></div>
76
+ <div class="mt-5 flex no-print">
77
+ <div class="no-print w-8"><i data-feather="crosshair" class="inline-block h-5 mr-2"></i></div>
72
78
  <div class="w-full">
73
79
  Unique slug:<br />
74
80
  <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>
@@ -85,12 +91,11 @@
85
91
  </div>
86
92
  <% end %>
87
93
 
88
- <% if @article.categories.exists? %>
89
- <div class="mt-5 flex">
90
- <div class="no-print w-8"><i data-feather="folder" class="inline-block h-5"></i></div>
94
+ <% if (category_name_list = @article.category_name_list(context_category_id: @category&.id)).present? %>
95
+ <div class="mt-5 flex no-print">
96
+ <div class="no-print w-8"><i data-feather="folder" class="inline-block h-5 mr-2"></i></div>
91
97
  <div class="w-full">
92
- <%= 'Category'.pluralize @article.categories.count %>:<br />
93
- <%= @article.category_name_list.split(':').last.html_safe %>
98
+ <%= category_name_list.sub(':', ':<br />').html_safe %>
94
99
  </div>
95
100
  </div>
96
101
  <% end %>
@@ -110,21 +115,22 @@
110
115
  <% if @article.summary.blank? && @article.markdown.blank? %>
111
116
  <div class="mb-10">No content</div>
112
117
  <% end %>
113
-
114
- <% if can_edit? %>
115
- <div class="no-print">
116
- <hr class="mt-5" />
117
- <div class="mt-10 text-right">
118
- <button title="Deactivate article" id="article-deactivate-button" class="bg-yellow-700 text-gray-300 hover:text-white rounded mr-3 py-2 px-3 font-bold text-xs <% if !@article.active %>hidden<% end %>" onclick="deactiveArticle('<%= @article.slug %>');"><i data-feather="sunset" class="inline h-4"></i> DEACTIVATE THIS</button>
119
- <button title="Re-activate article" id="article-activate-button" class="bg-green-700 text-gray-300 hover:text-white rounded mr-3 py-2 px-3 font-bold text-xs <% if @article.active %>hidden<% end %>" onclick="activeArticle('<%= @article.slug %>');"><i data-feather="sunrise" class="inline h-4"></i> RE-ACTIVATE THIS</button>
120
- <button title="Permanently delete article" class="bg-red-700 text-gray-300 hover:text-white rounded py-2 px-3 font-bold text-xs" onclick="deleteArticle('<%= @article.id %>');"><i data-feather="trash" class="inline h-4"></i> DELETE THIS</button>
121
- </div>
122
- </div>
123
- <% end %>
124
118
  </div>
125
119
  </div>
126
120
  </section>
127
121
 
128
- <% if @search_term.present? %>
129
- <script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight');</script>
122
+ <% if can_edit? %>
123
+ <div class="no-print">
124
+ <hr class="mt-5 mb-10" />
125
+ <div class="text-right">
126
+ <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>
127
+
128
+ <% if @article.active %>
129
+ <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="deactivateArticle('<%= @article.slug %>');"><i data-feather="file-minus" class="inline h-5"></i> DEACTIVATE</button>
130
+ <% else %>
131
+ <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="activateArticle('<%= @article.slug %>');"><i data-feather="file-plus" class="inline h-5"></i> RE-ACTIVATE</button>
132
+ <% end %>
133
+ <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>
134
+ </div>
135
+ </div>
130
136
  <% end %>
@@ -28,6 +28,11 @@
28
28
 
29
29
  <div class="mt-10">
30
30
  <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 CATEGORY</button>
31
- <span class="text-lg ml-5"><a class="no-underline" href="<%= category.persisted? ? "#{root_path}?id=#{category.id}" : root_path %>">Cancel</a></span>
31
+ <% if category.persisted? %>
32
+ <button type="button" class="bg-red-700 text-gray-300 hover:bg-red-900 hover:text-white rounded py-2 px-3 font-bold ml-5" onclick="deleteCategory('<%= category.id %>');"><i data-feather="trash" class="inline h-5"></i> DELETE</button>
33
+ <% end %>
34
+ <span class="text-lg ml-5"><a class="no-underline" href="<%= category.persisted? ? "#{dokno.article_index_path(category.code)}" : root_path %>">Cancel</a></span>
32
35
  </div>
33
36
  </section>
37
+
38
+ <script> elem('input#name').focus(); </script>
@@ -1,20 +1,12 @@
1
-
2
- <div class="flex items-center mb-10">
3
- <% if Dokno::Category.exists? %>
4
- <div class="w-1/2 pr-5">
5
- <select name="category" id="category" size="1" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full max-w-full" onchange="location.href='<%= article_index_path %>' + this.value + '?search_term=' + elem('#search_term').value + '&order=<%= @order %>';">
6
- <option value="">Select a category</option>
7
- <%= Dokno::Category.select_option_markup(selected_category_codes: [@category&.code]).html_safe %>
8
- </select>
9
- </div>
10
- <% end %>
11
- <div class="w-<%= Dokno::Category.exists? ? '1/2 pl-5' : 'full' %>">
12
- <%= form_with(url: article_index_path(@category&.code), method: :get) do %>
13
- <input type="hidden" name="order" value="<%= @order %>">
14
- <input placeholder="Search article content, titles, and slugs" type="text" name="search_term" id="search_term" value="<%= @search_term %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full" />
15
- <% end %>
1
+ <% if @category&.parent.present? %>
2
+ <div class="text-gray-500 mb-5">
3
+ <div><%= @category.breadcrumb %></div>
16
4
  </div>
17
- </div>
5
+ <% end %>
6
+
7
+ <% if !current_page?(up_for_review_path) && (Dokno::Category.exists? || Dokno::Article.exists?) %>
8
+ <%= render 'partials/category_header' %>
9
+ <% end %>
18
10
 
19
11
  <% if @articles.blank? %>
20
12
 
@@ -40,44 +32,55 @@
40
32
  </div>
41
33
  <div class="w-1/3 text-right">
42
34
  <i data-feather="corner-right-down" class="h-5 inline-block" title="Sort order"></i>
43
- <a class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'updated' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=updated">Updated</a>
44
- <a class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'newest' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=newest">Newest</a>
45
- <a class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'views' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=views">Views</a>
46
- <a class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'alpha' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=alpha">Title</a>
35
+ <a id="dokno-order-link-updated" class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'updated' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=updated">Updated</a>
36
+ <a id="dokno-order-link-newest" class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'newest' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=newest">Newest</a>
37
+ <a id="dokno-order-link-views" class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'views' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=views">Views</a>
38
+ <a id="dokno-order-link-alpha" class="ml-3 pb-1 <%= 'border-b-2 border-blue-900' if @order == 'alpha' %>" href="?search_term=<%= CGI.escape @search_term.to_s %>&order=alpha">Title</a>
47
39
  </div>
48
40
  </div>
49
41
 
50
42
  <div id="dokno-article-list">
51
- <% @articles.each_with_index do |article, i| %>
43
+ <% @articles.each do |article| %>
52
44
  <section class="border-t border-gray-300 py-10 text-xl flex">
53
45
  <div class="w-1/3 pr-10">
54
46
  <div class="flex">
55
- <div class="no-print w-10 text-gray-300"><i data-feather="chevron-right" class="inline-block"></i></div>
47
+ <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>
56
48
  <div class="w-full">
57
- <a class="" href="<%= article_path article.slug %>?search_term=<%= @search_term %>" title="View article"><%= article.title %></a>
49
+ <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>
58
50
  </div>
59
51
  </div>
60
52
  </div>
61
53
  <div class="dokno-article-summary w-2/3 <% unless article.active %>text-gray-500 italic<% end %>">
62
54
  <% unless article.active %>
63
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">
64
- <i data-feather="alert-circle" class="inline-block"></i> This article is no longer active
56
+ <i data-feather="info" class="inline-block"></i> This article is no longer active
65
57
  </div>
66
58
  <% end %>
67
59
 
68
- <span class="dokno-article-content-highlight"><%= article.summary.presence || 'No summary provided' %></span>
69
-
70
- <div class="text-base mt-2">
71
- <div class="text-gray-500"><%= article.category_name_list(context_category_id: @category&.id, order: @order, search_term: @search_term) %></div>
60
+ <div class="dokno-article-content-highlight mb-2"><%= article.summary.presence || 'No summary provided' %></div>
72
61
 
73
- <% if @order == 'views' %>
74
- <div class="text-gray-500">Viewed <%= number_with_delimiter(article.views, delimiter: ',') %> <%= 'time'.pluralize(article.views) %></div>
75
- <% elsif @order == 'updated' %>
76
- <div class="text-gray-500">Last updated <%= time_ago_in_words article.updated_at %> ago</div>
77
- <% elsif @order == 'newest' %>
78
- <div class="text-gray-500">Added <%= time_ago_in_words article.created_at %> ago</div>
79
- <% end %>
62
+ <div class="text-base text-gray-500">
63
+ <%= article.category_name_list(context_category_id: @category&.id, order: @order, search_term: @search_term) %>
80
64
  </div>
65
+
66
+ <% unless @order == 'alpha' %>
67
+ <div class="text-base">
68
+ <% if @order == 'views' %>
69
+ <div class="text-gray-500">This article was viewed <%= number_with_delimiter(article.views, delimiter: ',') %> <%= 'time'.pluralize(article.views) %></div>
70
+ <% elsif @order == 'updated' %>
71
+ <div class="text-gray-500">This article was last updated <%= time_ago_in_words article.updated_at %> ago</div>
72
+ <% elsif @order == 'newest' %>
73
+ <div class="text-gray-500">This article was added <%= time_ago_in_words article.created_at %> ago</div>
74
+ <% end %>
75
+ </div>
76
+ <% end %>
77
+
78
+ <% if article.up_for_review? %>
79
+ <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">
80
+ <i data-feather="bell" class="inline-block mr-1"></i> <%= article.review_due_days_string %>
81
+ </div>
82
+ <% end %>
83
+
81
84
  </div>
82
85
  </section>
83
86
  <% end %>
@@ -91,6 +94,6 @@
91
94
  </div>
92
95
  <% end %>
93
96
 
94
- <% if @search_term.present? %>
95
- <script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight');</script>
97
+ <% if @search_term.present? && @articles.blank? %>
98
+ <script> handleSearchHotKey(); </script>
96
99
  <% 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
 
@@ -12,7 +14,7 @@
12
14
  var dokno__base_path = '<%= root_path %>';
13
15
  </script>
14
16
  </head>
15
- <body class="bg-white font-sans font-light subpixel-antialiased">
17
+ <body class="bg-white font-sans font-light subpixel-antialiased text-lg">
16
18
 
17
19
  <nav id="dokno-nav-container" class="bg-blue-900 text-white py-10 px-16 text-lg">
18
20
  <div class="flex items-center m-auto w-full max-w-screen-xl">
@@ -24,12 +26,12 @@
24
26
  <div class="w-2/3 text-right">
25
27
  <% if can_edit? %>
26
28
  <% 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-circle" class="inline h-5"></i> ARTICLE</button>
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-circle" class="inline h-5"></i> CATEGORY</button>
29
+ <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>
30
+ <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
31
  <% end %>
30
32
 
31
33
  <% 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>
34
+ <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
35
  <% end %>
34
36
  <% end %>
35
37
 
@@ -40,12 +42,19 @@
40
42
  </div>
41
43
  </nav>
42
44
 
45
+ <% flash.each do |type, msg| %>
46
+ <div class="bg-<%= type %>-800 text-lg text-white font-base py-10 px-16 text-center">
47
+ <i data-feather="<%= (type == 'green' ? 'smile' : (type == 'yellow' ? 'info' : (type == 'gray' ? 'bell' : 'frown'))) %>" class="inline mr-1"></i>
48
+ <%= sanitize(msg, tags: %w[a], attributes: %w[href class]) %>
49
+ </div>
50
+ <% end %>
51
+
43
52
  <main class="py-10 px-16">
44
- <% if @article.blank? && (@category.blank? || @search_term.present?) %>
53
+ <% if !current_page?(up_for_review_path) && @article.blank? && (@category.blank? || @search_term.present?) %>
45
54
  <div class="text-center m-auto mb-10 w-full max-w-screen-xl">
46
55
  <% if @search_term.present? %>
47
56
  <div class="text-gray-600 text-2xl uppercase">
48
- <%= (article_count = @articles.count).positive? ? "#{article_count} #{'article'.pluralize(article_count)}" : 'No articles' %>
57
+ <%= @total_records.positive? ? "#{@total_records} #{'article'.pluralize(@total_records)}" : 'No articles' %>
49
58
  found containing the search term
50
59
  <div class="text-4xl leading-tight"><span class="font-serif">&ldquo;</span> <%= @search_term %> <span class="font-serif">&rdquo;</span> </div>
51
60
  </div>
@@ -69,16 +78,29 @@
69
78
 
70
79
  <footer id="dokno-footer-container">
71
80
  <% if @article.present? && action_name == 'show' %>
72
- <div id="dokno-article-log-container" data-category-id="<%= @category&.id %>" data-article-id="<%= @article&.id %>">
81
+ <div id="dokno-article-log-container" data-category-id="<%= @category&.id %>" data-article-id="<%= @article.id %>">
73
82
  <%= render 'partials/logs', category: @category, article: @article %>
74
83
  </div>
75
84
  <% end %>
76
85
 
86
+ <% if can_edit? && !current_page?(up_for_review_path) && action_name == 'index' && (up_for_review_count = Dokno::Article.up_for_review.count).positive? %>
87
+ <div id="dokno-articles-up-for-review-container">
88
+ <div class="py-10 px-16 bg-gray-900">
89
+ <div class="w-full max-w-screen-xl m-auto">
90
+ <div class="text-xl text-white cursor-pointer" onclick="location.href='<%= up_for_review_path %>';">
91
+ <i data-feather="bell" class="inline mr-1"></i>
92
+ There <%= "#{up_for_review_count == 1 ? 'is' : 'are'} #{up_for_review_count}" %> <%= 'article'.pluralize(up_for_review_count) %> up for accuracy / relevance review
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ <% end %>
77
98
 
78
99
  <div class="py-10 px-16 text-gray-400 bg-blue-900">
79
100
  <div class="w-full max-w-screen-xl m-auto flex">
80
101
  <div class="w-1/2">
81
- <a target="_blank" href="https://github.com/cpayne624/dokno" title="Knowledgebase">dokno</a>
102
+ <i data-feather="github" class="inline mr-1"></i>
103
+ <a target="_blank" href="https://github.com/cpayne624/dokno" title="Dokno on GitHub">dokno</a>
82
104
  </div>
83
105
  <div class="w-1/2 text-right">
84
106
  <% if user.present? %>
@@ -92,9 +114,12 @@
92
114
  </div>
93
115
  </div>
94
116
  </div>
95
-
96
117
  </footer>
97
118
 
98
119
  <%= javascript_include_tag 'init' %>
120
+
121
+ <% if @search_term.present? %>
122
+ <script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight');</script>
123
+ <% end %>
99
124
  </body>
100
125
  </html>
@@ -0,0 +1,29 @@
1
+ <div class="no-print flex items-center mb-10">
2
+ <% if Dokno::Category.exists? %>
3
+ <div class="w-1/2 pr-5">
4
+ <select aria-label="Category" name="category" id="category" size="1" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full max-w-full" onchange="applyCategoryCriteria(this.value, elem('#search_term').value, '<%= @order %>');">
5
+ <option value="">Uncategorized</option>
6
+
7
+ <optgroup label="Categories">
8
+ <% cache Dokno::Category do %>
9
+ <%= Dokno::Category.select_option_markup.html_safe %>
10
+ <% end %>
11
+ </optgroup>
12
+ </select>
13
+ </div>
14
+ <% end %>
15
+
16
+ <% if Dokno::Article.exists? %>
17
+ <div class="relative w-<%= Dokno::Category.exists? ? '1/2 pl-5' : 'full' %>">
18
+ <i data-feather="search" class="absolute ml-4 mt-3 inline-block text-gray-300" title="Search"></i>
19
+ <input title="Press / to search" onsearch="applyCategoryCriteria('<%= @category&.code %>', this.value, '<%= @order %>');" onfocus="disableSearchHotkey();" onblur="enableSearchHotkey();" placeholder="Search<%= @category.present? ? ' under this category' : ', hotkey /' %>" type="search" name="search_term" id="search_term" value="<%= @search_term %>" class="pl-12 pr-8 py-2 rounded text-xl shadow-inner bg-gray-100 w-full" />
20
+ <% if @category.present? %><div title="Press / to search" class="absolute -ml-6 mt-2 inline-block text-gray-300 font-semibold">/</div><% end %>
21
+ </div>
22
+ <% end %>
23
+ </div>
24
+
25
+ <script>
26
+ // Client-side select of cached select list
27
+ selectOption('category', '<%= j @category&.code %>');
28
+ enableSearchHotkey();
29
+ </script>
@@ -1,5 +1,4 @@
1
1
  <div id="error_explanation" class="bg-white mb-10">
2
- <i data-feather="alert-octagon" class="float-right"></i>
3
2
  <h2 class="font-semibold">
4
3
  There
5
4
  <% if errors.count == 1 %>
@@ -2,7 +2,7 @@
2
2
  <div class="py-10 px-16 text-gray-200 bg-gray-900">
3
3
  <div class="w-full max-w-screen-xl m-auto">
4
4
  <div class="text-xl text-gray-600 cursor-pointer" onclick="toggleVisibility('change-log');">
5
- Change log for this article
5
+ Change history for this article
6
6
 
7
7
  <div class="inline toggle-visibility-indicator-container change-log">
8
8
  <i data-feather="chevron-left" class="inline toggle-visibility-indicator change-log"></i>
@@ -20,7 +20,7 @@
20
20
  <% end %>
21
21
 
22
22
  <div class="text-gray-500 bg-gray-700 p-5 pr-10 rounded <%= 'cursor-pointer' if log.diff_left != log.diff_right %> flex items-center" onclick="toggleVisibility('article-diff-<%= log.id %>');" title="Show / Hide Diff">
23
- <div class="w-4/5">
23
+ <div class="w-<%= log.diff_left != log.diff_right ? '11/12' : 'full' %>">
24
24
  <%= time_ago_in_words log.created_at %> ago
25
25
  <% if log.username.present? %>
26
26
  by <%= log.username %>
@@ -31,9 +31,11 @@
31
31
  <% end %>
32
32
  </div>
33
33
 
34
- <div class="w-1/5 text-right toggle-visibility-indicator-container article-diff-<%= log.id %>">
35
- <% if log.diff_left != log.diff_right %><i data-feather="chevron-left" class="inline toggle-visibility-indicator article-diff-<%= log.id %>"></i><% end %>
36
- </div>
34
+ <% if log.diff_left != log.diff_right %>
35
+ <div class="w-1/12 text-right toggle-visibility-indicator-container article-diff-<%= log.id %>">
36
+ <i data-feather="chevron-left" class="inline toggle-visibility-indicator article-diff-<%= log.id %>"></i>
37
+ </div>
38
+ <% end %>
37
39
  </div>
38
40
 
39
41
  <% if log.diff_left != log.diff_right %>
@@ -1,29 +1,31 @@
1
- <span class="mr-5">
2
- <% if @page > 1 %>
3
- <span class="mr-1 inline-block"><a href="?search_term=<%= CGI.escape @search_term.to_s %>&order=<%= @order %>&page=<%= (@page - 1) %>"><i data-feather="arrow-left" class="h-5 inline-block" title="Previous page"></i></a></span>
4
- <% end %>
1
+ <% if @total_pages > 1 %>
2
+ <span class="mr-5">
3
+ <% if @page > 1 %>
4
+ <span class="mr-1 inline-block"><a href="?search_term=<%= CGI.escape @search_term.to_s %>&order=<%= @order %>&page=<%= (@page - 1) %>"><i data-feather="arrow-left" class="h-5 inline-block" title="Previous page"></i></a></span>
5
+ <% end %>
5
6
 
6
- <span class="mr-1 inline-block">Page</span>
7
+ <span class="mr-1 inline-block">Page</span>
7
8
 
8
- <%= form_with(url: article_index_path, method: :get, class: 'inline') do %>
9
- <input type="hidden" name="id" value="<%= @category&.id %>">
10
- <input type="hidden" name="search_term" value="<%= @search_term %>">
11
- <input type="hidden" name="order" value="<%= @order %>">
12
- <input type="text" name="page" id="page" value="<%= @page %>" onclick="this.select();" class="w-10 text-center bg-gray-200 rounded" />
9
+ <%= form_with(url: article_index_path(@category&.code), method: :get, class: 'inline') do %>
10
+ <input type="hidden" name="search_term" value="<%= @search_term %>">
11
+ <input type="hidden" name="order" value="<%= @order %>">
12
+ <input aria-label="Page" type="text" name="page" value="<%= @page %>" onclick="this.select();" class="w-10 text-center bg-gray-200 rounded" />
13
13
 
14
- <span class="mx-1 inline-block">of</span>
15
- <span class="text-center inline-block"><%= @total_pages %></span>
16
- <% end %>
14
+ <span class="mx-1 inline-block">of</span>
15
+ <span class="text-center inline-block"><%= @total_pages %></span>
16
+ <% end %>
17
17
 
18
- <% if @page < @total_pages %>
19
- <span class="ml-1 inline-block"><a href="?search_term=<%= CGI.escape @search_term.to_s %>&order=<%= @order %>&page=<%= (@page + 1) %>"><i data-feather="arrow-right" class="h-5 inline-block" title="Next page"></i></a></span>
20
- <% end %>
21
- </span>
18
+ <% if @page < @total_pages %>
19
+ <span class="ml-1 inline-block"><a href="?search_term=<%= CGI.escape @search_term.to_s %>&order=<%= @order %>&page=<%= (@page + 1) %>"><i data-feather="arrow-right" class="h-5 inline-block" title="Next page"></i></a></span>
20
+ <% end %>
21
+ </span>
22
+ <% end %>
22
23
 
23
24
  <span class="text-gray-400">
24
25
  <%= @total_records %>
25
- <%= 'uncategorized' if @category.blank? && @search_term.blank? %>
26
+ <%= 'uncategorized' if !current_page?(up_for_review_path) && @category.blank? && @search_term.blank? %>
26
27
  <%= 'article'.pluralize(@total_records) %>
28
+ <%= 'up for review' if current_page?(up_for_review_path) %>
27
29
 
28
30
  <% if @search_term.present? %>
29
31
  containing <span class="font-serif">&ldquo;</span><%= @search_term %><span class="font-serif">&rdquo;</span>