archangel 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.jshintrc +3 -3
- data/.reek +9 -0
- data/Gemfile +1 -0
- data/app/assets/javascripts/archangel/object/flash.js +2 -2
- data/app/assets/javascripts/archangel/object/routes.js.erb +4 -0
- data/app/assets/javascripts/archangel/object/routes/backend.js +13 -2
- data/app/helpers/archangel/flash_helper.rb +1 -1
- data/app/models/archangel/asset.rb +1 -1
- data/app/models/archangel/collection.rb +3 -3
- data/app/models/archangel/page.rb +1 -1
- data/app/models/archangel/site.rb +3 -4
- data/app/models/archangel/user.rb +4 -2
- data/app/models/archangel/widget.rb +1 -1
- data/app/services/archangel/render_service.rb +1 -7
- data/app/services/archangel/template_render_service.rb +1 -3
- data/app/themes/default/assets/javascripts/default/backend.js +0 -2
- data/app/themes/default/assets/javascripts/default/backend/core.js +71 -2
- data/app/themes/default/assets/javascripts/default/common/flash.js +1 -1
- data/app/themes/default/views/layouts/auth.html.erb +2 -0
- data/app/themes/default/views/layouts/backend/_sidebar.html.erb +7 -5
- data/app/views/archangel/shared/_flash_messages.html.erb +3 -3
- data/app/views/devise/shared/_links.html.erb +7 -7
- data/db/migrate/20171003210347_create_archangel_users.rb +2 -2
- data/db/migrate/20171005224054_create_archangel_pages.rb +1 -1
- data/db/migrate/20171006175939_create_archangel_widgets.rb +1 -1
- data/db/migrate/20171006194044_create_archangel_collections.rb +1 -1
- data/db/seeds.rb +72 -7
- data/docs/Extension/Models.md +1 -1
- data/lib/archangel/command/templates/extension/config/routes.rb +1 -1
- data/lib/archangel/engine.rb +4 -0
- data/lib/archangel/version.rb +1 -1
- data/lib/generators/archangel/dummy/templates/config/database.yml +0 -12
- data/spec/lib/archangel/command/extension_spec.rb +1 -1
- data/spec/models/archangel/asset_spec.rb +11 -14
- data/spec/models/archangel/collection_spec.rb +37 -7
- data/spec/models/archangel/entry_spec.rb +8 -6
- data/spec/models/archangel/field_spec.rb +21 -10
- data/spec/models/archangel/page_spec.rb +65 -24
- data/spec/models/archangel/site_spec.rb +45 -2
- data/spec/models/archangel/template_spec.rb +16 -9
- data/spec/models/archangel/user_spec.rb +44 -15
- data/spec/models/archangel/widget_spec.rb +44 -10
- data/spec/policies/archangel/asset_policy_spec.rb +26 -9
- data/spec/policies/archangel/collection_policy_spec.rb +23 -8
- data/spec/policies/archangel/entries_policy_spec.rb +26 -9
- data/spec/policies/archangel/page_policy_spec.rb +23 -8
- data/spec/policies/archangel/site_policy_spec.rb +11 -9
- data/spec/policies/archangel/template_policy_spec.rb +23 -8
- data/spec/policies/archangel/user_policy_spec.rb +23 -8
- data/spec/policies/archangel/widget_policy_spec.rb +23 -8
- metadata +2 -4
- data/app/themes/default/assets/javascripts/default/common/navigation.js +0 -30
- data/app/themes/default/assets/javascripts/default/common/sidebar.js +0 -114
@@ -14,7 +14,7 @@ class CreateArchangelWidgets < ActiveRecord::Migration[5.1]
|
|
14
14
|
add_index :archangel_widgets, :deleted_at
|
15
15
|
add_index :archangel_widgets, :name
|
16
16
|
add_index :archangel_widgets, :site_id
|
17
|
-
add_index :archangel_widgets, :slug
|
17
|
+
add_index :archangel_widgets, :slug
|
18
18
|
add_index :archangel_widgets, :template_id
|
19
19
|
end
|
20
20
|
end
|
@@ -12,6 +12,6 @@ class CreateArchangelCollections < ActiveRecord::Migration[5.1]
|
|
12
12
|
add_index :archangel_collections, :deleted_at
|
13
13
|
add_index :archangel_collections, :name
|
14
14
|
add_index :archangel_collections, :site_id
|
15
|
-
add_index :archangel_collections, :slug
|
15
|
+
add_index :archangel_collections, :slug
|
16
16
|
end
|
17
17
|
end
|
data/db/seeds.rb
CHANGED
@@ -29,20 +29,19 @@ def prompt_for_admin_password
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# Site
|
32
|
-
|
32
|
+
curent_site = Archangel::Site.first_or_create! do |item|
|
33
33
|
item.name = "Archangel"
|
34
34
|
item.locale = "en"
|
35
35
|
end
|
36
36
|
|
37
37
|
# User
|
38
|
-
unless
|
38
|
+
unless curent_site.users.first
|
39
39
|
email = prompt_for_admin_email
|
40
40
|
name = prompt_for_admin_name
|
41
41
|
username = prompt_for_admin_username
|
42
42
|
password = prompt_for_admin_password
|
43
43
|
|
44
44
|
attributes = {
|
45
|
-
site: site,
|
46
45
|
email: email,
|
47
46
|
username: username,
|
48
47
|
name: name,
|
@@ -52,14 +51,80 @@ unless Archangel::User.first
|
|
52
51
|
confirmed_at: Time.current
|
53
52
|
}
|
54
53
|
|
55
|
-
|
54
|
+
curent_site.users.create!(attributes)
|
56
55
|
end
|
57
56
|
|
58
57
|
# Homepage
|
59
|
-
|
60
|
-
.find_or_create_by!(site: site, homepage: true) do |item|
|
58
|
+
curent_site.pages.published.find_or_create_by(homepage: true) do |item|
|
61
59
|
item.slug = "homepage-#{Time.now.to_i}"
|
62
60
|
item.title = "Welcome to Archangel"
|
63
|
-
item.content =
|
61
|
+
item.content = %(
|
62
|
+
<p>Welcome to your new site.</p>
|
63
|
+
)
|
64
64
|
item.published_at = Time.current
|
65
65
|
end
|
66
|
+
|
67
|
+
# Page Template
|
68
|
+
page_template = curent_site.templates
|
69
|
+
.find_or_create_by!(partial: false) do |item|
|
70
|
+
item.name = "Example Page Template"
|
71
|
+
item.content = %(
|
72
|
+
<p>I think this is the beginning of a beautiful page template.</p>
|
73
|
+
{{ content_for_layout }}
|
74
|
+
<p>I think this is the end of a beautiful page template.</p>
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Page
|
79
|
+
curent_site.pages.find_or_create_by!(slug: "example-page",
|
80
|
+
template: page_template,
|
81
|
+
homepage: false) do |item|
|
82
|
+
item.title = "Example Page"
|
83
|
+
item.content = %(
|
84
|
+
<p>I think this is the content of the page.</p>
|
85
|
+
)
|
86
|
+
item.published_at = Time.now
|
87
|
+
end
|
88
|
+
|
89
|
+
# Template
|
90
|
+
widget_template = curent_site.templates
|
91
|
+
.find_or_create_by!(partial: true) do |item|
|
92
|
+
item.name = "Example Widget Template"
|
93
|
+
item.content = %(
|
94
|
+
<p>I think this is the beginning of a beautiful widget template.</p>
|
95
|
+
{{ content_for_layout }}
|
96
|
+
<p>I think this is the end of a beautiful widget template.</p>
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Widget
|
101
|
+
curent_site.widgets.find_or_create_by!(slug: "example-widget",
|
102
|
+
template: widget_template) do |item|
|
103
|
+
item.name = "Example Widget"
|
104
|
+
item.content = %(
|
105
|
+
<p>I think this is the content of the widget.</p>
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Collection
|
110
|
+
collection = curent_site.collections.find_or_create_by!(
|
111
|
+
slug: "example-collection"
|
112
|
+
) do |item|
|
113
|
+
item.name = "Example Collection"
|
114
|
+
end
|
115
|
+
|
116
|
+
# Fields
|
117
|
+
collection.fields.find_or_create_by!(
|
118
|
+
collection: collection,
|
119
|
+
slug: "field1",
|
120
|
+
required: true
|
121
|
+
) do |item|
|
122
|
+
item.label = "Field 1"
|
123
|
+
item.classification = "string"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Entry
|
127
|
+
collection.entries.find_or_create_by(collection: collection) do |item|
|
128
|
+
item.value = { field1: "Value for field 1" }
|
129
|
+
item.available_at = Time.now
|
130
|
+
end
|
data/docs/Extension/Models.md
CHANGED
data/lib/archangel/engine.rb
CHANGED
data/lib/archangel/version.rb
CHANGED
@@ -10,10 +10,6 @@ development:
|
|
10
10
|
test:
|
11
11
|
<<: *default
|
12
12
|
database: archangel_<%= options[:lib_name] %>_test
|
13
|
-
|
14
|
-
production:
|
15
|
-
<<: *default
|
16
|
-
database: archangel_<%= options[:lib_name] %>_production
|
17
13
|
<%- when "postgres" -%>
|
18
14
|
default: &default
|
19
15
|
adapter: postgresql
|
@@ -26,10 +22,6 @@ development:
|
|
26
22
|
test:
|
27
23
|
<<: *default
|
28
24
|
database: archangel_<%= options[:lib_name] %>_test
|
29
|
-
|
30
|
-
production:
|
31
|
-
<<: *default
|
32
|
-
database: archangel_<%= options[:lib_name] %>_production
|
33
25
|
<%- else -%>
|
34
26
|
default: &default
|
35
27
|
adapter: sqlite3
|
@@ -41,8 +33,4 @@ development:
|
|
41
33
|
test:
|
42
34
|
<<: *default
|
43
35
|
database: db/archangel_<%= options[:lib_name] %>_test.sqlite3
|
44
|
-
|
45
|
-
production:
|
46
|
-
<<: *default
|
47
|
-
database: db/archangel_<%= options[:lib_name] %>_production.sqlite3
|
48
36
|
<%- end -%>
|
@@ -5,28 +5,25 @@ require "rails_helper"
|
|
5
5
|
module Archangel
|
6
6
|
RSpec.describe Asset, type: :model do
|
7
7
|
context "callbacks" do
|
8
|
-
it {
|
8
|
+
it { is_expected.to callback(:save_asset_attributes).before(:save) }
|
9
9
|
end
|
10
10
|
|
11
11
|
context "validations" do
|
12
|
-
it {
|
13
|
-
it {
|
12
|
+
it { is_expected.to validate_presence_of(:file) }
|
13
|
+
it { is_expected.to validate_presence_of(:file_name) }
|
14
14
|
|
15
|
-
it {
|
15
|
+
it { is_expected.to allow_value("success.js").for(:file_name) }
|
16
|
+
it { is_expected.to allow_value("success.jpg").for(:file_name) }
|
17
|
+
it { is_expected.to allow_value("filename.extension").for(:file_name) }
|
16
18
|
|
17
|
-
it
|
18
|
-
|
19
|
-
|
20
|
-
it
|
21
|
-
expect(subject).not_to allow_value("with.dot.jpg").for(:file_name)
|
22
|
-
end
|
23
|
-
it do
|
24
|
-
expect(subject).not_to allow_value("with space.jpg").for(:file_name)
|
25
|
-
end
|
19
|
+
it { is_expected.to_not allow_value("error.c").for(:file_name) }
|
20
|
+
it { is_expected.to_not allow_value("without-extension").for(:file_name) }
|
21
|
+
it { is_expected.to_not allow_value("with.dot.jpg").for(:file_name) }
|
22
|
+
it { is_expected.to_not allow_value("with space.jpg").for(:file_name) }
|
26
23
|
end
|
27
24
|
|
28
25
|
context "associations" do
|
29
|
-
it {
|
26
|
+
it { is_expected.to belong_to(:site) }
|
30
27
|
end
|
31
28
|
end
|
32
29
|
end
|
@@ -5,21 +5,51 @@ require "rails_helper"
|
|
5
5
|
module Archangel
|
6
6
|
RSpec.describe Collection, type: :model do
|
7
7
|
context "callbacks" do
|
8
|
-
it {
|
8
|
+
it { is_expected.to callback(:parameterize_slug).before(:validation) }
|
9
9
|
|
10
|
-
it {
|
10
|
+
it { is_expected.to callback(:column_reset).after(:destroy) }
|
11
11
|
end
|
12
12
|
|
13
13
|
context "validations" do
|
14
|
-
it {
|
15
|
-
it {
|
14
|
+
it { is_expected.to validate_presence_of(:name) }
|
15
|
+
it { is_expected.to validate_presence_of(:slug) }
|
16
16
|
|
17
|
-
it
|
17
|
+
it "has a unique slug scoped to Site" do
|
18
|
+
resource = build(:collection)
|
19
|
+
|
20
|
+
expect(resource)
|
21
|
+
.to validate_uniqueness_of(:slug).scoped_to(:site_id).case_insensitive
|
22
|
+
end
|
18
23
|
end
|
19
24
|
|
20
25
|
context "associations" do
|
21
|
-
it {
|
22
|
-
|
26
|
+
it { is_expected.to belong_to(:site) }
|
27
|
+
|
28
|
+
it { is_expected.to have_many(:entries) }
|
29
|
+
it { is_expected.to have_many(:fields) }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "#to_param" do
|
33
|
+
it "uses `slug` as the identifier for routes" do
|
34
|
+
resource = build(:collection, slug: "foo")
|
35
|
+
|
36
|
+
expect(resource.to_param).to eq("foo")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "#column_reset" do
|
41
|
+
before { ::Timecop.freeze }
|
42
|
+
after { ::Timecop.return }
|
43
|
+
|
44
|
+
it "resets `slug` to `slug` + current time" do
|
45
|
+
resource = create(:collection)
|
46
|
+
|
47
|
+
slug = resource.slug
|
48
|
+
|
49
|
+
resource.destroy!
|
50
|
+
|
51
|
+
expect(resource.slug).to eq "#{Time.current.to_i}_#{slug}"
|
52
|
+
end
|
23
53
|
end
|
24
54
|
end
|
25
55
|
end
|
@@ -5,16 +5,18 @@ require "rails_helper"
|
|
5
5
|
module Archangel
|
6
6
|
RSpec.describe Entry, type: :model do
|
7
7
|
context "validations" do
|
8
|
-
it {
|
9
|
-
it {
|
8
|
+
it { is_expected.to validate_presence_of(:collection_id) }
|
9
|
+
it { is_expected.to validate_presence_of(:value) }
|
10
10
|
|
11
|
-
it {
|
12
|
-
it {
|
13
|
-
it {
|
11
|
+
it { is_expected.to allow_value(nil).for(:available_at) }
|
12
|
+
it { is_expected.to allow_value("").for(:available_at) }
|
13
|
+
it { is_expected.to allow_value(Time.current).for(:available_at) }
|
14
|
+
|
15
|
+
it { is_expected.to_not allow_value("invalid").for(:available_at) }
|
14
16
|
end
|
15
17
|
|
16
18
|
context "associations" do
|
17
|
-
it {
|
19
|
+
it { is_expected.to belong_to(:collection) }
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -5,25 +5,36 @@ require "rails_helper"
|
|
5
5
|
module Archangel
|
6
6
|
RSpec.describe Field, type: :model do
|
7
7
|
context "validations" do
|
8
|
-
it {
|
9
|
-
it {
|
10
|
-
it {
|
11
|
-
it {
|
8
|
+
it { is_expected.to validate_presence_of(:classification) }
|
9
|
+
it { is_expected.to validate_presence_of(:collection_id).on(:update) }
|
10
|
+
it { is_expected.to validate_presence_of(:label) }
|
11
|
+
it { is_expected.to validate_presence_of(:slug) }
|
12
12
|
|
13
|
-
it {
|
14
|
-
it {
|
15
|
-
it {
|
13
|
+
it { is_expected.to allow_value(true).for(:required) }
|
14
|
+
it { is_expected.to allow_value(1).for(:required) }
|
15
|
+
it { is_expected.to allow_value(false).for(:required) }
|
16
|
+
it { is_expected.to allow_value(0).for(:required) }
|
16
17
|
|
17
|
-
it
|
18
|
+
it { is_expected.to_not allow_value(nil).for(:required) }
|
19
|
+
|
20
|
+
it "allows certain classifications" do
|
18
21
|
expect(subject).to(
|
19
22
|
validate_inclusion_of(:classification)
|
20
|
-
.in_array(
|
23
|
+
.in_array(Archangel::Field::CLASSIFICATIONS)
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has a unique slug scoped to Collection" do
|
28
|
+
resource = build(:field)
|
29
|
+
|
30
|
+
expect(resource).to(
|
31
|
+
validate_uniqueness_of(:slug).scoped_to(:collection_id)
|
21
32
|
)
|
22
33
|
end
|
23
34
|
end
|
24
35
|
|
25
36
|
context "associations" do
|
26
|
-
it {
|
37
|
+
it { is_expected.to belong_to(:collection) }
|
27
38
|
end
|
28
39
|
end
|
29
40
|
end
|
@@ -5,38 +5,56 @@ require "rails_helper"
|
|
5
5
|
module Archangel
|
6
6
|
RSpec.describe Page, type: :model do
|
7
7
|
context "callbacks" do
|
8
|
-
it {
|
8
|
+
it { is_expected.to callback(:parameterize_slug).before(:validation) }
|
9
9
|
|
10
|
-
it {
|
10
|
+
it { is_expected.to callback(:build_page_path).before(:save) }
|
11
11
|
|
12
|
-
it {
|
12
|
+
it { is_expected.to callback(:homepage_reset).after(:save) }
|
13
13
|
|
14
|
-
it {
|
14
|
+
it { is_expected.to callback(:column_reset).after(:destroy) }
|
15
15
|
end
|
16
16
|
|
17
17
|
context "validations" do
|
18
|
-
it {
|
19
|
-
it {
|
20
|
-
it {
|
18
|
+
it { is_expected.to validate_presence_of(:content) }
|
19
|
+
it { is_expected.to validate_presence_of(:slug) }
|
20
|
+
it { is_expected.to validate_presence_of(:title) }
|
21
21
|
|
22
|
-
it {
|
23
|
-
it { expect(subject).to allow_value(false).for(:homepage) }
|
24
|
-
it { expect(subject).not_to allow_value(nil).for(:homepage) }
|
22
|
+
it { is_expected.to allow_value("{{ foo }}").for(:content) }
|
25
23
|
|
26
|
-
it {
|
27
|
-
it {
|
28
|
-
it {
|
24
|
+
it { is_expected.to allow_value(true).for(:homepage) }
|
25
|
+
it { is_expected.to allow_value(1).for(:homepage) }
|
26
|
+
it { is_expected.to allow_value(false).for(:homepage) }
|
27
|
+
it { is_expected.to allow_value(0).for(:homepage) }
|
29
28
|
|
30
|
-
it {
|
29
|
+
it { is_expected.to_not allow_value(nil).for(:homepage) }
|
31
30
|
|
32
|
-
it {
|
33
|
-
it {
|
31
|
+
it { is_expected.to allow_value(nil).for(:published_at) }
|
32
|
+
it { is_expected.to allow_value(Time.current).for(:published_at) }
|
33
|
+
|
34
|
+
it { is_expected.to_not allow_value("invalid").for(:published_at) }
|
35
|
+
|
36
|
+
it "has a unique path scoped to Site" do
|
37
|
+
resource = build(:page)
|
38
|
+
|
39
|
+
expect(resource).to validate_uniqueness_of(:path).scoped_to(:site_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "has a unique slug scoped to Page" do
|
43
|
+
resource = build(:page, :with_parent)
|
44
|
+
|
45
|
+
expect(resource).to(
|
46
|
+
validate_uniqueness_of(:slug).scoped_to(:parent_id).case_insensitive
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
it { is_expected.to allow_value("{{ foo }}").for(:content) }
|
51
|
+
it { is_expected.to_not allow_value("{{ foo }").for(:content) }
|
34
52
|
end
|
35
53
|
|
36
54
|
context "associations" do
|
37
|
-
it {
|
38
|
-
it {
|
39
|
-
it {
|
55
|
+
it { is_expected.to belong_to(:site) }
|
56
|
+
it { is_expected.to belong_to(:parent).class_name("Archangel::Page") }
|
57
|
+
it { is_expected.to belong_to(:template).conditions(partial: false) }
|
40
58
|
end
|
41
59
|
|
42
60
|
context "scopes" do
|
@@ -44,7 +62,7 @@ module Archangel
|
|
44
62
|
it "returns all where published_at <= now" do
|
45
63
|
page = create(:page)
|
46
64
|
|
47
|
-
expect(
|
65
|
+
expect(described_class.published.first).to eq(page)
|
48
66
|
end
|
49
67
|
end
|
50
68
|
|
@@ -52,13 +70,13 @@ module Archangel
|
|
52
70
|
it "returns all where published_at is nil" do
|
53
71
|
page = create(:page, :unpublished)
|
54
72
|
|
55
|
-
expect(
|
73
|
+
expect(described_class.unpublished.first).to eq(page)
|
56
74
|
end
|
57
75
|
|
58
76
|
it "returns all where published_at is > now" do
|
59
77
|
page = create(:page, :future)
|
60
78
|
|
61
|
-
expect(
|
79
|
+
expect(described_class.unpublished.first).to eq(page)
|
62
80
|
end
|
63
81
|
end
|
64
82
|
|
@@ -66,12 +84,12 @@ module Archangel
|
|
66
84
|
it "returns all where homepage is true" do
|
67
85
|
page = create(:page, :homepage)
|
68
86
|
|
69
|
-
expect(
|
87
|
+
expect(described_class.homepage.first).to eq(page)
|
70
88
|
end
|
71
89
|
end
|
72
90
|
end
|
73
91
|
|
74
|
-
context "
|
92
|
+
context ".published?" do
|
75
93
|
it "is published" do
|
76
94
|
page = build(:page)
|
77
95
|
|
@@ -90,5 +108,28 @@ module Archangel
|
|
90
108
|
expect(page.published?).to be_falsey
|
91
109
|
end
|
92
110
|
end
|
111
|
+
|
112
|
+
context "#to_liquid" do
|
113
|
+
it "returns a Liquid object" do
|
114
|
+
resource = build(:page)
|
115
|
+
|
116
|
+
expect(resource.to_liquid).to be_a(Archangel::Liquid::Drops::PageDrop)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "#column_reset" do
|
121
|
+
before { ::Timecop.freeze }
|
122
|
+
after { ::Timecop.return }
|
123
|
+
|
124
|
+
it "resets `slug` to `slug` + current time" do
|
125
|
+
resource = create(:page)
|
126
|
+
|
127
|
+
slug = resource.slug
|
128
|
+
|
129
|
+
resource.destroy!
|
130
|
+
|
131
|
+
expect(resource.slug).to eq "#{Time.current.to_i}_#{slug}"
|
132
|
+
end
|
133
|
+
end
|
93
134
|
end
|
94
135
|
end
|