dokno 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08352501c3a71f5edef7bd7bf311d8459dc5d38adc20dff5540f755bf04033b6'
4
- data.tar.gz: 19aedf91902b6fc6e30378074740578c347041702d849999a7c62c4a0fff53cd
3
+ metadata.gz: df8bbd2d17e134f0298f31fc97d049b245c4830e9d44655a8c4659507c6ebe6f
4
+ data.tar.gz: bdeb9513295036198a8f30a476a1ea8a4c34d35330c9e6e75e2364aadddf0b3b
5
5
  SHA512:
6
- metadata.gz: f44728981b2004cb703d75641f72f02dc0cf4e92b697ae10d8ef69f1e1b099aa536499c139ae6931748331bbfe3c77bbcbeb3395e59b7fa99398aaeb45b25761
7
- data.tar.gz: 32a8b4f6cbf26d8ef35a6894e3d668f10b81f085c47b65fa44abba17fec7fa337c7e917a532af45bf258c80ecdf869c3ec48cdd6386f96e3e029e3100ee84776
6
+ metadata.gz: 97c1353f3c85e9a6e40de60a0947101978bb101b0dc85be48945ee7e54bb13596fd0f1afbd011113f538c5dfe0ed8784c09c87643b5813e5021292c49244273b
7
+ data.tar.gz: 1bfda031b688b21b65fc8b43fd550e006fec2d5b5f1fd50d4f536db9724ef4853ed47f49e8b2e3ed3329f9ecd6092eb2d678dc6562fa1c07d092da0412ff1e12
@@ -61,6 +61,17 @@ function deleteArticle(id) {
61
61
  sendRequest(dokno__base_path + 'articles/' + id, {}, callback, 'DELETE');
62
62
  }
63
63
 
64
+ function deleteCategory(id) {
65
+ if (!confirm('Delete Category\n\nThis will remove this category. Any articles in this category will become uncategorized and appear on the home page until re-categorized.')) {
66
+ return true;
67
+ }
68
+
69
+ const callback = function(_data) {
70
+ location.href = dokno__base_path;
71
+ }
72
+ sendRequest(dokno__base_path + 'categories/' + id, {}, callback, 'DELETE');
73
+ }
74
+
64
75
  function previewArticleToggle() {
65
76
  const markdown = elem('div#dokno-content-container textarea#markdown').value;
66
77
  const callback = function(data) {
@@ -1,7 +1,10 @@
1
1
  module Dokno
2
2
  class ApplicationController < ::ApplicationController
3
3
  protect_from_forgery with: :exception
4
+
4
5
  include UserConcern
5
6
  include PaginationConcern
7
+
8
+ add_flash_types :green, :yellow, :red
6
9
  end
7
10
  end
@@ -27,9 +27,11 @@ module Dokno
27
27
  set_editor_username
28
28
 
29
29
  if @article.save
30
+ flash[:green] = 'Article was created'
30
31
  @article.categories = Category.where(code: params[:category_code]) if params[:category_code].present?
31
32
  redirect_to article_path @article.slug
32
33
  else
34
+ flash.now[:red] = 'Article could not be created'
33
35
  @category_codes = params[:category_code]
34
36
  render :new
35
37
  end
@@ -42,9 +44,11 @@ module Dokno
42
44
  set_editor_username
43
45
 
44
46
  if @article.update(article_params)
47
+ flash[:green] = 'Article was updated'
45
48
  @article.categories = Category.where(code: params[:category_code])
46
49
  redirect_to article_path @article.slug
47
50
  else
51
+ flash.now[:red] = 'Article could not be updated'
48
52
  @category_codes = params[:category_code]
49
53
  render :edit
50
54
  end
@@ -52,6 +56,8 @@ module Dokno
52
56
 
53
57
  def destroy
54
58
  Article.find(params[:id].to_i).destroy!
59
+
60
+ flash[:green] = 'Article was deleted'
55
61
  render json: {}, layout: false
56
62
  end
57
63
 
@@ -35,8 +35,10 @@ module Dokno
35
35
  @category = Category.new(name: params[:name], parent: Category.find_by(code: params[:parent_category_code]))
36
36
 
37
37
  if @category.save
38
+ flash[:green] = 'Category was created'
38
39
  redirect_to article_index_path(@category.code)
39
40
  else
41
+ flash.now[:red] = 'Category could not be created'
40
42
  @parent_category_code = params[:parent_category_code]
41
43
  render :new
42
44
  end
@@ -46,13 +48,22 @@ module Dokno
46
48
  return redirect_to root_path if @category.blank?
47
49
 
48
50
  if @category.update(name: params[:name], parent: Category.find_by(code: params[:parent_category_code]))
51
+ flash[:green] = 'Category was updated'
49
52
  redirect_to article_index_path(@category.code)
50
53
  else
54
+ flash.now[:red] = 'Category could not be updated'
51
55
  @parent_category_code = params[:parent_category_code]
52
56
  render :edit
53
57
  end
54
58
  end
55
59
 
60
+ def destroy
61
+ Category.find(params[:id].to_i).destroy!
62
+
63
+ flash[:green] = 'Category was deleted'
64
+ render json: {}, layout: false
65
+ end
66
+
56
67
  private
57
68
 
58
69
  def fetch_category
@@ -9,9 +9,7 @@ module Dokno
9
9
 
10
10
  return "Dokno article slug '#{slug}' not found" if article.blank?
11
11
 
12
- %Q(
13
- <a href="javascript:;" onclick="doknoOpenPanel('#{j article.slug}');">#{link_text.presence || article.title}</a>
14
- ).html_safe
12
+ %Q(<a href="javascript:;" onclick="doknoOpenPanel('#{j article.slug}');">#{link_text.presence || article.title}</a>).html_safe
15
13
  end
16
14
  end
17
15
  end
@@ -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]
@@ -71,19 +73,40 @@ module Dokno
71
73
  categories.flatten
72
74
  end
73
75
 
74
- # HTML markup for Category SELECT field OPTION lists
75
- def self.select_option_markup(selected_category_codes: nil, exclude_category_id: nil)
76
- breadcrumbs = all
77
- .reject { |category| category.id == exclude_category_id.to_i }
78
- .map { |category| { code: category.code, name: category.breadcrumb } }
79
- breadcrumbs.sort_by { |category_hash| category_hash[:name] }.map do |category_hash|
80
- selected = selected_category_codes&.include?(category_hash[:code])
81
- %(<option value="#{category_hash[:code]}" #{'selected="selected"' if selected}>#{category_hash[:name]}</option>)
82
- end.join
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
+ %(<option value="#{category.code}" #{'selected="selected"' if selected}>#{('&nbsp;&nbsp;' * level)}#{category.name}</option>)
108
+ end
109
+
87
110
  # Never allow setting of parent to self
88
111
  def circular_parent_check
89
112
  return unless persisted? && id.to_i == category_id.to_i
@@ -67,6 +67,7 @@
67
67
 
68
68
  // Close on escape
69
69
  document.addEventListener('keydown', dokno__keydown_listener, false);
70
+ document.addEventListener('click', dokno__click_listener, false);
70
71
  }
71
72
  };
72
73
 
@@ -78,6 +79,7 @@
78
79
  dokno__panel.classList.remove('open');
79
80
  document.body.classList.remove('dokno-no-scroll');
80
81
  document.removeEventListener('keydown', dokno__keydown_listener, false);
82
+ document.removeEventListener('click', dokno__click_listener, false);
81
83
 
82
84
  dokno__slug = null;
83
85
  }
@@ -106,6 +108,11 @@
106
108
  if (e.key === 'Escape') { doknoClosePanel(); }
107
109
  }
