inverter 0.2.7 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +132 -96
- data/app/assets/javascripts/input-inverter-image.coffee +8 -3
- data/app/assets/javascripts/input-inverter-link.coffee +98 -0
- data/app/assets/javascripts/input-inverter-version.coffee +42 -0
- data/app/assets/javascripts/input-inverter.coffee +10 -1
- data/app/assets/javascripts/inverter.coffee +7 -1
- data/app/assets/stylesheets/_inverter.scss +12 -0
- data/inverter.gemspec +3 -0
- data/lib/history_tracker.rb +3 -0
- data/lib/inverter.rb +8 -1
- data/lib/inverter/concerns/inverter.rb +69 -24
- data/lib/inverter/configuration.rb +3 -1
- data/lib/inverter/engine.rb +13 -1
- data/lib/inverter/middleware.rb +23 -0
- data/lib/inverter/renderer.rb +44 -0
- data/lib/inverter/version.rb +1 -1
- data/lib/tasks/inverter.rake +26 -0
- metadata +51 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a12fcc4aa0c6147bbcc747c703bc98547dba6765
|
4
|
+
data.tar.gz: de490871d8ec0d0030b0a3028d9055cb1b587b80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 166ec4a8bcac10ee30dfcfce766c2f0aa521f1712344f5a9b9a76cb3ee761cf645d56eec16393a41e19beabd0df9f482974e75fbd0e4078500cee44c3d46da3a
|
7
|
+
data.tar.gz: 9b1870192eaa8a9b1dec2ecb394f03505a71b98350a25685e8ec575348cb5435b09e87ab2a0bbb4f74af603bb9ec618d68068601c9a4bfcfba326d1071691275
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Mark content that you want to change via CMS in Rails templates. It's automatically populated to models and is accessible via CMS. When Rails renders template it pulls editable content from databased automatically.
|
6
6
|
|
7
7
|
|
8
|
-
##
|
8
|
+
## Setup
|
9
9
|
|
10
10
|
Add to ```Gemfile```:
|
11
11
|
|
@@ -13,139 +13,173 @@ Add to ```Gemfile```:
|
|
13
13
|
|
14
14
|
Setup initializer ```config/initializers/inverter.rb```:
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
```ruby
|
17
|
+
Inverter.configure do |config|
|
18
|
+
# model that stores template editable blocks
|
19
|
+
config.model_class = Page
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
# folders which templates are editable
|
22
|
+
config.template_folders = %w( pages )
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
# templates from template_folders the are not editable
|
25
|
+
config.excluded_template_names = %w( pages/home )
|
26
|
+
|
27
|
+
# disable Inverter middleware
|
28
|
+
config.disabled_middleware = false
|
29
|
+
end
|
30
|
+
```
|
28
31
|
|
29
32
|
Configure model that stores template content, e.g. ```models/page.rb```:
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
```ruby
|
35
|
+
class Page
|
36
|
+
include Mongoid::Document
|
37
|
+
include Mongoid::Timestamps
|
38
|
+
include Mongoid::Inverter
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Setup admin page controller configuration ```controllers/admin/pages_controller.rb```:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class Admin::PagesController < Admin::BaseController
|
46
|
+
mongosteen
|
47
|
+
json_config({ methods: [ :list_item_title, :version_options ])
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
|
52
|
+
### Meta Tags
|
53
|
+
|
54
|
+
```Mongoid::Inverter``` concern includes page meta tags fields. Check out [meta-tags](https://github.com/kpumuk/meta-tags) gem documentation for usage details, it helps to make pages SEO friendly.
|
55
|
+
|
56
|
+
To enable meta-tags support include following helper in application layout:
|
57
|
+
|
58
|
+
```erb
|
59
|
+
<%= display_meta_tags title: 'Default Website Title',
|
60
|
+
description: 'Default Website Description',
|
61
|
+
open_graph: { type: 'website',
|
62
|
+
title: 'Default Website Title',
|
63
|
+
description: 'Default Website Description',
|
64
|
+
image: 'https://slate-git-images.s3-us-west-1.amazonaws.com/slate.png' } %>
|
65
|
+
```
|
66
|
+
|
67
|
+
To override default behavior add custom fields and write own ```update_inverter_meta_tags``` implementation.
|
68
|
+
|
38
69
|
|
39
|
-
|
70
|
+
### View Example
|
40
71
|
|
41
|
-
|
42
|
-
class Admin::PagesController < Admin::BaseController
|
43
|
-
mongosteen
|
44
|
-
json_config({ methods: [ :list_item_title ])
|
72
|
+
An example of editable template with five content blocks and page name (to identify page in CMS), e.g. ```pages/about.html.erb```:
|
45
73
|
|
46
|
-
|
74
|
+
```html
|
75
|
+
<!--// About //-->
|
76
|
+
<h1>About</h1>
|
47
77
|
|
48
|
-
|
78
|
+
<!--[ hero : inverter-image ]-->
|
79
|
+
<%= image_tag('hero-1.png', alt: 'Welcome to Inverter') %>
|
80
|
+
<!--END-->
|
49
81
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
```
|
82
|
+
<!--[ subtitle ]-->
|
83
|
+
<p>
|
84
|
+
Blocks could have not only plain HTML but a Ruby template code as well. For
|
85
|
+
example these links below are going to be rendered and saved as HTML links in
|
86
|
+
the page objects.</p>
|
57
87
|
|
58
|
-
|
88
|
+
<p>
|
89
|
+
This content is editable via CMS, please go to website
|
90
|
+
<%= link_to 'admin', admin_path %> and check how it can be changed.</p>
|
91
|
+
<!--END-->
|
59
92
|
|
60
|
-
|
93
|
+
<!--[ body : markdown ]-->
|
94
|
+
You can use markdown in your views as well. [redcarpet](https://github.com/vmg/redcarpet)
|
95
|
+
gem is used as markdown rendere.
|
96
|
+
<!--END-->
|
61
97
|
|
62
|
-
|
63
|
-
|
64
|
-
|
98
|
+
<!--[ footer ]-->
|
99
|
+
<p>
|
100
|
+
This is an example of the content block named footer. This content is editable
|
101
|
+
via CMS, please go to website <%= link_to 'admin', admin_path %> and check how
|
102
|
+
it can be changed.</p>
|
103
|
+
<!--END-->
|
65
104
|
|
66
|
-
|
67
|
-
|
68
|
-
|
105
|
+
<!--[ footer_link : inverter-link ]-->
|
106
|
+
<p>
|
107
|
+
<%= link_to 'Slate', 'http://www.slatestudio.com', target: '_blank' %></p>
|
108
|
+
<!--END-->
|
109
|
+
```
|
69
110
|
|
70
|
-
<!--[ subtitle ]-->
|
71
|
-
<p>
|
72
|
-
This is an example of the content block named subtitle. This content is editable
|
73
|
-
via CMS, please go to website <%= link_to 'admin', admin_path %> and check how
|
74
|
-
it can be changed.</p>
|
75
|
-
<!--END-->
|
76
111
|
|
77
|
-
|
78
|
-
<p>
|
79
|
-
Blocks could have not only plain HTML but a Ruby template code as well. For
|
80
|
-
example these links below are going to be rendered and saved as HTML links in
|
81
|
-
the models. You can access <%= link_to 'welcome', page_path('welcome') %> &
|
82
|
-
<%= link_to 'about', page_path('about') %> pages.</p>
|
83
|
-
<!--END-->
|
112
|
+
### Middleware
|
84
113
|
|
85
|
-
|
86
|
-
<p>
|
87
|
-
This is an example of the content block named footer. This content is editable
|
88
|
-
via CMS, please go to website <%= link_to 'admin', admin_path %> and check how
|
89
|
-
it can be changed.</p>
|
90
|
-
<!--END-->
|
91
|
-
```
|
114
|
+
Inverter middleware helps to keep inverter objects up to date with template changes in development environment.
|
92
115
|
|
116
|
+
If new template added to tracked folders it's linked automatically and correspoding inverter object created. After tracked template deleted a tracking inverter object is removed as well.
|
93
117
|
|
94
|
-
|
118
|
+
It also watches changes in templates: adding new blocks and removing existing ones. When block is renamed inverter thinks that the new one added and previous removed so content for the previous is lost.
|
119
|
+
|
120
|
+
|
121
|
+
### Character Configuration
|
95
122
|
|
96
123
|
Inverter supports [chr](https://github.com/slate-studio/chr) out of the box. Include custom input in the cms configuration file ```admin.coffee```, and setup module configuration:
|
97
124
|
|
98
|
-
|
125
|
+
```coffeescript
|
126
|
+
|
127
|
+
#= require inverter
|
99
128
|
|
100
|
-
|
129
|
+
pagesConfig = ->
|
130
|
+
itemTitleField: 'list_item_title'
|
131
|
+
disableNewItems: true
|
132
|
+
disableDelete: true
|
133
|
+
arrayStore: new RailsArrayStore({
|
134
|
+
resource: 'page'
|
135
|
+
path: '/admin/pages'
|
136
|
+
})
|
137
|
+
formSchema:
|
138
|
+
version: { type: 'inverter-version', path: '/admin/pages' }
|
139
|
+
_page_title: { type: 'string', label: 'Title' }
|
140
|
+
_page_description: { type: 'text', label: 'Description' }
|
141
|
+
_page_keywords: { type: 'text', label: 'Keywords' }
|
142
|
+
_page_image_url: { type: 'string', label: 'Image URL' }
|
143
|
+
_blocks: { type: 'inverter' }
|
144
|
+
```
|
101
145
|
|
102
|
-
|
103
|
-
itemTitleField: 'list_item_title'
|
104
|
-
disableNewItems: true
|
105
|
-
disableDelete: true
|
106
|
-
arrayStore: new MongosteenArrayStore({
|
107
|
-
resource: 'page'
|
108
|
-
path: '/admin/pages'
|
109
|
-
})
|
110
|
-
formSchema:
|
111
|
-
_page_title: { type: 'string', label: 'Title' }
|
112
|
-
_page_description: { type: 'text', label: 'Description' }
|
113
|
-
_page_keywords: { type: 'text', label: 'Keywords' }
|
114
|
-
_page_image_url: { type: 'string', label: 'Image URL' }
|
115
|
-
blocks: { type: 'inverter' }
|
116
|
-
```
|
146
|
+
Inverer ```version``` input allows to select previous version of the page to edit.
|
117
147
|
|
118
|
-
Inverter input has an option ```defaultInputType```
|
148
|
+
Inverter input has an option ```defaultInputType``` that specifies what input type should be used as default, if nothing specified ```text``` is used. This might be set to WYSIWYG editor of your choice, e.g:
|
119
149
|
|
120
|
-
|
121
|
-
|
122
|
-
|
150
|
+
```coffeescript
|
151
|
+
blocks: { type: 'inverter', defaultInputType: 'redactor' }
|
152
|
+
```
|
123
153
|
|
124
154
|
You can also specify input type that you want to use for specific block like this: ```<!--[ Main Body : text ]-->``` — in this case ```Main Body``` would be a label and ```text``` is an input type that will be used to edit this block in CMS.
|
125
155
|
|
156
|
+
Include inverter styles for cms inputs into character styles configuration file ```admin.scss```
|
126
157
|
|
127
|
-
|
158
|
+
```scss
|
159
|
+
@import "inverter";
|
160
|
+
```
|
128
161
|
|
129
|
-
```Mongoid::Inverter``` concern includes page meta tags fields. Check out [meta-tags](https://github.com/kpumuk/meta-tags) gem documentation for usage details, it helps to make pages SEO friendly.
|
130
162
|
|
131
|
-
|
163
|
+
### Rake Tasks
|
132
164
|
|
133
|
-
|
134
|
-
<%= display_meta_tags title: 'Default Website Title',
|
135
|
-
description: 'Default Website Description',
|
136
|
-
open_graph: { type: 'website',
|
137
|
-
title: 'Default Website Title',
|
138
|
-
description: 'Default Website Description',
|
139
|
-
image: 'https://slate-git-images.s3-us-west-1.amazonaws.com/slate.png' } %>
|
140
|
-
```
|
165
|
+
To reset all inverter objects to template defaults run:
|
141
166
|
|
142
|
-
|
167
|
+
rake inverter:reset
|
143
168
|
|
169
|
+
**You need to run this rake task manually after first production deploy.** Middleware synchronizes objects only for development mode.
|
144
170
|
|
145
|
-
|
171
|
+
To sync all inverter objects with template changes run:
|
172
|
+
|
173
|
+
rake inverter:sync
|
174
|
+
|
175
|
+
**You might need to run this command on production after deploy if some templates blocks were changed.**
|
176
|
+
|
177
|
+
|
178
|
+
## Inverter Family:
|
146
179
|
|
147
|
-
- [Mongosteen](https://github.com/slate-studio/mongosteen): An easy way to add RESTful actions for mongoid models
|
148
180
|
- [Character](https://github.com/slate-studio/chr): Powerful responsive javascript CMS for apps
|
181
|
+
- [Mongosteen](https://github.com/slate-studio/mongosteen): An easy way to add RESTful actions for Mongoid models
|
182
|
+
- [Inverter](https://github.com/slate-studio/inverter): An easy way to connect Rails templates content to Character CMS
|
149
183
|
- [Loft](https://github.com/slate-studio/loft): Media assets manager for Character CMS
|
150
184
|
|
151
185
|
|
@@ -161,3 +195,5 @@ Copyright © 2015 [Slate Studio, LLC](http://slatestudio.com). Inverter is free
|
|
161
195
|
Inverter is maintained and funded by [Slate Studio, LLC](http://slatestudio.com). Tweet your questions or suggestions to [@slatestudio](https://twitter.com/slatestudio) and while you’re at it follow us too.
|
162
196
|
|
163
197
|
|
198
|
+
|
199
|
+
|
@@ -8,7 +8,11 @@
|
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
# INPUT INVERTER IMAGE
|
11
|
-
#
|
11
|
+
#
|
12
|
+
# Dependencies:
|
13
|
+
# - Loft character plugin for assets management
|
14
|
+
# - Chr input string implementation
|
15
|
+
#
|
12
16
|
# -----------------------------------------------------------------------------
|
13
17
|
class @InputInverterImage extends InputString
|
14
18
|
|
@@ -30,7 +34,7 @@ class @InputInverterImage extends InputString
|
|
30
34
|
|
31
35
|
|
32
36
|
_normalize_value: ->
|
33
|
-
if @value.indexOf('<img') > -1
|
37
|
+
if @value && @value.indexOf('<img') > -1
|
34
38
|
@value = @value.replace(new RegExp('"', 'g'), "'")
|
35
39
|
|
36
40
|
if ! @value.indexOf(' alt=') > -1
|
@@ -86,7 +90,7 @@ class @InputInverterImage extends InputString
|
|
86
90
|
|
87
91
|
@$chooseBtn.on 'click', (e) =>
|
88
92
|
e.preventDefault()
|
89
|
-
chr.modules.
|
93
|
+
chr.modules.loft.showModal 'images', false, (objects) =>
|
90
94
|
newSrc = objects[0].file.url
|
91
95
|
alt = @_alt() || objects[0].name
|
92
96
|
@_update_value(newSrc, alt)
|
@@ -119,6 +123,7 @@ class @InputInverterImage extends InputString
|
|
119
123
|
updateValue: (@value) ->
|
120
124
|
@_normalize_value()
|
121
125
|
@$input.val(@value)
|
126
|
+
@$input.trigger('change')
|
122
127
|
|
123
128
|
@_update_image()
|
124
129
|
@_update_alt()
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
# Author: Alexander Kravets <alex@slatestudio.com>,
|
3
|
+
# Slate Studio (http://www.slatestudio.com)
|
4
|
+
#
|
5
|
+
# Coding Guide:
|
6
|
+
# https://github.com/thoughtbot/guides/tree/master/style/coffeescript
|
7
|
+
# -----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
# -----------------------------------------------------------------------------
|
10
|
+
# INPUT INVERTER LINK
|
11
|
+
# - depends on Loft character plugin for assets management
|
12
|
+
# -----------------------------------------------------------------------------
|
13
|
+
class @InputInverterLink extends InputString
|
14
|
+
|
15
|
+
# PRIVATE ===============================================
|
16
|
+
|
17
|
+
_normalize_value: ->
|
18
|
+
if ! (@value.indexOf('<a') > -1)
|
19
|
+
@value = "<a title='' href=''></a>"
|
20
|
+
|
21
|
+
|
22
|
+
_add_input: ->
|
23
|
+
@_normalize_value()
|
24
|
+
|
25
|
+
@$el.addClass('input-loft-image')
|
26
|
+
@$el.addClass('has-value')
|
27
|
+
|
28
|
+
@$input =$ "<input type='hidden' name='#{ @name }' value='#{ @_safe_value() }' />"
|
29
|
+
@$el.append @$input
|
30
|
+
|
31
|
+
@_add_title()
|
32
|
+
@_add_url()
|
33
|
+
@_add_choose_button()
|
34
|
+
|
35
|
+
|
36
|
+
_update_value: (url, title) ->
|
37
|
+
$wrapper =$ "<div>#{ @value }</div>"
|
38
|
+
$wrapper.children().attr('href', url).attr('title', title).html(title)
|
39
|
+
@updateValue($wrapper.html())
|
40
|
+
|
41
|
+
|
42
|
+
_title: -> $(@value).html()
|
43
|
+
|
44
|
+
|
45
|
+
_url: -> $(@value).attr('href')
|
46
|
+
|
47
|
+
|
48
|
+
_add_title: ->
|
49
|
+
@$titleInput =$ "<input type='text' value='' placeholder='Title' />"
|
50
|
+
@$el.append @$titleInput
|
51
|
+
|
52
|
+
@$titleInput.val(@_title())
|
53
|
+
|
54
|
+
@$titleInput.on 'change', (e) =>
|
55
|
+
newTitle = $(e.target).val()
|
56
|
+
@_update_value(@_url(), newTitle)
|
57
|
+
|
58
|
+
|
59
|
+
_add_url: ->
|
60
|
+
@$urlInput =$ "<input type='text' value='' placeholder='URL' />"
|
61
|
+
@$el.append @$urlInput
|
62
|
+
|
63
|
+
@$urlInput.val(@_url())
|
64
|
+
|
65
|
+
@$urlInput.on 'change', (e) =>
|
66
|
+
newUrl = $(e.target).val()
|
67
|
+
@_update_value(newUrl, @_title())
|
68
|
+
|
69
|
+
|
70
|
+
_add_choose_button: ->
|
71
|
+
@$chooseBtn =$ "<a href='#' class='choose'>Choose or upload a file</a>"
|
72
|
+
@$el.append @$chooseBtn
|
73
|
+
|
74
|
+
@$chooseBtn.on 'click', (e) =>
|
75
|
+
e.preventDefault()
|
76
|
+
chr.modules.loft.showModal 'all', false, (objects) =>
|
77
|
+
url = objects[0].file.url
|
78
|
+
title = @_title() || objects[0].name
|
79
|
+
@_update_value(url, title)
|
80
|
+
|
81
|
+
|
82
|
+
# PUBLIC ================================================
|
83
|
+
|
84
|
+
updateValue: (@value) ->
|
85
|
+
@_normalize_value()
|
86
|
+
|
87
|
+
@$input.val(@value)
|
88
|
+
@$input.trigger('change')
|
89
|
+
|
90
|
+
@$titleInput.val(@_title())
|
91
|
+
@$urlInput.val(@_url())
|
92
|
+
|
93
|
+
|
94
|
+
chr.formInputs['inverter-link'] = InputInverterLink
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
# Author: Alexander Kravets <alex@slatestudio.com>,
|
3
|
+
# Slate Studio (http://www.slatestudio.com)
|
4
|
+
#
|
5
|
+
# Coding Guide:
|
6
|
+
# https://github.com/thoughtbot/guides/tree/master/style/coffeescript
|
7
|
+
# -----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
# -----------------------------------------------------------------------------
|
10
|
+
# INPUT INVERTER VERSION SELECT
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
class @InputInverterVersion extends InputSelect
|
13
|
+
|
14
|
+
_create_el: ->
|
15
|
+
@config.optionsHashFieldName = 'version_options'
|
16
|
+
@config.ignoreOnSubmission = true
|
17
|
+
@config.default = 0
|
18
|
+
@url = "#{ @config.path }/#{ @object._id }.json"
|
19
|
+
|
20
|
+
@$el =$ "<div class='input-#{ @config.type } input-#{ @config.klass } #{ @config.klassName }'>"
|
21
|
+
|
22
|
+
|
23
|
+
_add_input: ->
|
24
|
+
@$input =$ """<select name='#{ @name }'></select>"""
|
25
|
+
@$el.append @$input
|
26
|
+
|
27
|
+
@$input.on 'change', (e) => @_load_version()
|
28
|
+
|
29
|
+
@_add_options()
|
30
|
+
|
31
|
+
|
32
|
+
_load_version: ->
|
33
|
+
version = @$input.val()
|
34
|
+
$.get @url, { version: version }, (object) ->
|
35
|
+
chr.module.view.form.updateValues(object)
|
36
|
+
|
37
|
+
|
38
|
+
chr.formInputs['inverter-version'] = InputInverterVersion
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
@@ -72,8 +72,13 @@ class @InputInverter
|
|
72
72
|
|
73
73
|
inputClass = chr.formInputs[inputType]
|
74
74
|
|
75
|
+
# here we have @config.namePrefix undefined, so the second case works
|
76
|
+
# where @name is [_blocks] and name is the name of the block
|
75
77
|
inputName = if @config.namePrefix then "#{ @config.namePrefix }#{ @name }[#{ name }]" else "#{ @name }[#{ name }]"
|
76
78
|
inputConfig.namePrefix = @config.namePrefix
|
79
|
+
# add extra config parameter to save the original block name for hash
|
80
|
+
# function to work properly
|
81
|
+
inputConfig.blockName = name
|
77
82
|
|
78
83
|
return new inputClass(inputName, value, inputConfig, @object)
|
79
84
|
|
@@ -89,8 +94,11 @@ class @InputInverter
|
|
89
94
|
|
90
95
|
hash: (hash={}) ->
|
91
96
|
obj = {}
|
97
|
+
# workaround for using block names to have consistency
|
98
|
+
# while caching and versioning documents
|
92
99
|
for key, input of @inputs
|
93
|
-
input.
|
100
|
+
obj[input.config.blockName] = input.$input.val()
|
101
|
+
|
94
102
|
hash[@config.klassName] = obj
|
95
103
|
return hash
|
96
104
|
|
@@ -102,6 +110,7 @@ class @InputInverter
|
|
102
110
|
|
103
111
|
showErrorMessage: (message) -> ;
|
104
112
|
|
113
|
+
|
105
114
|
hideErrorMessage: -> ;
|
106
115
|
|
107
116
|
|
data/inverter.gemspec
CHANGED
@@ -25,6 +25,9 @@ pulled from databased automatically.
|
|
25
25
|
|
26
26
|
s.add_dependency("render_anywhere", ">= 0.0.10")
|
27
27
|
s.add_dependency("meta-tags", ">= 2.0")
|
28
|
+
s.add_dependency("mongoid-history", ">= 0.4.7")
|
29
|
+
s.add_dependency("mongoid-slug", ">= 4.0.0")
|
30
|
+
s.add_dependency("redcarpet", ">= 3.2.3")
|
28
31
|
end
|
29
32
|
|
30
33
|
|
data/lib/inverter.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
+
require "mongoid_slug"
|
2
|
+
require "mongoid-history"
|
3
|
+
require "history_tracker"
|
4
|
+
require "redcarpet"
|
5
|
+
|
1
6
|
require "inverter/concerns/inverter"
|
2
7
|
require "inverter/object"
|
8
|
+
require "inverter/middleware"
|
3
9
|
require "inverter/controller_helper"
|
4
10
|
require "inverter/configuration"
|
5
11
|
require "inverter/parser"
|
12
|
+
require "inverter/renderer"
|
6
13
|
require "inverter/version"
|
7
|
-
require "inverter/engine"
|
8
14
|
require "inverter/template_renderer_helper"
|
15
|
+
require "inverter/engine"
|
9
16
|
|
10
17
|
module Inverter
|
11
18
|
extend Configuration
|
@@ -3,7 +3,11 @@ module Mongoid
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
|
6
|
+
include Mongoid::Timestamps
|
7
|
+
include Mongoid::Slug
|
8
|
+
include Mongoid::History::Trackable
|
9
|
+
|
10
|
+
# ATTRIBUTES
|
7
11
|
field :_page_title, default: ''
|
8
12
|
field :_page_description, default: ''
|
9
13
|
field :_page_keywords, default: ''
|
@@ -13,12 +17,31 @@ module Mongoid
|
|
13
17
|
field :_name, default: ''
|
14
18
|
field :_blocks, type: Hash, default: {}
|
15
19
|
|
16
|
-
#
|
20
|
+
# HISTORY
|
21
|
+
track_history track_create: true
|
22
|
+
# # telling Mongoid::History how you want to track changes
|
23
|
+
# # dynamic fields will be tracked automatically (for MongoId 4.0+ you should include Mongoid::Attributes::Dynamic to your model)
|
24
|
+
# track_history :on => [:title, :body], # track title and body fields only, default is :all
|
25
|
+
# :modifier_field => :modifier, # adds "belongs_to :modifier" to track who made the change, default is :modifier
|
26
|
+
# :modifier_field_inverse_of => :nil, # adds an ":inverse_of" option to the "belongs_to :modifier" relation, default is not set
|
27
|
+
# :version_field => :version, # adds "field :version, :type => Integer" to track current version, default is :version
|
28
|
+
# :track_create => false, # track document creation, default is false
|
29
|
+
# :track_update => true, # track document updates, default is true
|
30
|
+
# :track_destroy => false # track document destruction, default is false
|
31
|
+
|
32
|
+
|
33
|
+
# INDEXES
|
17
34
|
index({ _template_name: 1 })
|
18
35
|
|
19
|
-
#
|
36
|
+
# SCOPES
|
20
37
|
default_scope -> { asc(:created_at) }
|
21
38
|
|
39
|
+
# SLUG
|
40
|
+
# used in cms for direct object access
|
41
|
+
slug do |current_object|
|
42
|
+
current_object._template_name.gsub('.html.erb', '').gsub('/', '-')
|
43
|
+
end
|
44
|
+
|
22
45
|
|
23
46
|
# returns title to be used in cms and identify page in list
|
24
47
|
def list_item_title
|
@@ -26,6 +49,22 @@ module Mongoid
|
|
26
49
|
end
|
27
50
|
|
28
51
|
|
52
|
+
# returns list of available object versions
|
53
|
+
def version_options
|
54
|
+
hash = {}
|
55
|
+
|
56
|
+
history_tracks.only(:created_at, :version).collect do |h|
|
57
|
+
hash[h.version] = "Version #{ h.version } — #{ h.created_at }"
|
58
|
+
end
|
59
|
+
|
60
|
+
if hash.empty?
|
61
|
+
hash = { '' => '--' }
|
62
|
+
end
|
63
|
+
|
64
|
+
return hash
|
65
|
+
end
|
66
|
+
|
67
|
+
|
29
68
|
# populates seo values to cached meta_tags object which is
|
30
69
|
# used by ActionController while template rendering
|
31
70
|
def update_inverter_meta_tags
|
@@ -51,31 +90,23 @@ module Mongoid
|
|
51
90
|
end
|
52
91
|
|
53
92
|
|
54
|
-
# updates blocks in
|
55
|
-
# objects _blocks hash
|
93
|
+
# updates blocks in html with objects _blocks hash values
|
56
94
|
def update_html(html)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
map.each do |name, pos|
|
62
|
-
block = "\n" + self._blocks[name] + "\n"
|
63
|
-
html[offset+pos[0]..offset+pos[1]] = block
|
95
|
+
html = ::Inverter::Renderer.render(html, self._blocks)
|
96
|
+
return html
|
97
|
+
end
|
64
98
|
|
65
|
-
block_size = block.size
|
66
|
-
template_block_size = pos[1] - pos[0]
|
67
|
-
offset += block_size - template_block_size - 1
|
68
|
-
end
|
69
99
|
|
70
|
-
|
100
|
+
# returns datetime when template was updated
|
101
|
+
def template_updated_at
|
102
|
+
template_path = Rails.root.to_s + '/app/views/' + self._template_name
|
103
|
+
File.mtime(template_path).getgm
|
71
104
|
end
|
72
105
|
|
73
106
|
|
74
107
|
# check if template file was changed after object was saved
|
75
108
|
def template_changed?
|
76
|
-
|
77
|
-
template_time_updated = File.mtime(template_path)
|
78
|
-
template_time_updated > updated_at
|
109
|
+
template_updated_at > updated_at.getgm
|
79
110
|
end
|
80
111
|
|
81
112
|
|
@@ -105,6 +136,9 @@ module Mongoid
|
|
105
136
|
# update page name
|
106
137
|
self._name = name
|
107
138
|
|
139
|
+
# force update_at change event the conten not changed
|
140
|
+
self.updated_at = Time.now
|
141
|
+
|
108
142
|
save
|
109
143
|
end
|
110
144
|
|
@@ -129,20 +163,31 @@ module Mongoid
|
|
129
163
|
|
130
164
|
# add new objects
|
131
165
|
if existing_template_names.size < template_names.size
|
166
|
+
puts "\nCreate Inverter objects for new templates: "
|
132
167
|
template_names_to_create = template_names - existing_template_names
|
133
|
-
template_names_to_create.each
|
168
|
+
template_names_to_create.each do |name|
|
169
|
+
create_from_template(name)
|
170
|
+
puts " - #{ name }"
|
171
|
+
end
|
134
172
|
end
|
135
173
|
|
136
174
|
# delete object for removed templates
|
137
175
|
if existing_template_names.size > template_names.size
|
176
|
+
puts "\nDelete Inverter objects for missing templates: "
|
138
177
|
template_names_to_remove = existing_template_names - template_names
|
139
|
-
template_names_to_remove.each
|
178
|
+
template_names_to_remove.each do |name|
|
179
|
+
find_by(_template_name: name).delete
|
180
|
+
puts " - #{ name }"
|
181
|
+
end
|
140
182
|
end
|
141
183
|
|
142
184
|
# update objects for changes in templates
|
143
|
-
created_objects.
|
144
|
-
|
185
|
+
changed_objects = created_objects.select { |o| o.template_changed? }
|
186
|
+
if changed_objects.size > 0
|
187
|
+
puts "\nUpdate Inverter objects for changed templates: "
|
188
|
+
changed_objects.each do |o|
|
145
189
|
o.update_from_template!
|
190
|
+
puts " - #{ o._template_name }"
|
146
191
|
end
|
147
192
|
end
|
148
193
|
end
|
@@ -4,7 +4,8 @@ module Inverter
|
|
4
4
|
attr_accessor(
|
5
5
|
:model_class,
|
6
6
|
:template_folders,
|
7
|
-
:excluded_templates
|
7
|
+
:excluded_templates,
|
8
|
+
:disable_middleware
|
8
9
|
)
|
9
10
|
|
10
11
|
def configure
|
@@ -17,6 +18,7 @@ module Inverter
|
|
17
18
|
|
18
19
|
def set_default_configuration
|
19
20
|
self.excluded_templates = []
|
21
|
+
self.disable_middleware = false
|
20
22
|
end
|
21
23
|
|
22
24
|
end
|
data/lib/inverter/engine.rb
CHANGED
@@ -2,4 +2,16 @@ module Inverter
|
|
2
2
|
class Engine < Rails::Engine
|
3
3
|
# auto wire
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
if Rails.env.development?
|
8
|
+
initializer "inverter.configure_rails_initialization" do
|
9
|
+
Rails.application.middleware.use Inverter::Middleware
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Inverter
|
2
|
+
class Middleware
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
# workaround this method so no need to call it if:
|
9
|
+
# - not GET request
|
10
|
+
# - not action request (assets or public files)
|
11
|
+
|
12
|
+
if ! Inverter.disable_middleware
|
13
|
+
Inverter.model_class.sync_with_templates!
|
14
|
+
end
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Inverter
|
2
|
+
class Renderer
|
3
|
+
|
4
|
+
def self.markdown_input_type?(name)
|
5
|
+
name_and_type = name.split(':')
|
6
|
+
|
7
|
+
if name_and_type.size > 1
|
8
|
+
return name_and_type[1].strip == 'markdown'
|
9
|
+
end
|
10
|
+
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.render(html, blocks)
|
15
|
+
# markdown configuration
|
16
|
+
# https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
|
17
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)
|
18
|
+
|
19
|
+
offset = 0
|
20
|
+
map = ::Inverter::Parser.map_blocks_for(html)
|
21
|
+
|
22
|
+
map.each do |name, pos|
|
23
|
+
|
24
|
+
block = blocks[name]
|
25
|
+
|
26
|
+
if markdown_input_type?(name)
|
27
|
+
block = markdown.render(block)
|
28
|
+
end
|
29
|
+
|
30
|
+
block = "\n#{ block }\n"
|
31
|
+
|
32
|
+
html[offset+pos[0]..offset+pos[1]] = block
|
33
|
+
|
34
|
+
block_size = block.size
|
35
|
+
template_block_size = pos[1] - pos[0]
|
36
|
+
offset += block_size - template_block_size - 1
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
return html
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/inverter/version.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
namespace :inverter do
|
2
|
+
|
3
|
+
desc "Reset all inverter objects to template defaults"
|
4
|
+
task :reset => :environment do
|
5
|
+
Inverter.model_class.delete_all
|
6
|
+
Inverter.model_class.sync_with_templates!
|
7
|
+
|
8
|
+
inverter_objects = Inverter.model_class.all
|
9
|
+
inverter_objects.each do |o|
|
10
|
+
puts " - #{ o._template_name }"
|
11
|
+
end
|
12
|
+
puts "\n#{ inverter_objects.size } objects created."
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
desc "Sync all inverter objects with template changes"
|
17
|
+
task :sync => :environment do
|
18
|
+
Inverter.model_class.sync_with_templates!
|
19
|
+
puts "Objects has been updated."
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inverter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Kravets
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: render_anywhere
|
@@ -38,6 +38,48 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mongoid-history
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.7
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.7
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mongoid-slug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.0.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: redcarpet
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.2.3
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.2.3
|
41
83
|
description: |
|
42
84
|
Easy way to connect Rails templates content to CMS. HTML content is marked using
|
43
85
|
special formatted comments. Then it automatically populated to models and is accessible
|
@@ -55,18 +97,25 @@ files:
|
|
55
97
|
- README.md
|
56
98
|
- Rakefile
|
57
99
|
- app/assets/javascripts/input-inverter-image.coffee
|
100
|
+
- app/assets/javascripts/input-inverter-link.coffee
|
101
|
+
- app/assets/javascripts/input-inverter-version.coffee
|
58
102
|
- app/assets/javascripts/input-inverter.coffee
|
59
103
|
- app/assets/javascripts/inverter.coffee
|
104
|
+
- app/assets/stylesheets/_inverter.scss
|
60
105
|
- inverter.gemspec
|
106
|
+
- lib/history_tracker.rb
|
61
107
|
- lib/inverter.rb
|
62
108
|
- lib/inverter/concerns/inverter.rb
|
63
109
|
- lib/inverter/configuration.rb
|
64
110
|
- lib/inverter/controller_helper.rb
|
65
111
|
- lib/inverter/engine.rb
|
112
|
+
- lib/inverter/middleware.rb
|
66
113
|
- lib/inverter/object.rb
|
67
114
|
- lib/inverter/parser.rb
|
115
|
+
- lib/inverter/renderer.rb
|
68
116
|
- lib/inverter/template_renderer_helper.rb
|
69
117
|
- lib/inverter/version.rb
|
118
|
+
- lib/tasks/inverter.rake
|
70
119
|
homepage: http://slatestudio.com
|
71
120
|
licenses:
|
72
121
|
- MIT
|