micro_cms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +74 -0
  3. data/Rakefile +24 -0
  4. data/app/assets/config/micro_cms_manifest.js +1 -0
  5. data/app/assets/javascripts/micro_cms.js +51 -0
  6. data/app/assets/stylesheets/micro_cms/micro_cms.css +30 -0
  7. data/app/controllers/micro_cms/application_controller.rb +7 -0
  8. data/app/controllers/micro_cms/content_block_controller.rb +31 -0
  9. data/app/helpers/micro_cms/application_helper.rb +6 -0
  10. data/app/helpers/micro_cms/cms_block_helper.rb +28 -0
  11. data/app/models/micro_cms/application_record.rb +7 -0
  12. data/app/models/micro_cms/content_block.rb +26 -0
  13. data/app/views/micro_cms/_content_block.html.erb +19 -0
  14. data/config/routes.rb +5 -0
  15. data/db/migrate/20190923103919_create_micro_cms_content_blocks.rb +12 -0
  16. data/lib/micro_cms.rb +15 -0
  17. data/lib/micro_cms/engine.rb +25 -0
  18. data/lib/micro_cms/version.rb +5 -0
  19. data/spec/dummy/Rakefile +8 -0
  20. data/spec/dummy/app/assets/config/manifest.js +3 -0
  21. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  22. data/spec/dummy/app/channels/application_cable/channel.rb +6 -0
  23. data/spec/dummy/app/channels/application_cable/connection.rb +6 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  25. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  26. data/spec/dummy/app/javascript/packs/application.js +15 -0
  27. data/spec/dummy/app/jobs/application_job.rb +9 -0
  28. data/spec/dummy/app/mailers/application_mailer.rb +6 -0
  29. data/spec/dummy/app/models/application_record.rb +5 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  32. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  33. data/spec/dummy/bin/rails +11 -0
  34. data/spec/dummy/bin/rake +11 -0
  35. data/spec/dummy/bin/rspec +8 -0
  36. data/spec/dummy/bin/setup +35 -0
  37. data/spec/dummy/bin/spring +17 -0
  38. data/spec/dummy/config.ru +7 -0
  39. data/spec/dummy/config/application.rb +31 -0
  40. data/spec/dummy/config/boot.rb +7 -0
  41. data/spec/dummy/config/cable.yml +10 -0
  42. data/spec/dummy/config/database.yml +25 -0
  43. data/spec/dummy/config/environment.rb +7 -0
  44. data/spec/dummy/config/environments/development.rb +64 -0
  45. data/spec/dummy/config/environments/production.rb +114 -0
  46. data/spec/dummy/config/environments/test.rb +50 -0
  47. data/spec/dummy/config/initializers/application_controller_renderer.rb +10 -0
  48. data/spec/dummy/config/initializers/assets.rb +14 -0
  49. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  50. data/spec/dummy/config/initializers/content_security_policy.rb +30 -0
  51. data/spec/dummy/config/initializers/cookies_serializer.rb +7 -0
  52. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  53. data/spec/dummy/config/initializers/inflections.rb +18 -0
  54. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  55. data/spec/dummy/config/initializers/wrap_parameters.rb +16 -0
  56. data/spec/dummy/config/locales/en.yml +33 -0
  57. data/spec/dummy/config/puma.rb +40 -0
  58. data/spec/dummy/config/routes.rb +5 -0
  59. data/spec/dummy/config/spring.rb +8 -0
  60. data/spec/dummy/config/storage.yml +34 -0
  61. data/spec/dummy/db/development.sqlite3 +0 -0
  62. data/spec/dummy/db/migrate/20190923150252_create_micro_cms_content_blocks.micro_cms.rb +13 -0
  63. data/spec/dummy/db/schema.rb +22 -0
  64. data/spec/dummy/db/test.sqlite3 +0 -0
  65. data/spec/dummy/log/development.log +1 -0
  66. data/spec/dummy/log/test.log +478 -0
  67. data/spec/dummy/public/404.html +67 -0
  68. data/spec/dummy/public/422.html +67 -0
  69. data/spec/dummy/public/500.html +66 -0
  70. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  71. data/spec/dummy/public/apple-touch-icon.png +0 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/dummy/tmp/development_secret.txt +1 -0
  74. data/spec/engine/micro_cms_spec.rb +9 -0
  75. data/spec/examples.txt +28 -0
  76. data/spec/factories/micro_cms/content_blocks.rb +8 -0
  77. data/spec/helpers/micro_cms/cms_block_helper_spec.rb +138 -0
  78. data/spec/models/micro_cms/content_block_spec.rb +62 -0
  79. data/spec/rails_helper.rb +75 -0
  80. data/spec/requests/micro_cms/content_block_controller_spec.rb +57 -0
  81. data/spec/routing/micro_cms/content_blocks_routing_spec.rb +17 -0
  82. data/spec/spec_helper.rb +43 -0
  83. data/spec/support/shared_examples/cms_block_helper_spec_helper.rb +9 -0
  84. data/spec/views/micro_cms/content_block_spec.rb +25 -0
  85. metadata +250 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 30b5c1e55c3ca21195b3f9564e0d2b5a56b499450b349167469f345aa5a49485
