archangel 0.0.5 → 0.0.6

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.jshintrc +3 -3
  3. data/.reek +9 -0
  4. data/Gemfile +1 -0
  5. data/app/assets/javascripts/archangel/object/flash.js +2 -2
  6. data/app/assets/javascripts/archangel/object/routes.js.erb +4 -0
  7. data/app/assets/javascripts/archangel/object/routes/backend.js +13 -2
  8. data/app/helpers/archangel/flash_helper.rb +1 -1
  9. data/app/models/archangel/asset.rb +1 -1
  10. data/app/models/archangel/collection.rb +3 -3
  11. data/app/models/archangel/page.rb +1 -1
  12. data/app/models/archangel/site.rb +3 -4
  13. data/app/models/archangel/user.rb +4 -2
  14. data/app/models/archangel/widget.rb +1 -1
  15. data/app/services/archangel/render_service.rb +1 -7
  16. data/app/services/archangel/template_render_service.rb +1 -3
  17. data/app/themes/default/assets/javascripts/default/backend.js +0 -2
  18. data/app/themes/default/assets/javascripts/default/backend/core.js +71 -2
  19. data/app/themes/default/assets/javascripts/default/common/flash.js +1 -1
  20. data/app/themes/default/views/layouts/auth.html.erb +2 -0
  21. data/app/themes/default/views/layouts/backend/_sidebar.html.erb +7 -5
  22. data/app/views/archangel/shared/_flash_messages.html.erb +3 -3
  23. data/app/views/devise/shared/_links.html.erb +7 -7
  24. data/db/migrate/20171003210347_create_archangel_users.rb +2 -2
  25. data/db/migrate/20171005224054_create_archangel_pages.rb +1 -1
  26. data/db/migrate/20171006175939_create_archangel_widgets.rb +1 -1
  27. data/db/migrate/20171006194044_create_archangel_collections.rb +1 -1
  28. data/db/seeds.rb +72 -7
  29. data/docs/Extension/Models.md +1 -1
  30. data/lib/archangel/command/templates/extension/config/routes.rb +1 -1
  31. data/lib/archangel/engine.rb +4 -0
  32. data/lib/archangel/version.rb +1 -1
  33. data/lib/generators/archangel/dummy/templates/config/database.yml +0 -12
  34. data/spec/lib/archangel/command/extension_spec.rb +1 -1
  35. data/spec/models/archangel/asset_spec.rb +11 -14
  36. data/spec/models/archangel/collection_spec.rb +37 -7
  37. data/spec/models/archangel/entry_spec.rb +8 -6
  38. data/spec/models/archangel/field_spec.rb +21 -10
  39. data/spec/models/archangel/page_spec.rb +65 -24
  40. data/spec/models/archangel/site_spec.rb +45 -2
  41. data/spec/models/archangel/template_spec.rb +16 -9
  42. data/spec/models/archangel/user_spec.rb +44 -15
  43. data/spec/models/archangel/widget_spec.rb +44 -10
  44. data/spec/policies/archangel/asset_policy_spec.rb +26 -9
  45. data/spec/policies/archangel/collection_policy_spec.rb +23 -8
  46. data/spec/policies/archangel/entries_policy_spec.rb +26 -9
  47. data/spec/policies/archangel/page_policy_spec.rb +23 -8
  48. data/spec/policies/archangel/site_policy_spec.rb +11 -9
  49. data/spec/policies/archangel/template_policy_spec.rb +23 -8
  50. data/spec/policies/archangel/user_policy_spec.rb +23 -8
  51. data/spec/policies/archangel/widget_policy_spec.rb +23 -8
  52. metadata +2 -4
  53. data/app/themes/default/assets/javascripts/default/common/navigation.js +0 -30
  54. data/app/themes/default/assets/javascripts/default/common/sidebar.js +0 -114
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d09b2b524c0d918a1098d8f77e7c4e41b3614bffe7703a28df6f26932dcf0d19
4
- data.tar.gz: d5d7a79459ce16ab1a8109b803cff19dce14b1f3b813ddf716edb71c2c2b638a
3
+ metadata.gz: ffb41416bed166dc7a839e962bd30c941dbc5a617a082bafd8b53c9dfce8dfb1
4
+ data.tar.gz: 21ee7b769a7678816b1668800714dac78292c07aa60d6abc3a86f807c5302c56
5
5
  SHA512:
