dokno 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +130 -0
  4. data/Rakefile +22 -0
  5. data/app/assets/config/dokno_manifest.js +3 -0
  6. data/app/assets/javascripts/dokno.js +144 -0
  7. data/app/assets/javascripts/dokno/application.js +15 -0
  8. data/app/assets/javascripts/feather.min.js +13 -0
  9. data/app/assets/javascripts/init.js +5 -0
  10. data/app/assets/stylesheets/dokno/application.css +137 -0
  11. data/app/assets/stylesheets/dokno/tailwind.min.css +1 -0
  12. data/app/controllers/dokno/application_controller.rb +7 -0
  13. data/app/controllers/dokno/articles_controller.rb +115 -0
  14. data/app/controllers/dokno/categories_controller.rb +63 -0
  15. data/app/controllers/dokno/pagination_concern.rb +15 -0
  16. data/app/controllers/dokno/user_concern.rb +38 -0
  17. data/app/helpers/dokno/application_helper.rb +17 -0
  18. data/app/models/dokno/application_record.rb +5 -0
  19. data/app/models/dokno/article.rb +215 -0
  20. data/app/models/dokno/article_slug.rb +7 -0
  21. data/app/models/dokno/category.rb +100 -0
  22. data/app/models/dokno/log.rb +7 -0
  23. data/app/views/dokno/_article_formatting.html.erb +89 -0
  24. data/app/views/dokno/_article_panel.html.erb +112 -0
  25. data/app/views/dokno/_panel_formatting.html.erb +95 -0
  26. data/app/views/dokno/_reset_formatting.html.erb +55 -0
  27. data/app/views/dokno/articles/_article_form.html.erb +60 -0
  28. data/app/views/dokno/articles/edit.html.erb +7 -0
  29. data/app/views/dokno/articles/new.html.erb +7 -0
  30. data/app/views/dokno/articles/show.html.erb +130 -0
  31. data/app/views/dokno/categories/_category_form.html.erb +33 -0
  32. data/app/views/dokno/categories/edit.html.erb +7 -0
  33. data/app/views/dokno/categories/index.html.erb +96 -0
  34. data/app/views/dokno/categories/new.html.erb +7 -0
  35. data/app/views/layouts/dokno/application.html.erb +100 -0
  36. data/app/views/partials/_form_errors.html.erb +18 -0
  37. data/app/views/partials/_logs.html.erb +52 -0
  38. data/app/views/partials/_pagination.html.erb +35 -0
  39. data/config/routes.rb +11 -0
  40. data/db/migrate/20201203190330_baseline.rb +62 -0
  41. data/lib/dokno.rb +4 -0
  42. data/lib/dokno/config/config.rb +73 -0
  43. data/lib/dokno/engine.rb +27 -0
  44. data/lib/dokno/version.rb +3 -0
  45. data/lib/generators/dokno/install/install_generator.rb +13 -0
  46. data/lib/generators/dokno/templates/config/dokno_template.md +5 -0
  47. data/lib/generators/dokno/templates/config/initializers/dokno.rb +14 -0
  48. data/lib/tasks/dokno_tasks.rake +4 -0
  49. metadata +253 -0