4
+ data.tar.gz: bf95432f342ceedff1dfe24da3eeda9d41e24d7bd2874172bce099a4c836e903
5
+ SHA512:
6
+ metadata.gz: bf74071bb121573869b82a8c90dc6f8ef13feb0fdd26394f8e53dbe66a17cf2d9b76f10bedb4b2787f073dca0828334f91e80bfeb379f66d4a9891e5c7e042bb
7
+ data.tar.gz: 51db9356c673799b72531e960520ae7b9c86747a41e28224ef438f2dca2fdca873fc350e424089b2caa2efb0206f864fc5659f4ba1001609100ae5920f7bcf05
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # MicroCms
2
+ Provides editable inline content blocks to modify your content on the fly.
3
+
4
+ ## Dependencies
5
+ * [`ckeditor`](https://github.com/galetahub/ckeditor) gem.
6
+ * jQuery
7
+
8
+ ## Usage
9
+ To provide an editable content block, use the `cms_block` helper method in your view, e.g.:
10
+ ```slim
11
+ = cms_block 'my.unique.block.identifier'
12
+ h1 Default
13
+ p This is my default content
14
+ ```
15
+
16
+ To print the content in readonly mode, use the `cms_content` helper method in your view, e.g:
17
+ ```slim
18
+ = cms_content 'my.unique.block.identifier'
19
+ p My content if there's no content block yet
20
+ ```
21
+
22
+ It's best to write an own helper method which also does authentication like
23
+ ```ruby
24
+ def cms(path, &block)
25
+ if current_user&.write_cms?
26
+ cms_block(path, &block)
27
+ else
28
+ cms_content(path, &block)
29
+ end
30
+ end
31
+ ```
32
+
33
+ ## Installation
34
+ Add this line to your application's Gemfile:
35
+
36
+ ```ruby
37
+ gem 'micro_cms'
38
+ ```
39
+
40
+ And then execute:
41
+ ```bash
42
+ $ bundle
43
+ ```
44
+
45
+ Or install it yourself as:
46
+ ```bash
47
+ $ gem install micro_cms
48
+ ```
49
+
50
+ In your app, run
51
+ ```bash
52
+ bin/bundle exec rake micro_cms:install:migrations
53
+ bin/rails db:migrate
54
+ ```
55
+ to copy the migrations.
56
+
57
+ Require the JavaScript (e.g. `//= require micro_cms`) and all styles (e.g. `@import 'micro_cms';'`).
58
+
59
+ Mount the engine routes in you `config/routes.rb` file:
60
+ ```ruby
61
+ mount MicroCms::Engine => '/micro_cms'
62
+ ```
63
+
64
+ ## Configuration
65
+ `app/config/initializers/micro_cms.rb`:
66
+
67
+ ```ruby
68
+ MicroCms.configure do |config|
69
+ config.ckeditor_configuration_file = 'ckeditor/config.js' # Custom ckeditor config. Optional
70
+ end
71
+ ```
72
+
73
+ ## License
74
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'MicroCms'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ load 'rails/tasks/statistics.rake'
23
+
24
+ require 'bundler/gem_tasks'
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/micro_cms .css
@@ -0,0 +1,51 @@
1
+ (function($) {
2
+ CKEDITOR.disableAutoInline = true;
3
+
4
+ var setupMicroCms = function() {
5
+ for (var instance in CKEDITOR.instances) {
6
+ if (!CKEDITOR.instances.hasOwnProperty(instance)) {
7
+ break;
8
+ }
9
+
10
+ CKEDITOR.instances[instance].on('blur', function(event) {
11
+ event.editor.updateElement();
12
+ var element = event.editor.element.$;
13
+ var updateUrl = element.getAttribute('data-update-url');
14
+ var authorizationToken = element.getAttribute('data-authorization-token');
15
+ window.e = event;
16
+
17
+ var data = new FormData();
18
+ data.append('micro_cms_content_block[content]', event.editor.getData());
19
+ data.append('micro_cms_content_block[authorization_token]', authorizationToken);
20
+
21
+ function blink(className) {
22
+ $(element).addClass(className);
23
+ setTimeout(function () {
24
+ $(element).removeClass(className);
25
+ }, 1000);
26
+ }
27
+
28
+ Rails.ajax({
29
+ type: 'PATCH',
30
+ url: updateUrl,
31
+ dataType: 'json',
32
+ contentType: 'multipart/form-data',
33
+ data: data,
34
+ success: function(e) {
35
+ blink('successful');
36
+ },
37
+ error: function(e) {
38
+ console.error(e);
39
+ blink('error');
40
+ },
41
+ })
42
+ });
43
+ }
44
+ };
45
+
46
+ window.addEventListener('load', setupMicroCms);
47
+
48
+ if ('Turbolinks' in window && Turbolinks.supported) {
49
+ $(document).on('turbolinks:load', setupMicroCms);
50
+ }
51
+ })(jQuery);
@@ -0,0 +1,30 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
5
+
6
+ @keyframes blinkGreen {
7
+ from {
8
+ background: #66ff66
9
+ }
10
+ to {
11
+ background: transparent
12
+ }
13
+ }
14
+
15
+ @keyframes blinkRed {
16
+ from {
17
+ background: #ff6666
18
+ }
19
+ to {
20
+ background: transparent
21
+ }
22
+ }
23
+
24
+ .content-block.successful {
25
+ animation: 1s blinkGreen ease-in;
26
+ }
27
+
28
+ .content-block.error {
29
+ animation: 1s blinkRed ease-in;
30
+ }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ class ApplicationController < ActionController::Base
5
+ protect_from_forgery with: :exception
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'micro_cms/application_controller'
4
+
5
+ module MicroCms
6
+ class ContentBlockController < ApplicationController
7
+ def update
8
+ check_authorization_token
9
+
10
+ respond_to do |format|
11
+ format.js do
12
+ ContentBlock.find_by!(path: params[:path]).update(content: content_block_params[:content])
13
+
14
+ head :no_content
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def check_authorization_token
22
+ token = content_block_params[:authorization_token]
23
+
24
+ raise ActiveRecord::RecordNotFound unless token == MicroCms.authorization_token
25
+ end
26
+
27
+ def content_block_params
28
+ params.require(:micro_cms_content_block).permit(:content, :authorization_token)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ module ApplicationHelper
5
+ end
6
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ module CmsBlockHelper
5
+ def cms_block(path, default = nil, &block)
6
+ content_block = content_block_for_path(path, default: capture_default(default, &block))
7
+
8
+ render partial: 'micro_cms/content_block', locals: { content_block: content_block }
9
+ end
10
+
11
+ def cms_content(path, default = nil, &block)
12
+ content_block = content_block_for_path(path, default: capture_default(default, &block))
13
+
14
+ content_tag :div, content_block.content, nil, false
15
+ end
16
+
17
+ private
18
+
19
+ def content_block_for_path(path, default:)
20
+ MicroCms::ContentBlock.content_block_for_path path, content: default || ''
21
+ end
22
+
23
+ def capture_default(default)
24
+ default = capture { yield } if block_given? && default.nil?
25
+ default
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ class ContentBlock < ApplicationRecord
5
+ validates :path, presence: true
6
+ validates :content, exclusion: { in: [nil] }
7
+
8
+ def self.table_name_prefix
9
+ 'micro_cms_'
10
+ end
11
+
12
+ def self.format_path(i18n_key)
13
+ "#{i18n_key.parameterize}-#{I18n.locale}"
14
+ end
15
+
16
+ def self.content_block_for_path(path, content: '')
17
+ ContentBlock.find_or_create_by(path: format_path(path)) do |content_block|
18
+ content_block.content = content
19
+ end
20
+ end
21
+
22
+ def to_param
23
+ path
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ <div
2
+ class="content-block"
3
+ contenteditable="true"
4
+ id="<%= content_block.path %>"
5
+ data-update-url="<%= MicroCms::Engine.routes.url_helpers.content_block_path(content_block) %>"
6
+ data-authorization-token="<%= MicroCms.authorization_token %>"
7
+ >
8
+ <%= raw content_block.content %>
9
+ </div>
10
+
11
+ <script type="text/javascript" charset="utf-8">
12
+ <% if MicroCms.ckeditor_configuration_file.present? %>
13
+ var config = { customConfig: "<%= asset_path(MicroCms.ckeditor_configuration_file) %>" };
14
+ <% else %>
15
+ var config = undefined;
16
+ <% end %>
17
+
18
+ CKEDITOR.inline('<%= content_block.path %>', config);
19
+ </script>
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ MicroCms::Engine.routes.draw do
4
+ resources :content_block, only: :update, param: :path
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateMicroCmsContentBlocks < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :micro_cms_content_blocks do |t|
6
+ t.string :path, null: false
7
+ t.text :content, null: false, default: ''
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
data/lib/micro_cms.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'micro_cms/engine'
4
+
5
+ module MicroCms
6
+ mattr_accessor :ckeditor_configuration_file
7
+ @ckeditor_configuration_file = nil
8
+
9
+ mattr_accessor :authorization_token
10
+ @authorization_token = nil
11
+
12
+ def self.configure
13
+ yield self
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace MicroCms
6
+
7
+ config.generators do |generators|
8
+ generators.test_framework :rspec
9
+ generators.fixture_replacement :factory_bot
10
+ generators.factory_bot dir: 'spec/factories'
11
+ end
12
+
13
+ initializer 'micro_cms.include_view_helpers' do |_app|
14
+ ActiveSupport.on_load :action_view do
15
+ ActionView::Base.public_send :include, MicroCms::CmsBlockHelper
16
+ end
17
+ end
18
+
19
+ initializer 'micro_cms.configure_authorization_token' do |_app|
20
+ MicroCms.configure do |config|
21
+ config.authorization_token = SecureRandom.urlsafe_base64
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicroCms
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
4
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
5
+
6
+ require_relative 'config/application'
7
+
8
+ Rails.application.load_tasks
@@ -0,0 +1,3 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../stylesheets .css
3
+ //= link micro_cms_manifest.js
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApplicationCable
4
+ class Channel < ActionCable::Channel::Base
5
+ end
6
+ end