6
- metadata.gz: baffd2cd0808981ad90eeb76a4925d3dd7a843da6f38a77894cca076d6a1a00f602e8a07741023c9882be15e7b1f2b633ef9e8470dbf4bb9d3a26f6017240587
7
- data.tar.gz: 1d81da1349524ed0ac92dedd88abd93620b78b7b09fb3057d4927b39cadb7c4f3a1da9a9b13820212ff804332eccbc95509793466d9ac9fcb6f8e1f9c85d5b3f
6
+ metadata.gz: 6b0381d552c49d82b3ee4bc5fe1501e06e7aa809e7ae9f1209e6761d2252c262b507ab18ede3136310b241d8b7eedbd459f7fa9ac5630c6922ec3f18a6bd9e10
7
+ data.tar.gz: 4156e91ffcf03d124aad5654b773d39d92a1e1733f817246eda137dcb964695fceedbbcee63a51c672168fa464cc4ae9da11fa3cf57eacaacd0bad39aafad92e
data/.jshintrc CHANGED
@@ -2,12 +2,12 @@
2
2
  "globals": {
3
3
  "$": true,
4
4
  "Archangel": true,
5
+ "Sortable": true,
6
+ "XMLHttpRequest": true,
5
7
  "document": true,
6
8
  "jQuery": true,
7
9
  "localStorage": true,
8
- "Sortable": true,
9
- "window": true,
10
- "XMLHttpRequest": true
10
+ "window": true
11
11
  },
12
12
  "boss": true,
13
13
  "curly": true,
data/.reek CHANGED
@@ -30,6 +30,15 @@ UtilityFunction:
30
30
  enabled: false
31
31
  UtilityFunction:
32
32
  enabled: false
33
+ "app/inputs":
34
+ InstanceVariableAssumption:
35
+ enabled: false
33
36
  "app/mailers":
34
37
  InstanceVariableAssumption:
35
38
  enabled: false
39
+ "app/policies":
40
+ InstanceVariableAssumption:
41
+ enabled: false
42
+ "app/uploaders":
43
+ UtilityFunction:
44
+ enabled: false
data/Gemfile CHANGED
@@ -33,4 +33,5 @@ group :test do
33
33
  gem "shoulda-callback-matchers", "~> 1.1"
34
34
  gem "shoulda-matchers", "~> 3.1"
35
35
  gem "simplecov", "~> 0.14"
36
+ gem "timecop", "~> 0.9"
36
37
  end
@@ -28,7 +28,7 @@
28
28
  },
29
29
 
30
30
  flashMessage: function(type, message) {
31
- if (message == '' || message == undefined) {
31
+ if (message === '' || message === undefined) {
32
32
  return false;
33
33
  }
34
34
 
@@ -37,7 +37,7 @@
37
37
  var messagesContainer = document.querySelector('#alert-messages'),
38
38
  msgContainer = document.createElement('div');
39
39
 
40
- msgContainer.setAttribute('class', 'alert alert-' + type + ' alert-link');
40
+ msgContainer.setAttribute('class', 'alert alert-' + type + ' alert-link alert-dismissable fade-in');
41
41
  msgContainer.setAttribute('role', 'alert');
42
42
  msgContainer.innerHTML = message;
43
43
 
@@ -75,6 +75,10 @@
75
75
  return '/' + finalPath;
76
76
  };
77
77
 
78
+ object.rootUrl = function() {
79
+ return window.location.origin + object.rootPath();
80
+ };
81
+
78
82
  object.route = {
79
83
  rootPath: object.rootPath()
80
84
  };
@@ -5,15 +5,26 @@
5
5
  return object.pathBuilder([object.mountScope(), object.backendScope()]);
6
6
  };
7
7
 
8
+ object.backendUrl = function () {
9
+ return [object.rootUrl(), object.backendPath()].join('/');
10
+ };
11
+
8
12
  object.backendPathFor = function (path, args) {
9
13
  return object.pathFor([object.backendScope(), path], args);
10
14
  };
11
15
 