108
110
 
111
+ const dokno__click_listener = function(e) {
112
+ var isClickInside = dokno__panel.contains(e.target);
113
+ if (!isClickInside) { doknoClosePanel(); }
114
+ }
115
+
109
116
  dokno__close.onclick = function() { doknoClosePanel(); }
110
117
 
111
118
  var dokno__id, dokno__slug;
@@ -58,3 +58,5 @@
58
58
  </div>
59
59
 
60
60
  </section>
61
+
62
+ <script> elem('input#slug').focus(); </script>
@@ -1,6 +1,14 @@
1
1
  <%= render 'dokno/article_formatting' %>
2
2
 
3
3
  <section>
4
+ <% if @article.categories.present? %>
5
+ <div class="text-gray-500 mb-5">
6
+ <% @article.categories.each do |category| %>
7
+ <div><a href="<%= article_index_path(category.code) %>"><%= category.breadcrumb %></a></div>
8
+ <% end %>
9
+ </div>
10
+ <% end %>
11
+
4
12
  <div class="flex">
5
13
  <div id="dokno-article-sidebar" class="w-2/5 pr-10">
6
14
  <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">
@@ -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
+ <% 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 %>
31
34
  <span class="text-lg ml-5"><a class="no-underline" href="<%= category.persisted? ? "#{root_path}?id=#{category.id}" : root_path %>">Cancel</a></span>
32
35
  </div>
33
36
  </section>
37
+
38
+ <script> elem('input#name').focus(); </script>
@@ -1,3 +1,8 @@
1
+ <% if @category&.parent.present? %>
2
+ <div class="text-gray-500 mb-5">
3
+ <div><%= @category.breadcrumb %></div>
4
+ </div>
5
+ <% end %>
1
6
 
2
7
  <div class="flex items-center mb-10">
3
8
  <% if Dokno::Category.exists? %>
@@ -63,6 +63,13 @@
63
63
  <% end %>
64
64
 
65
65
  <div id="dokno-content-container" class="w-full max-w-screen-xl m-auto print-this">
66
+ <% flash.each do |color, msg| %>
67
+ <div class="bg-<%= color %>-700 p-4 mb-5 rounded text-lg border-t-4 border-<%= color %>-900 text-white font-base">
68
+ <i data-feather="<%= (color == 'green' ? 'check-circle' : (color == 'yellow' ? 'alert-circle' : 'x-circle')) %>" class="inline mr-2"></i>
69
+ <%= msg %>
70
+ </div>
71
+ <% end %>
72
+
66
73
  <%= yield %>
67
74
  </div>
68
75
  </main>
@@ -1,3 +1,3 @@
1
1
  module Dokno
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dokno
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtney Payne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-03 00:00:00.000000000 Z
11
+ date: 2020-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diffy
@@ -169,8 +169,7 @@ dependencies:
169
169
  - !ruby/object:Gem::Version
170
170
  version: '2.15'
171
171
  description: Dokno allows you to easily mount a self-contained knowledgebase / wiki
172
- / help system to your Rails app where you and your users can author articles relevant
173
- to your app.
172
+ / help system to your Rails app.
174
173
  email:
175
174
  - cpayne624@gmail.com
176
175
  executables: []