@@ -0,0 +1,60 @@
1
+ <%= render 'dokno/article_formatting' %>
2
+
3
+ <section class="mb-10">
4
+
5
+ <div class="text-2xl mb-5 text-gray-500"><%= article.persisted? ? 'Edit' : 'New' %> Article</div>
6
+ <h1 class="text-4xl mb-5 leading-tight font-light"><%= article.title %></h1>
7
+ <hr class="mb-5" />
8
+
9
+ <div class="mb-5">
10
+ <div class="text-lg font-semibold"><label for="slug">Slug</label></div>
11
+ <input placeholder="Article unique identifier" type="text" name="slug" id="slug" value="<%= article.slug %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 mt-2 w-1/3" />
12
+ <div class="text-gray-500 mt-2">Unique identifier for this article (required) (2-20 alphanumeric chars)</div>
13
+ </div>
14
+
15
+ <% if Dokno::Category.exists? %>
16
+ <div class="mb-5">
17
+ <div class="text-lg font-semibold"><label for="category_id"><%= 'Category'.pluralize article.categories.count %></label></div>
18
+ <select name="category_code[]" id="category_code" multiple="multiple" size="<%= (cat_count = Dokno::Category.count) <= 4 ? (cat_count + 1).to_s : '5' %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 w-full mt-2 w-full max-w-full">
19
+ <option></option>
20
+ <%= Dokno::Category.select_option_markup(selected_category_codes: @category_codes).html_safe %>
21
+ </select>
22
+ <div class="text-gray-500 mt-2">
23
+ If applicable, select one or more categories to which this article will belong (optional). CTRL/CMD to select multiple.
24
+ Articles will be automatically included in parent categories. Uncategorized articles
25
+ are displayed on the landing page.
26
+ </div>
27
+ </div>
28
+ <% end %>
29
+
30
+ <hr class="mb-5" />
31
+
32
+ <div class="mb-5">
33
+ <div class="text-lg font-semibold"><label for="title">Title</label></div>
34
+ <input placeholder="Article title" type="text" name="title" id="title" value="<%= article.title %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 mt-2 w-1/2" />
35
+ <div class="text-gray-500 mt-2">Descriptive article title (required) (5-255 alphanumeric chars)</div>
36
+ </div>
37
+
38
+ <div class="mb-5">
39
+ <div class="text-lg font-semibold"><label for="summary">Summary</label></div>
40
+ <input placeholder="Brief article summary" type="text" name="summary" id="summary" value="<%= article.summary %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 mt-2 w-full" />
41
+ <div class="text-gray-500 mt-2">Brief summary of the described topic (text only)</div>
42
+ </div>
43
+
44
+ <div class="mb-5">
45
+ <div class="text-lg font-semibold">
46
+ <label for="markdown">Content</label>
47
+ <a id="markdown_write_link" href="javascript:;" onclick="writeArticleToggle();" class="float-right hidden"><i data-feather="pen-tool" class="inline"></i> Write</a>
48
+ <a id="markdown_preview_link" href="javascript:;" onclick="previewArticleToggle();" class="float-right"><i data-feather="eye" class="inline"></i> Preview</a>
49
+ </div>
50
+ <textarea placeholder="Full article content" name="markdown" id="markdown" class="rounded text-xl shadow-inner bg-gray-100 p-3 mt-2 w-full" rows="10"><%= article.persisted? ? article.markdown : (article.markdown.presence || @template) %></textarea>
51
+ <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
+ <div class="text-gray-500 mt-2">Detailed documentation of the described topic. Basic HTML &amp; <a target="_blank" href="https://commonmark.org/help/" title="Markdown formatting examples">markdown</a> OK.</div>
53
+ </div>
54
+
55
+ <div class="mt-10">
56
+ <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
+ </div>
59
+
60
+ </section>
@@ -0,0 +1,7 @@
1
+ <%= form_with(model: @article, local: true) do |form| %>
2
+ <% if @article.errors.any? %>
3
+ <%= render 'partials/form_errors', errors: @article.errors %>
4
+ <% end %>
5
+
6
+ <%= render 'article_form', article: @article %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%= form_with(url: articles_path) do %>
2
+ <% if @article.errors.any? %>
3
+ <%= render 'partials/form_errors', errors: @article.errors %>
4
+ <% end %>
5
+
6
+ <%= render 'article_form', article: @article %>
7
+ <% end %>
@@ -0,0 +1,130 @@
1
+ <%= render 'dokno/article_formatting' %>
2
+
3
+ <section>
4
+ <div class="flex">
5
+ <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>
11
+
12
+ <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 %>
20
+ </div>
21
+
22
+ <div class="flex">
23
+ <div class="no-print w-8"><i data-feather="clock" class="inline-block h-5"></i></div>
24
+ <div class="w-full">
25
+ Last updated:<br />
26
+ <%= time_ago_in_words @article.updated_at %> ago
27
+ <% if (editor_username = @article.logs.first&.username).present? %>
28
+ by <%= editor_username %>
29
+ <% end %>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="mt-5 flex">
34
+ <div class="no-print w-8"><i data-feather="eye" class="inline-block h-5"></i></div>
35
+ <div class="w-full">
36
+ Views:<br />
37
+ <%= number_with_delimiter(@article.views, delimiter: ',') %>
38
+ </div>
39
+ </div>
40
+
41
+ <% if @article.contributors.present? %>
42
+ <div class="mt-5 flex">
43
+ <div class="no-print w-8"><i data-feather="user-check" class="inline-block h-5"></i></div>
44
+ <div class="w-full">
45
+ Contributors:<br />
46
+ <%= @article.contributors %>
47
+ </div>
48
+ </div>
49
+ <% end %>
50
+
51
+ <% 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>
54
+ <div class="w-full">
55
+ Reading time:<br />
56
+ <%= @article.reading_time %>
57
+ </div>
58
+ </div>
59
+ <% end %>
60
+
61
+ <div class="mt-5 flex">
62
+ <div class="no-print w-8"><i data-feather="link" class="inline-block h-5"></i></div>
63
+ <div class="w-full">
64
+ Permalink:<br />
65
+ <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>
66
+ </div>
67
+ </div>
68
+
69
+ <% 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>
72
+ <div class="w-full">
73
+ Unique slug:<br />
74
+ <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>
75
+
76
+ <% if (old_slugs = @article.article_slugs).present? %>
77
+ <div class="text-gray-500 mt-5">
78
+ Editor note:<br />
79
+ This article is still accessible via previous
80
+ <%= 'slug'.pluralize(old_slugs.count) %>
81
+ <%= old_slugs.map(&:slug).reject { |slug| slug == @article.slug }.to_sentence %>
82
+ </div>
83
+ <% end %>
84
+ </div>
85
+ </div>
86
+ <% end %>
87
+
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>
91
+ <div class="w-full">
92
+ <%= 'Category'.pluralize @article.categories.count %>:<br />
93
+ <%= @article.category_name_list.split(':').last.html_safe %>
94
+ </div>
95
+ </div>
96
+ <% end %>
97
+ </div>
98
+ </div>
99
+ <div id="dokno-article-content" class="dokno-article-content-highlight w-3/5">
100
+ <% if @article.summary.present? %>
101
+ <div class="text-2xl mb-8 text-gray-700 font-light"><%= simple_format @article.summary %></div>
102
+ <% end %>
103
+
104
+ <% if @article.markdown.present? %>
105
+ <div id="dokno-article-content-markup" class="dokno-article-content-markup text-gray-800 font-light mb-10 bg-gray-100 p-10 rounded">
106
+ <%= @article.markdown_parsed %>
107
+ </div>
108
+ <% end %>
109
+
110
+ <% if @article.summary.blank? && @article.markdown.blank? %>
111
+ <div class="mb-10">No content</div>
112
+ <% 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
+ </div>
125
+ </div>
126
+ </section>
127
+
128
+ <% if @search_term.present? %>
129
+ <script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight');</script>
130
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <section class="mb-10">
2
+
3
+ <div class="text-2xl mb-5 text-gray-500"><%= category.persisted? ? 'Edit' : 'New' %> Category</div>
4
+ <hr class="mb-5" />
5
+
6
+ <div class="mb-5">
7
+ <div class="text-lg font-semibold"><label for="name">Category Name</label></div>
8
+ <input type="text" name="name" id="name" value="<%= category.name %>" class="rounded text-xl shadow-inner bg-gray-100 p-2 mt-2 w-1/3" />
9
+ <div class="text-gray-500 mt-2">Unique name for this category (required)</div>
10
+ </div>
11
+
12
+ <% if Dokno::Category.exists? %>
13
+ <div class="mb-5">
14
+ <div class="text-lg font-semibold"><label for="parent_category_code">Parent Category</label></div>
15
+ <select name="parent_category_code" id="parent_category_code" class="rounded text-xl shadow-inner bg-gray-100 p-2 mt-2 w-1/2 max-w-full">
16
+ <option></option>
17
+ <%= Dokno::Category.select_option_markup(selected_category_codes: [@parent_category_code], exclude_category_id: category.id).html_safe %>
18
+ </select>
19
+ <div class="text-gray-500 mt-2 w-1/2">
20
+ The existing category to which this category belongs.
21
+ <% if (article_count = category.articles.count).positive? %>
22
+ There <%= article_count > 1 ? "are #{article_count} articles" : 'is an article' %> currently in this category.
23
+ Changing the parent category will move <%= article_count > 1 ? 'them' : 'it' %> as well.
24
+ <% end %>
25
+ </div>
26
+ </div>
27
+ <% end %>
28
+
29
+ <div class="mt-10">
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>
32
+ </div>
33
+ </section>
@@ -0,0 +1,7 @@
1
+ <%= form_with(model: @category, local: true) do |form| %>
2
+ <% if @category.errors.any? %>
3
+ <%= render 'partials/form_errors', errors: @category.errors %>
4
+ <% end %>
5
+
6
+ <%= render 'category_form', category: @category %>
7
+ <% end %>
@@ -0,0 +1,96 @@
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 %>
16
+ </div>
17
+ </div>
18
+
19
+ <% if @articles.blank? %>
20
+
21
+ <section class="border-t border-gray-300 py-10 text-xl">
22
+ <% if Dokno::Category.exists? %>
23
+ <% if @search_term.present? %>
24
+ No articles found <% if @category.present? %>in this category<% end %> matching the given search criteria
25
+ <% elsif @category.present? %>
26
+ No articles found in this category
27
+ <% else %>
28
+ No uncategorized articles
29
+ <% end %>
30
+ <% elsif can_edit? %>
31
+ <a href="<%= new_category_path(@category&.id) %>">Add your first category</a>
32
+ <% end %>
33
+ </section>
34
+
35
+ <% else %>
36
+
37
+ <div id="dokno-article-list-controls-top" class="flex mb-10">
38
+ <div class="w-2/3">
39
+ <%= render 'partials/pagination' %>
40
+ </div>
41
+ <div class="w-1/3 text-right">
42
+ <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>
47
+ </div>
48
+ </div>
49
+
50
+ <div id="dokno-article-list">
51
+ <% @articles.each_with_index do |article, i| %>
52
+ <section class="border-t border-gray-300 py-10 text-xl flex">
53
+ <div class="w-1/3 pr-10">
54
+ <div class="flex">
55
+ <div class="no-print w-10 text-gray-300"><i data-feather="chevron-right" class="inline-block"></i></div>
56
+ <div class="w-full">
57
+ <a class="" href="<%= article_path article.slug %>?search_term=<%= @search_term %>" title="View article"><%= article.title %></a>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ <div class="dokno-article-summary w-2/3 <% unless article.active %>text-gray-500 italic<% end %>">
62
+ <% unless article.active %>
63
+ <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
65
+ </div>
66
+ <% end %>
67
+
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>
72
+
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 %>
80
+ </div>
81
+ </div>
82
+ </section>
83
+ <% end %>
84
+ </div>
85
+
86
+ <div id="dokno-article-list-controls-bottom" class="flex mt-10">
87
+ <div class="w-2/3">
88
+ <%= render 'partials/pagination' %>
89
+ </div>
90
+ <div class="w-1/3 text-right"></div>
91
+ </div>
92
+ <% end %>
93
+
94
+ <% if @search_term.present? %>
95
+ <script>highlightTerm(['<%= j @search_term.strip %>'], 'dokno-article-content-highlight');</script>
96
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%= form_with(url: categories_path) do %>
2
+ <% if @category.errors.any? %>
3
+ <%= render 'partials/form_errors', errors: @category.errors %>
4
+ <% end %>
5
+
6
+ <%= render 'category_form', category: @category %>
7
+ <% end %>
@@ -0,0 +1,100 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= Dokno.config.app_name %> KNOWLEDGEBASE</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "dokno/application", media: "all" %>
9
+ <%= javascript_include_tag 'dokno/application' %>
10
+
11
+ <script>
12
+ var dokno__base_path = '<%= root_path %>';
13
+ </script>
14
+ </head>
15
+ <body class="bg-white font-sans font-light subpixel-antialiased">
16
+
17
+ <nav id="dokno-nav-container" class="bg-blue-900 text-white py-10 px-16 text-lg">
18
+ <div class="flex items-center m-auto w-full max-w-screen-xl">
19
+ <div class="w-1/3">
20
+ <a href="<%= root_path %>">
21
+ <span class="font-semibold uppercase"><%= Dokno.config.app_name %> KNOWLEDGEBASE</span>
22
+ </a>
23
+ </div>
24
+ <div class="w-2/3 text-right">
25
+ <% if can_edit? %>
26
+ <% 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
+ <% end %>
30
+
31
+ <% 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>
33
+ <% end %>
34
+ <% end %>
35
+
36
+ <% if action_name != 'edit' %>
37
+ <button class="bg-green-700 text-gray-300 hover:text-white hover:bg-green-800 rounded ml-3 py-2 px-3 font-bold text-base" onclick="window.open('/');"><i data-feather="log-out" class="inline h-5"></i> GO TO APP</button>
38
+ <% end %>
39
+ </div>
40
+ </div>
41
+ </nav>
42
+
43
+ <main class="py-10 px-16">
44
+ <% if @article.blank? && (@category.blank? || @search_term.present?) %>
45
+ <div class="text-center m-auto mb-10 w-full max-w-screen-xl">
46
+ <% if @search_term.present? %>
47
+ <div class="text-gray-600 text-2xl uppercase">
48
+ <%= (article_count = @articles.count).positive? ? "#{article_count} #{'article'.pluralize(article_count)}" : 'No articles' %>
49
+ found containing the search term
50
+ <div class="text-4xl leading-tight"><span class="font-serif">&ldquo;</span> <%= @search_term %> <span class="font-serif">&rdquo;</span> </div>
51
+ </div>
52
+ <% else %>
53
+ <div class="text-gray-600 text-2xl">
54
+ Browse or search
55
+ <% if (article_count = Dokno::Article.count) > 1 %>
56
+ <%= number_with_delimiter(article_count, delimiter: ',') %> articles in
57
+ <% end %>
58
+ the
59
+ </div>
60
+ <div class="text-gray-800 text-4xl leading-tight uppercase"><%= Dokno.config.app_name %> knowledgebase</div>
61
+ <% end %>
62
+ </div>
63
+ <% end %>
64
+
65
+ <div id="dokno-content-container" class="w-full max-w-screen-xl m-auto print-this">
66
+ <%= yield %>
67
+ </div>
68
+ </main>
69
+
70
+ <footer id="dokno-footer-container">
71
+ <% if @article.present? && action_name == 'show' %>
72
+ <div id="dokno-article-log-container" data-category-id="<%= @category&.id %>" data-article-id="<%= @article&.id %>">
73
+ <%= render 'partials/logs', category: @category, article: @article %>
74
+ </div>
75
+ <% end %>
76
+
77
+
78
+ <div class="py-10 px-16 text-gray-400 bg-blue-900">
79
+ <div class="w-full max-w-screen-xl m-auto flex">
80
+ <div class="w-1/2">
81
+ <a target="_blank" href="https://github.com/cpayne624/dokno" title="Knowledgebase">dokno</a>
82
+ </div>
83
+ <div class="w-1/2 text-right">
84
+ <% if user.present? %>
85
+ <span title="<%= Dokno.config.app_name %> Authenticated User" class="mr-10">
86
+ <i data-feather="user<%= '-check' if can_edit? %>" class="inline-block h-5"></i> <span class="text-white"><%= username %></span>
87
+ (<%= can_edit? ? 'Editor' : 'Read Only' %>)
88
+ </span>
89
+ <% end %>
90
+
91
+ <a href="/" target="_blank" title="Go to the app" class="font-semibold"><%= Dokno.config.app_name %></a>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ </footer>
97
+
98
+ <%= javascript_include_tag 'init' %>
99
+ </body>
100
+ </html>