16
+ object.backendUrlFor = function (path, args) {
17
+ return object.backendUrl() + object.backendPathFor(path, args);
18
+ };
19
+
12
20
  object.route.backend = {
13
- // Dashboard
21
+ // Dashboard (path)
14
22
  rootPath: object.backendPath(),
15
23
 
16
- // Assets
24
+ // Dashboard (url)
25
+ rootUrl: object.backendUrl(),
26
+
27
+ // Assets (path)
17
28
  assetsPath: object.backendPathFor('assets'),
18
29
  newAssetPath: object.backendPathFor('assets/new'),
19
30
  assetPath: function (id) {
@@ -16,7 +16,7 @@ module Archangel
16
16
 
17
17
  {
18
18
  success: "success", error: "danger", alert: "warning", notice: "info"
19
- }[flash_type.to_sym] || flash_type
19
+ }.fetch(flash_type.to_sym, flash_type)
20
20
  end
21
21
  end
22
22
  end
@@ -34,7 +34,7 @@ module Archangel
34
34
  end
35
35
 
36
36
  def valid_file_name
37
- return if /^[\w-]+\.[A-Za-z]{3}$/ =~ file_name
37
+ return if /^[\w-]+\.[A-Za-z]{2,}$/ =~ file_name
38
38
 
39
39
  errors.add(:file_name, Archangel.t(:file_name_invalid))
40
40
  end
@@ -12,10 +12,10 @@ module Archangel
12
12
  after_destroy :column_reset
13
13
 
14
14
  validates :name, presence: true
15
- validates :slug, presence: true, uniqueness: true
15
+ validates :slug, presence: true, uniqueness: { scope: :site_id }
16
16
 
17
- has_many :entries, inverse_of: :collection, dependent: :destroy
18
- has_many :fields, inverse_of: :collection, dependent: :destroy
17
+ has_many :entries, inverse_of: :collection
18
+ has_many :fields, inverse_of: :collection
19
19
 
20
20
  accepts_nested_attributes_for :fields, reject_if: :all_blank,
21
21
  allow_destroy: true
@@ -20,7 +20,7 @@ module Archangel
20
20
 
21
21
  validates :content, presence: true
22
22
  validates :homepage, inclusion: { in: [true, false] }
23
- validates :path, uniqueness: true
23
+ validates :path, uniqueness: { scope: :site_id }
24
24
  validates :published_at, allow_blank: true, date: true
25
25
  validates :slug, presence: true, uniqueness: { scope: :parent_id }
26
26
  validates :title, presence: true
@@ -18,18 +18,17 @@ module Archangel
18
18
  less_than_or_equal_to: Archangel.config.image_maximum_file_size
19
19
  }
20
20
  validates :name, presence: true
21
- validates :theme, presence: true,
22
- inclusion: { in: Archangel.themes },
23
- allow_blank: true
21
+ validates :theme, inclusion: { in: Archangel.themes }, allow_blank: true
24
22
 
25
23
  has_many :assets
26
- has_many :collections
27
24
  has_many :pages
28
25
  has_many :templates
29
26
  has_many :users
30
27
  has_many :widgets
31
28
 
29
+ has_many :collections
32
30
  has_many :entries, through: :collections
31
+ has_many :fields, through: :collections
33
32
 
34
33
  ##
35
34
  # Current site
@@ -22,12 +22,14 @@ module Archangel
22
22
  validates :avatar, file_size: {
23
23
  less_than_or_equal_to: Archangel.config.image_maximum_file_size
24
24
  }
25
- validates :email, presence: true, uniqueness: true, email: true
25
+ validates :email, presence: true,
26
+ email: true,
27
+ uniqueness: { scope: :site_id }
26
28
  validates :name, presence: true
27
29
  validates :password, presence: true, length: { minimum: 8 }, on: :create
28
30
  validates :password, allow_blank: true, length: { minimum: 8 }, on: :update
29
31
  validates :role, presence: true, inclusion: { in: Archangel::ROLES }
30
- validates :username, presence: true, uniqueness: true
32
+ validates :username, presence: true, uniqueness: { scope: :site_id }
31
33
 
32
34
  belongs_to :site
33
35
 
@@ -13,7 +13,7 @@ module Archangel
13
13
 
14
14
  validates :content, presence: true
15
15
  validates :name, presence: true
16
- validates :slug, presence: true, uniqueness: true
16
+ validates :slug, presence: true, uniqueness: { scope: :site_id }
17
17
 
18
18
  validate :valid_liquid_content
19
19
 
@@ -58,17 +58,11 @@ module Archangel
58
58
  #
59
59
  def call
60
60
  liquid = ::Liquid::Template.parse(template)
61
- liquid.send(liquid_renderer,
62
- stringify_assigns,
63
- liquid_options).html_safe
61
+ liquid.send(:render, stringify_assigns, liquid_options).html_safe
64
62
  end
65
63
 
66
64
  protected
67
65
 
68
- def liquid_renderer
69
- %w[development test].include?(Rails.env) ? :render! : :render
70
- end
71
-
72
66
  def stringify_assigns
73
67
  assigns.deep_stringify_keys
74
68
  end
@@ -14,9 +14,7 @@ module Archangel
14
14
  template_content = build_template(template)
15
15
 
16
16
  liquid = ::Liquid::Template.parse(template_content)
17
- liquid.send(liquid_renderer,
18
- stringify_assigns,
19
- liquid_options).html_safe
17
+ liquid.send(:render, stringify_assigns, liquid_options).html_safe
20
18
  end
21
19
 
22
20
  protected
@@ -44,7 +44,5 @@
44
44
  // Theme assets
45
45
  //= require default/common/cards
46
46
  //= require default/common/flash
47
- //= require default/common/navigation
48
- //= require default/common/sidebar
49
47
  //
50
48
  //= require default/backend/core
@@ -1,7 +1,76 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- document.addEventListener('DOMContentLoaded', function() {
5
- // Nothing
4
+ jQuery(function() {
5
+
6
+ function resizeBroadcast() {
7
+ var timesRun = 0,
8
+ interval = setInterval(function() {
9
+ timesRun += 1;
10
+ if (timesRun === 5) {
11
+ clearInterval(interval);
12
+ }
13
+ window.dispatchEvent(new Event('resize'));
14
+ }, 62.5);
15
+ }
16
+
17
+ // Add class .active to current link
18
+ $('nav > ul.nav').find('a').each(function() {
19
+ var currentUrl = String(window.location).split('?')[0],
20
+ rootUrl = Archangel.route.backend.rootUrl,
21
+ itemHref = $($(this))[0].href;
22
+
23
+ if (currentUrl.substr(currentUrl.length - 1) === '#') {
24
+ currentUrl = currentUrl.slice(0, -1);
25
+ }
26
+
27
+ // Dashboard
28
+ if (itemHref === rootUrl && itemHref === currentUrl) {
29
+ $(this).addClass('active');
30
+
31
+ return;
32
+ }
33
+
34
+ // All other items
35
+ if (itemHref !== rootUrl && currentUrl.lastIndexOf(itemHref, 0) === 0) {
36
+ $(this).addClass('active');
37
+ }
38
+ });
39
+
40
+ // Dropdown Menu
41
+ $('nav > ul.nav').on('click', 'a', function(evt) {
42
+ if ($.ajaxLoad) {
43
+ evt.preventDefault();
44
+ }
45
+
46
+ if ($(this).hasClass('nav-dropdown-toggle')) {
47
+ $(this).parent().toggleClass('open');
48
+
49
+ resizeBroadcast();
50
+ }
51
+ });
52
+
53
+ $('.sidebar-toggler').click(function(){
54
+ $('body').toggleClass('sidebar-hidden');
55
+
56
+ resizeBroadcast();
57
+ });
58
+
59
+ $('.sidebar-minimizer').click(function(){
60
+ $('body').toggleClass('sidebar-minimized');
61
+
62
+ resizeBroadcast();
63
+ });
64
+
65
+ $('.brand-minimizer').click(function(){
66
+ $('body').toggleClass('brand-minimized');
67
+ });
68
+
69
+ $('.mobile-sidebar-toggler').click(function(){
70
+ $('body').toggleClass('sidebar-mobile-show');
71
+
72
+ resizeBroadcast();
73
+ });
74
+
6
75
  });
7
76
  }());
@@ -21,7 +21,7 @@
21
21
 
22
22
  clearInterval(fadeInternal);
23
23
 
24
- if (typeof callback == 'function') callback(true);
24
+ if (typeof callback === 'function') { callback(true); }
25
25
  }
26
26
 
27
27
  else {
@@ -22,6 +22,8 @@
22
22
  <div class="card-body">
23
23
  <%= render "archangel/shared/flash_messages" %>
24
24
 
25
+ <%= image_tag(current_site.logo.medium.url, alt: current_site.name, class: "mx-auto d-block") %>
26
+
25
27
  <%= yield %>
26
28
  </div>
27
29
  </div>
@@ -34,12 +34,14 @@
34
34
  </li>
35
35
 
36
36
  <% if current_site.collections.present? %>
37
- <li class="nav-title">
38
- <%= Archangel.t(:collections) %>
39
- </li>
40
-
41
- <% for item in current_site.collections %>
37
+ <% current_site.collections.each_with_index do |item, index| %>
42
38
  <% if item.persisted? %>
39
+ <% if index.zero? %>
40
+ <li class="nav-title">
41
+ <%= Archangel.t(:collections) %>
42
+ </li>
43
+ <% end %>
44
+
43
45
  <li class="nav-item">
44
46
  <a class="nav-link" href="<%= backend_collection_entries_path(item) %>"><%= fa_icon("circle") %> <%= item.name %></a>
45
47
  </li>
@@ -1,8 +1,8 @@
1
1
  <div id="alert-messages">
2
2
  <% unless flash.empty? %>
3
- <% flash.delete(:timedout).each do |key, value| %>
4
- <div class="alert alert-<%= flash_class_for(key) %> alert-link" role="alert">
5
- <%= value %>
3
+ <% flash.delete(:timedout).each do |type, message| %>
4
+ <div class="alert alert-<%= flash_class_for(type) %> alert-link alert-dismissable" role="alert">
5
+ <%= message %>
6
6
  </div>
7
7
  <% end %>
8
8
  <% end %>
@@ -1,30 +1,30 @@
1
- <ul class="nav justify-content-center">
1
+ <ul class="list-inline text-center">
2
2
  <%- if controller_name != "sessions" %>
3
- <li class="nav-item">
3
+ <li class="list-inline-item">
4
4
  <%= link_to("Log in", new_session_path(resource_name), class: "nav-link") %>
5
5
  </li>
6
6
  <% end -%>
7
7
 
8
8
  <%- if Archangel.config.allow_registration && devise_mapping.registerable? && controller_name != "registrations" %>
9
- <li class="nav-item">
9
+ <li class="list-inline-item">
10
10
  <%= link_to("Sign up", new_registration_path(resource_name), class: "nav-link") %>
11
11
  </li>
12
12
  <% end -%>
13
13
 
14
14
  <%- if devise_mapping.recoverable? && controller_name != "passwords" && controller_name != "registrations" %>
15
- <li class="nav-item">
15
+ <li class="list-inline-item">
16
16
  <%= link_to("Forgot your password?", new_password_path(resource_name), class: "nav-link") %>
17
17
  </li>
18
18
  <% end -%>
19
19
 
20
20
  <%- if devise_mapping.confirmable? && controller_name != "confirmations" %>
21
- <li class="nav-item">
21
+ <li class="list-inline-item">
22
22
  <%= link_to("Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: "nav-link") %>
23
23
  </li>
24
24
  <% end -%>
25
25
 
26
26
  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != "unlocks" %>
27
- <li class="nav-item">
27
+ <li class="list-inline-item">
28
28
  <%= link_to("Didn't receive unlock instructions?", new_unlock_path(resource_name), class: "nav-link") %>
29
29
  </li>
30
30
  <% end -%>
@@ -33,7 +33,7 @@
33
33
  <%- if devise_mapping.omniauthable? %>
34
34
  <ul class="nav justify-content-center">
35
35
  <%- resource_class.omniauth_providers.each do |provider| %>
36
- <li class="nav-item">
36
+ <li class="list-inline-item">
37
37
  <%= link_to("Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), class: "nav-link") %>
38
38
  </li>
39
39
  <% end -%>
@@ -52,7 +52,7 @@ class CreateArchangelUsers < ActiveRecord::Migration[5.1]
52
52
  t.timestamps null: false
53
53
  end
54
54
 
55
- add_index :archangel_users, :email, unique: true
55
+ add_index :archangel_users, :email
56
56
  add_index :archangel_users, :reset_password_token, unique: true
57
57
  add_index :archangel_users, :confirmation_token, unique: true
58
58
  add_index :archangel_users, :unlock_token, unique: true
@@ -60,7 +60,7 @@ class CreateArchangelUsers < ActiveRecord::Migration[5.1]
60
60
  add_index :archangel_users, :name
61
61
  add_index :archangel_users, :role
62
62
  add_index :archangel_users, :site_id
63
- add_index :archangel_users, :username, unique: true
63
+ add_index :archangel_users, :username
64
64
  add_index :archangel_users, :invitations_count
65
65
  add_index :archangel_users, :invitation_token, unique: true
66
66
  add_index :archangel_users, :invited_by_id
@@ -20,7 +20,7 @@ class CreateArchangelPages < ActiveRecord::Migration[5.1]
20
20
  add_index :archangel_pages, :deleted_at
21
21
  add_index :archangel_pages, :homepage
22
22
  add_index :archangel_pages, :parent_id
23
- add_index :archangel_pages, :path, unique: true
23
+ add_index :archangel_pages, :path
24
24
  add_index :archangel_pages, :published_at
25
25
  add_index :archangel_pages, :site_id
26
26
  add_index :archangel_pages, :slug