vitrage 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +97 -2
- data/Rakefile +2 -0
- data/app/assets/javascripts/vitrage/editor.js.coffee +126 -0
- data/app/assets/javascripts/vitrage/vitrage.js +3 -0
- data/app/assets/stylesheets/vitrage/editor.scss +61 -0
- data/app/assets/stylesheets/vitrage/vitrage.css +5 -0
- data/app/controllers/vitrage/pieces_controller.rb +108 -0
- data/app/views/vitrage/_edit.html.erb +13 -0
- data/app/views/vitrage/_edit_wraped_piece.html.erb +18 -0
- data/app/views/vitrage/_form_wrap.html.erb +12 -0
- data/app/views/vitrage/_show.html.erb +3 -0
- data/app/views/vitrage/pieces/create.html.erb +1 -0
- data/app/views/vitrage/pieces/edit.html.erb +1 -0
- data/app/views/vitrage/pieces/new.html.erb +4 -0
- data/app/views/vitrage/pieces/show.html.erb +1 -0
- data/config/locales/vitrage_en.yml +4 -0
- data/config/locales/vitrage_ru.yml +4 -0
- data/config/routes.rb +2 -0
- data/lib/generators/vitrage/install_generator.rb +26 -0
- data/lib/generators/vitrage/piece_generator.rb +45 -0
- data/lib/generators/vitrage/templates/migrations/create_vitrage_piece.rb +19 -0
- data/lib/generators/vitrage/templates/migrations/create_vitrage_slots.rb +16 -0
- data/lib/generators/vitrage/templates/views/piece_form_generator.html.erb +13 -0
- data/lib/generators/vitrage/templates/views/piece_show_generator.html.erb +2 -0
- data/lib/generators/vitrage/templates/vitrage_piece.rb +10 -0
- data/lib/generators/vitrage/templates/vitrage_slot.rb +10 -0
- data/lib/vitrage.rb +6 -0
- data/lib/vitrage/acts_as_vitrage_owner.rb +15 -0
- data/lib/vitrage/engine.rb +8 -0
- data/lib/vitrage/helpers/action_view_extention.rb +24 -0
- data/lib/vitrage/router.rb +21 -0
- data/lib/vitrage/version.rb +1 -1
- data/test/dummy/config/routes.rb +1 -53
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +1 -0
- metadata +104 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c668c147525e7adc7619a7c059273fdbed9cfd0d
|
4
|
+
data.tar.gz: c8c65f7cfffd9a0d231eddeb8133670bff403942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ab5a9b4d656a6fd8ff087d732b34f2ed203555dccb14c83421bbaf8c3579b3c24a9c09ce42c224b42de2f9c82ef517aef5a4db5a258cf66d0d328ee1499cca0
|
7
|
+
data.tar.gz: 96169ea834658d55a05b46cc4173cb3ed3e1d0b6d988495ca1654ab4e30d4cd75350231dd58fab80b03989e607cf10883c25944b5c129db1e72cf5cf51b043ef
|
data/README.md
CHANGED
@@ -1,13 +1,108 @@
|
|
1
1
|
Vitrage
|
2
2
|
=======
|
3
3
|
|
4
|
-
|
4
|
+
Vitrage allows store and manage your Rails application web-pages content as separated pieces of different types: text, image, slider, several-columned text etc. Pieces are objects of different Rails models having their specific views for show and edit. Vitrage allows you inline editing of content pieces.
|
5
5
|
|
6
6
|
<img src="http://www.vitroart.ru/upload/information_system_35/4/2/2/item_422/information_items_1242584051.jpg" alt="vitrage of glass" height="600" width="379">
|
7
7
|
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
Put this line in your Gemfile:
|
13
|
+
|
14
|
+
gem 'vitrage'
|
15
|
+
|
16
|
+
Then run `bundle install`.
|
17
|
+
|
18
|
+
After installing the gem, you need to run the generator.
|
19
|
+
|
20
|
+
bin/rails generate vitrage:install
|
21
|
+
|
22
|
+
The generator adds these files:
|
23
|
+
|
24
|
+
app/models/vitrage_owners_pieces_slot.rb
|
25
|
+
db/migrate/[timestamp]_create_vitrage_owners_pieces_slots.rb
|
26
|
+
|
27
|
+
and line to the `routes.rb` file:
|
28
|
+
|
29
|
+
Vitrage.routes(self)
|
30
|
+
|
31
|
+
Now, migrate your database: `bin/rake db:migrate`
|
32
|
+
|
33
|
+
Require js in your js file (`application.js` by default):
|
34
|
+
|
35
|
+
//= require vitrage/vitrage
|
36
|
+
|
37
|
+
Require vitrage css in your css file (`application.css` by default):
|
38
|
+
|
39
|
+
*= require vitrage/vitrage
|
40
|
+
|
41
|
+
|
42
|
+
Use vitrage content pieces for your model and views
|
43
|
+
---------------------------------------------------
|
44
|
+
|
45
|
+
Add to any models you want to use vitrage content pieces line:
|
46
|
+
|
47
|
+
acts_as_vitrage_owner
|
48
|
+
|
49
|
+
Add render call to the `show` view:
|
50
|
+
|
51
|
+
<%= show_vitrage_for @object %>
|
52
|
+
|
53
|
+
Add render call to the `edit` view:
|
54
|
+
|
55
|
+
<%= edit_vitrage_for @object %>
|
56
|
+
|
57
|
+
|
58
|
+
Add content piece
|
59
|
+
-----------------
|
60
|
+
|
61
|
+
Content pieces it is necessary parts of Vitrage. By default we have no pieces.
|
62
|
+
Describes process of creating simple content piece only with text field.
|
63
|
+
|
64
|
+
bin/rails generate vitrage:piece Text body:text
|
65
|
+
|
66
|
+
The generator adds these files:
|
67
|
+
|
68
|
+
db/migrate/[timestamp]_create_vtrg_texts.rb
|
69
|
+
app/models/vitrage_pieces/vtrg_text.rb
|
70
|
+
app/views/vitrage/_vtrg_text.html.erb
|
71
|
+
app/views/vitrage/_vtrg_text_form.html.erb
|
72
|
+
# ... and more
|
73
|
+
|
74
|
+
Migrate your database: `bin/rake db:migrate`
|
75
|
+
|
76
|
+
Add name of content piece model to `PIECE_CLASSES_STRINGS` array constant
|
77
|
+
of VitrageOwnersPiecesSlot model.
|
78
|
+
|
79
|
+
Add styles for add new block button:
|
80
|
+
|
81
|
+
.vtrg-new-block-kinds .vtrg-text { background: red; }
|
82
|
+
|
83
|
+
Do not forget about piece view partials.
|
84
|
+
|
85
|
+
|
86
|
+
Custom Pieces Controller
|
87
|
+
------------------------
|
88
|
+
|
89
|
+
`PiecesController` have actions for vitrage pieces.
|
90
|
+
If you need to override controller, create new controller, inherited from `Vitrage::PiecesController`:
|
91
|
+
|
92
|
+
class VitragePiecesController < Vitrage::PiecesController
|
93
|
+
# add devise authorization as option
|
94
|
+
before_action :authenticate_admin_user!
|
95
|
+
end
|
96
|
+
|
97
|
+
And add parameter `controller` to routes method call with underscored and pluralized controller name:
|
98
|
+
|
99
|
+
Vitrage.routes(self, controller: 'vitrage_pieces')
|
100
|
+
|
101
|
+
|
102
|
+
|
8
103
|
License
|
9
104
|
-------
|
10
|
-
Vitrage is released under the [MIT License](LICENSE
|
105
|
+
Vitrage is released under the [MIT License](MIT-LICENSE).
|
11
106
|
|
12
107
|
|
13
108
|
Contributing
|
data/Rakefile
CHANGED
@@ -0,0 +1,126 @@
|
|
1
|
+
$(document).ready ->
|
2
|
+
if $(".vtrg-add-new-wrapper").length
|
3
|
+
|
4
|
+
toggleEditorBlocker = ($editWrapper, act) ->
|
5
|
+
$editWrapper.toggleClass 'blocked', act
|
6
|
+
|
7
|
+
# --- # --- VIEW --- # --- #
|
8
|
+
restoreViewState = ($editWrapper, viewdata) ->
|
9
|
+
if viewdata
|
10
|
+
$editWrapper.removeClass "editmode"
|
11
|
+
$editWrapper.children(".vtrg-edit-body").html viewdata
|
12
|
+
toggleEditorBlocker $editWrapper, false
|
13
|
+
else
|
14
|
+
$.ajax
|
15
|
+
url: "/vitrage/pieces/" + $editWrapper.data("id")
|
16
|
+
# type: "GET"
|
17
|
+
dataType: "html"
|
18
|
+
success: (data, textStatus, jqXHR) ->
|
19
|
+
restoreViewState $editWrapper, data
|
20
|
+
# error: null
|
21
|
+
|
22
|
+
# --- # --- UPDATE and cancel editing --- # --- #
|
23
|
+
coverEditFormActions = ($editWrapper) ->
|
24
|
+
# cover Submit action
|
25
|
+
$blockForm = $editWrapper.find('form')
|
26
|
+
|
27
|
+
$blockForm.on "ajax:before", ->
|
28
|
+
toggleEditorBlocker $editWrapper, true
|
29
|
+
return true # do your work buddy
|
30
|
+
|
31
|
+
$blockForm.on "ajax:success", (evnt, data, textStatus, jqXHR) ->
|
32
|
+
restoreViewState $(@).closest(".vtrg-edit-wrapper"), data
|
33
|
+
# $blockForm.on "ajax:error"
|
34
|
+
# $blockForm.on "ajax:complete"
|
35
|
+
|
36
|
+
|
37
|
+
# cover Cancel action
|
38
|
+
$editWrapper.find('form .actions a').click (evnt) ->
|
39
|
+
$clickedAnchor = $(@)
|
40
|
+
clickedAnchorParentID = $clickedAnchor.parent().attr("id")
|
41
|
+
if clickedAnchorParentID && clickedAnchorParentID.substr(clickedAnchorParentID.length - 13) == "cancel_action"
|
42
|
+
evnt.preventDefault()
|
43
|
+
toggleEditorBlocker $editWrapper, true
|
44
|
+
restoreViewState $editWrapper
|
45
|
+
return false
|
46
|
+
|
47
|
+
# --- # --- EDIT --- # --- #
|
48
|
+
initEditControl = (wrappers) ->
|
49
|
+
wrappers.find(".vtrg-edit-control a[rel=edit]").click (evnt) ->
|
50
|
+
evnt.preventDefault()
|
51
|
+
$editWrapper = $(@).closest(".vtrg-edit-wrapper")
|
52
|
+
toggleEditorBlocker $editWrapper, true
|
53
|
+
$.ajax
|
54
|
+
url: "/vitrage/pieces/" + $editWrapper.data("id") + "/edit"
|
55
|
+
# type: "GET"
|
56
|
+
dataType: "html"
|
57
|
+
success: (data, textStatus, jqXHR) ->
|
58
|
+
$editWrapper.addClass "editmode"
|
59
|
+
$editWrapper.children(".vtrg-edit-body").html data
|
60
|
+
coverEditFormActions $editWrapper
|
61
|
+
toggleEditorBlocker $editWrapper, false
|
62
|
+
# error: null
|
63
|
+
return
|
64
|
+
return
|
65
|
+
# init edit control for all exists
|
66
|
+
initEditControl $(".vtrg-edit-wrapper")
|
67
|
+
|
68
|
+
# --- # --- DESTROY --- # --- #
|
69
|
+
initDestroyControl = (wrappers) ->
|
70
|
+
wrappers.find(".vtrg-edit-control a[rel=destroy]").click (evnt) ->
|
71
|
+
evnt.preventDefault()
|
72
|
+
$editWrapper = $(@).closest(".vtrg-edit-wrapper")
|
73
|
+
if confirm("Are you sure?")
|
74
|
+
toggleEditorBlocker $editWrapper, true
|
75
|
+
$.ajax
|
76
|
+
url: "/vitrage/pieces/" + $editWrapper.data("id")
|
77
|
+
type: "DELETE"
|
78
|
+
dataType: "html"
|
79
|
+
success: (data, textStatus, jqXHR) ->
|
80
|
+
$editWrapper.remove()
|
81
|
+
# error: null
|
82
|
+
return
|
83
|
+
return
|
84
|
+
# init destroy control for all exists
|
85
|
+
initDestroyControl $(".vtrg-edit-wrapper")
|
86
|
+
|
87
|
+
# --- # --- CREATE and cancel creating --- # --- #
|
88
|
+
coverNewFormActions = ($editWrapper) ->
|
89
|
+
# cover Submit action
|
90
|
+
$blockForm = $editWrapper.find('form')
|
91
|
+
|
92
|
+
$blockForm.on "ajax:before", ->
|
93
|
+
toggleEditorBlocker $editWrapper, true
|
94
|
+
return true # do your work buddy
|
95
|
+
|
96
|
+
$blockForm.on "ajax:success", (evnt, data, textStatus, jqXHR) ->
|
97
|
+
clwr = $(@).closest(".vtrg-edit-wrapper")
|
98
|
+
if $(@).data('remotipartSubmitted')
|
99
|
+
a = 12
|
100
|
+
console.log "ololo"
|
101
|
+
else
|
102
|
+
clwr.after data
|
103
|
+
brandNewWrapper = clwr.next()
|
104
|
+
clwr.remove()
|
105
|
+
initDestroyControl brandNewWrapper
|
106
|
+
initEditControl brandNewWrapper
|
107
|
+
# $blockForm.on "ajax:error"
|
108
|
+
$blockForm.on "ajax:complete", ->
|
109
|
+
toggleEditorBlocker $(@).closest(".vtrg-edit-wrapper"), false
|
110
|
+
|
111
|
+
# cover Cancel action
|
112
|
+
$editWrapper.find('form .actions a').click (evnt) ->
|
113
|
+
$clickedAnchor = $(@)
|
114
|
+
clickedAnchorParentID = $clickedAnchor.parent().attr("id")
|
115
|
+
if clickedAnchorParentID && clickedAnchorParentID.substr(clickedAnchorParentID.length - 13) == "cancel_action"
|
116
|
+
evnt.preventDefault()
|
117
|
+
$clickedAnchor.closest(".vtrg-edit-wrapper").remove()
|
118
|
+
return false
|
119
|
+
|
120
|
+
# --- # --- NEW --- # --- #
|
121
|
+
$createAnchors = $(".vtrg-new-block-kinds a")
|
122
|
+
$createAnchors.on "ajax:success", (evnt, data, textStatus, jqXHR) ->
|
123
|
+
$(".vtrg-add-new-wrapper").before data
|
124
|
+
coverNewFormActions $(".vtrg-edit-wrapper:last")
|
125
|
+
# $createAnchors.on "ajax:error"
|
126
|
+
# $createAnchors.on "ajax:complete"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
$vtrg-act-color: #c19a6b; // Цвет увядших листьев
|
2
|
+
@mixin activated_state { box-shadow: 0 0 0 2px $vtrg-act-color inset; }
|
3
|
+
|
4
|
+
.vtrg-edit-wrapper {
|
5
|
+
position: relative;
|
6
|
+
min-height: 64px;
|
7
|
+
|
8
|
+
// clearfix
|
9
|
+
&:before, &:after { display: table; content: " "; }
|
10
|
+
&:after { clear: both; }
|
11
|
+
|
12
|
+
// ==== controls block ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
|
13
|
+
.vtrg-edit-control {
|
14
|
+
display: none;
|
15
|
+
position: absolute;
|
16
|
+
&.top { top: 0; left: 0; }
|
17
|
+
&.bottom { right: 0; bottom: 0; }
|
18
|
+
padding: 4px;
|
19
|
+
background: $vtrg-act-color;
|
20
|
+
a { text-decoration: none; &:hover { fill: #fff; } }
|
21
|
+
.icon { vertical-align: middle; }
|
22
|
+
}
|
23
|
+
&:hover { @include activated_state; .vtrg-edit-control { display: block; } }
|
24
|
+
&.editmode { @include activated_state; .vtrg-edit-control { display: none; } }
|
25
|
+
&.blocked { .vtrg-edit-control { display: none; } }
|
26
|
+
|
27
|
+
// ==== block cover overlay ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
|
28
|
+
.vtrg-edit-block-cover {
|
29
|
+
display: none;
|
30
|
+
position: absolute;
|
31
|
+
top: 0; right: 0; bottom: 0; left: 0;
|
32
|
+
background: #eee;
|
33
|
+
opacity: 0.8;
|
34
|
+
text-align: center;
|
35
|
+
fill: blue;
|
36
|
+
}
|
37
|
+
&.blocked .vtrg-edit-block-cover { display: block; }
|
38
|
+
}
|
39
|
+
|
40
|
+
// ==== add new block button ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
|
41
|
+
.vtrg-add-new {
|
42
|
+
display: block;
|
43
|
+
text-align: center;
|
44
|
+
&:hover { background: $vtrg-act-color + #333; fill: #666; }
|
45
|
+
&:active { fill: #000; }
|
46
|
+
}
|
47
|
+
|
48
|
+
.vtrg-new-block-kinds {
|
49
|
+
text-align: center;
|
50
|
+
span { display: inline-block; margin-right: 6px; }
|
51
|
+
span, a { vertical-align: middle; }
|
52
|
+
a {
|
53
|
+
display: inline-block;
|
54
|
+
margin: 0 4px;
|
55
|
+
width: 64px;
|
56
|
+
height: 64px;
|
57
|
+
cursor: pointer;
|
58
|
+
&:hover { opacity: 0.6; }
|
59
|
+
&:active { opacity: 1; }
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Vitrage
|
2
|
+
class PiecesController < ApplicationController
|
3
|
+
before_action :find_vitrage_piece, only: [:show, :edit, :update]
|
4
|
+
|
5
|
+
def show
|
6
|
+
respond_to do |format|
|
7
|
+
format.html { render layout: false }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
piece_class = params[:kind]
|
13
|
+
unless piece_class &&
|
14
|
+
VitrageOwnersPiecesSlot::PIECE_CLASSES_STRINGS.include?(piece_class)
|
15
|
+
piece_class = VitrageOwnersPiecesSlot::PIECE_CLASSES_STRINGS.first
|
16
|
+
end
|
17
|
+
@piece = VitragePieces.const_get(piece_class).new
|
18
|
+
|
19
|
+
respond_to do |format|
|
20
|
+
format.html { render layout: false }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit
|
25
|
+
respond_to do |format|
|
26
|
+
format.html { render layout: false }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def create
|
31
|
+
wrong_params_here = false
|
32
|
+
|
33
|
+
# check existance of params
|
34
|
+
unless params[:kind] &&
|
35
|
+
VitrageOwnersPiecesSlot::PIECE_CLASSES_STRINGS.include?(params[:kind]) &&
|
36
|
+
params[:owner_type] &&
|
37
|
+
params[:owner_id]
|
38
|
+
wrong_params_here = true
|
39
|
+
end
|
40
|
+
|
41
|
+
# get the owner of vitrage
|
42
|
+
unless wrong_params_here
|
43
|
+
@owner = nil
|
44
|
+
begin
|
45
|
+
@owner = Object.const_get(params[:owner_type]).find params[:owner_id]
|
46
|
+
rescue Exception => e
|
47
|
+
wrong_params_here = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# create piece
|
52
|
+
unless wrong_params_here
|
53
|
+
@piece = VitragePieces.const_get(params[:kind]).new
|
54
|
+
@piece.assign_attributes vitrage_piece_params
|
55
|
+
wrong_params_here = true unless @piece.save
|
56
|
+
end
|
57
|
+
|
58
|
+
# create vitrage slot
|
59
|
+
unless wrong_params_here
|
60
|
+
@slot = VitrageOwnersPiecesSlot.new owner: @owner, piece: @piece
|
61
|
+
unless @slot.save
|
62
|
+
wrong_params_here = true
|
63
|
+
@piece.destroy
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if wrong_params_here
|
68
|
+
respond_to do |format|
|
69
|
+
format.html { render text: "error", status: :unprocessable_entity }
|
70
|
+
end
|
71
|
+
else
|
72
|
+
# respond_to do |format|
|
73
|
+
# format.html { render layout: false }
|
74
|
+
# end
|
75
|
+
render layout: false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def update
|
80
|
+
@piece.update vitrage_piece_params
|
81
|
+
|
82
|
+
respond_to do |format|
|
83
|
+
format.html { render action: "show", layout: false }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def destroy
|
88
|
+
@slot = VitrageOwnersPiecesSlot.find params[:id]
|
89
|
+
@slot.destroy
|
90
|
+
|
91
|
+
respond_to do |format|
|
92
|
+
format.html { render text: "" }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def find_vitrage_piece
|
99
|
+
@slot = VitrageOwnersPiecesSlot.find params[:id]
|
100
|
+
@piece = @slot.piece
|
101
|
+
end
|
102
|
+
|
103
|
+
def vitrage_piece_params
|
104
|
+
params.require(@piece.class.name.underscore.gsub('/', '_').to_sym).
|
105
|
+
permit @piece.params_for_permit
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= evil_icons_sprite %>
|
2
|
+
<% owner.vitrage_slots.each do |slot| %>
|
3
|
+
<%= render partial: "vitrage/edit_wraped_piece", locals: { slot: slot } %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<div class="vtrg-add-new-wrapper">
|
7
|
+
<div class="vtrg-new-block-kinds">
|
8
|
+
<span><%= evil_icon 'ei-plus', size: "l" %></span>
|
9
|
+
<% VitrageOwnersPiecesSlot::PIECE_CLASSES_STRINGS.each do |piece_class_string| %>
|
10
|
+
<%= link_to "", Rails.application.routes.url_helpers.new_vitrage_piece_path(kind: piece_class_string, owner_type: owner.class.name, owner_id: owner.id), role: "button", class: piece_class_string.underscore.dasherize, remote: true %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% piece = piece || slot.piece %>
|
2
|
+
|
3
|
+
<div class="vtrg-edit-wrapper" data-id="<%= slot.id %>">
|
4
|
+
<% ['top', 'bottom'].each do |position_class| %>
|
5
|
+
<div class="vtrg-edit-control <%= position_class %>">
|
6
|
+
<a href="javascript:void(0)" role="button" rel="edit" title="<%= t('vitrage.edit') %>">
|
7
|
+
<%= evil_icon 'ei-pencil', size: "m" %>
|
8
|
+
</a>
|
9
|
+
<a href="javascript:void(0)" role="button" rel="destroy" title="<%= t('vitrage.destroy') %>">
|
10
|
+
<%= evil_icon 'ei-trash', size: "m" %>
|
11
|
+
</a>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
<div class="vtrg-edit-block-cover"><%= evil_icon 'ei-spinner', size: "m" %></div>
|
15
|
+
<div class="vtrg-edit-body">
|
16
|
+
<%= render partial: "vitrage/#{piece.class.name.demodulize.underscore}", locals: { piece: piece } %>
|
17
|
+
</div>
|
18
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% slot = slot || (piece.new_record? ? nil : piece.slot) %>
|
2
|
+
|
3
|
+
<% if slot && !slot.new_record? %>
|
4
|
+
<% form_url = Rails.application.routes.url_helpers.vitrage_piece_path(slot.id) %>
|
5
|
+
<% form_method = :patch %>
|
6
|
+
<% else %>
|
7
|
+
<% form_url = Rails.application.routes.url_helpers.vitrage_pieces_path %>
|
8
|
+
<% form_method = :post %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%#TODO make helper for building forms in the piece partial (like the `form` method of active_admin) %>
|
12
|
+
<%= render partial: "vitrage/#{piece.class.name.demodulize.underscore}_form", locals: { piece: piece, form_url: form_url, form_method: form_method } %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: "vitrage/edit_wraped_piece", locals: { slot: @slot, piece: @piece } %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: "vitrage/form_wrap", locals: { slot: @slot, piece: @piece } %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: "vitrage/#{@item.class.name.demodulize.underscore}", locals: { piece: @piece } %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module Vitrage
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ActiveRecord::Generators::Base
|
6
|
+
desc "Create migration, model and routes for Vitrage"
|
7
|
+
|
8
|
+
argument :name, type: :string, default: "VitragePiece" # TODO we don't needs name
|
9
|
+
|
10
|
+
source_root File.expand_path("../templates", __FILE__)
|
11
|
+
|
12
|
+
def copy_vitrage_piece_model_file
|
13
|
+
copy_file "vitrage_slot.rb", "app/models/vitrage_owners_pieces_slot.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_vitrage_piece_migration
|
17
|
+
migration_template "migrations/create_vitrage_slots.rb",
|
18
|
+
"db/migrate/create_vitrage_owners_pieces_slots.rb"
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_routes
|
22
|
+
route "Vitrage.routes(self)"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rails/generators/active_record/model/model_generator'
|
2
|
+
|
3
|
+
# I think it isn't optimal solution for items models generation. Rethink.
|
4
|
+
|
5
|
+
module Vitrage
|
6
|
+
module Generators
|
7
|
+
class PieceGenerator < ActiveRecord::Generators::ModelGenerator
|
8
|
+
desc "Create vitrage piece model, migration and necessary views"
|
9
|
+
|
10
|
+
source_root File.expand_path("../templates", __FILE__)
|
11
|
+
|
12
|
+
def class_name
|
13
|
+
clsn = super
|
14
|
+
clsn[0..3] == "Vtrg" ? clsn : "Vtrg#{clsn}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_name
|
18
|
+
flen = super
|
19
|
+
flen[0..4] == "vtrg_" ? flen : "vtrg_#{flen}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def table_name
|
23
|
+
tbns = super
|
24
|
+
tbns[0..4] == "vtrg_" ? tbns : "vtrg_#{tbns}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# override ActiveRecord::Generators::ModelGenerator method
|
28
|
+
def create_migration_file
|
29
|
+
return unless options[:migration] && options[:parent].nil?
|
30
|
+
attributes.each { |a| a.attr_options.delete(:index) if a.reference? && !a.has_index? } if options[:indexes] == false
|
31
|
+
migration_template "migrations/create_vitrage_piece.rb", "db/migrate/create_#{table_name}.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
# override ActiveRecord::Generators::ModelGenerator method
|
35
|
+
def create_model_file
|
36
|
+
template 'vitrage_piece.rb', File.join('app/models/vitrage_pieces/', class_path, "#{file_name}.rb")
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_necessary_views
|
40
|
+
copy_file 'views/piece_show_generator.html.erb', File.join('app/views/vitrage/', "_#{file_name}.html.erb")
|
41
|
+
copy_file 'views/piece_form_generator.html.erb', File.join('app/views/vitrage/', "_#{file_name}_form.html.erb")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
<% attributes.each do |attribute| -%>
|
5
|
+
<% if attribute.password_digest? -%>
|
6
|
+
t.string :password_digest<%= attribute.inject_options %>
|
7
|
+
<% else -%>
|
8
|
+
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
|
9
|
+
<% end -%>
|
10
|
+
<% end -%>
|
11
|
+
<% if options[:timestamps] %>
|
12
|
+
t.timestamps
|
13
|
+
<% end -%>
|
14
|
+
end
|
15
|
+
<% attributes_with_index.each do |attribute| -%>
|
16
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
17
|
+
<% end -%>
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateVitrageOwnersPiecesSlots < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :vitrage_owners_pieces_slots do |t|
|
4
|
+
t.references :owner, polymorphic: true, null: false, index: true
|
5
|
+
t.references :piece, polymorphic: true, index: true
|
6
|
+
t.integer :ordn, default: 9, null: false
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :vitrage_owners_pieces_slots, :ordn
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :vitrage_owners_pieces_slots
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= semantic_form_for piece, url: form_url, method: form_method, remote: true do |f| %>
|
2
|
+
<%= f.inputs do %>
|
3
|
+
<%# Add inputs of your piece model here %>
|
4
|
+
<%# f.input :body, input_html: { rows: 2 } %>
|
5
|
+
<% end -%>
|
6
|
+
<%= hidden_field_tag :kind, piece.class.name.demodulize, id: nil %>
|
7
|
+
<%= hidden_field_tag :owner_type, params[:owner_type], id: nil %>
|
8
|
+
<%= hidden_field_tag :owner_id, params[:owner_id], id: nil %>
|
9
|
+
<%= f.actions do %>
|
10
|
+
<%= f.action :submit, as: :button %>
|
11
|
+
<%= f.action :cancel, as: :link %>
|
12
|
+
<% end -%>
|
13
|
+
<% end -%>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class VitrageOwnersPiecesSlot < ActiveRecord::Base
|
2
|
+
# stored fields: :owner_type, :owner_id, :piece_type, :piece_id, :ordn
|
3
|
+
|
4
|
+
belongs_to :owner, polymorphic: true
|
5
|
+
belongs_to :piece, polymorphic: true, dependent: :destroy
|
6
|
+
|
7
|
+
default_scope -> { order(ordn: :asc, id: :asc) }
|
8
|
+
|
9
|
+
PIECE_CLASSES_STRINGS = [ ] # add pieces class names strings here (demodulized)
|
10
|
+
end
|
data/lib/vitrage.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Vitrage
|
2
|
+
module ActsAsVitrageOwner
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def acts_as_vitrage_owner
|
7
|
+
has_many :vitrage_slots, class_name: "VitrageOwnersPiecesSlot",
|
8
|
+
as: :owner,
|
9
|
+
dependent: :destroy
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Base.send :include, Vitrage::ActsAsVitrageOwner
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vitrage
|
2
|
+
# = Helpers
|
3
|
+
module ActionViewExtension
|
4
|
+
# A helper that renders the show view of vitrage
|
5
|
+
#
|
6
|
+
# <%= show_vitrage_for @page %>
|
7
|
+
#
|
8
|
+
def show_vitrage_for(owner)
|
9
|
+
render partial: 'vitrage/show', locals: { owner: owner }
|
10
|
+
end
|
11
|
+
|
12
|
+
# A helper that renders the show view of vitrage
|
13
|
+
#
|
14
|
+
# <%= edit_vitrage_for @page %>
|
15
|
+
#
|
16
|
+
def edit_vitrage_for(owner)
|
17
|
+
render partial: 'vitrage/edit', locals: { owner: owner }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveSupport.on_load(:action_view) do
|
23
|
+
ActionView::Base.send :include, Vitrage::ActionViewExtension
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Vitrage
|
2
|
+
module Router
|
3
|
+
|
4
|
+
def routes(rails_router, options = {})
|
5
|
+
if options[:controller]
|
6
|
+
cs = options[:controller].to_s
|
7
|
+
rails_router.post '/vitrage/pieces' => "#{cs}#create", as: :vitrage_pieces
|
8
|
+
rails_router.get '/vitrage/pieces/new' => "#{cs}#new", as: :new_vitrage_piece
|
9
|
+
rails_router.get '/vitrage/pieces/:id/edit' => "#{cs}#edit", as: :edit_vitrage_piece
|
10
|
+
rails_router.get '/vitrage/pieces/:id' => "#{cs}#show", as: :vitrage_piece
|
11
|
+
rails_router.match '/vitrage/pieces/:id' => "#{cs}#update", via: [:patch, :put]
|
12
|
+
rails_router.delete '/vitrage/pieces/:id' => "#{cs}#destroy"
|
13
|
+
else
|
14
|
+
rails_router.namespace :vitrage do
|
15
|
+
rails_router.resources :pieces, except: [:index]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/vitrage/version.rb
CHANGED
data/test/dummy/config/routes.rb
CHANGED
@@ -1,56 +1,4 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
# The priority is based upon order of creation: first created -> highest priority.
|
3
|
-
# See how all your routes lay out with "rake routes".
|
4
2
|
|
5
|
-
|
6
|
-
# root 'welcome#index'
|
7
|
-
|
8
|
-
# Example of regular route:
|
9
|
-
# get 'products/:id' => 'catalog#view'
|
10
|
-
|
11
|
-
# Example of named route that can be invoked with purchase_url(id: product.id)
|
12
|
-
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
13
|
-
|
14
|
-
# Example resource route (maps HTTP verbs to controller actions automatically):
|
15
|
-
# resources :products
|
16
|
-
|
17
|
-
# Example resource route with options:
|
18
|
-
# resources :products do
|
19
|
-
# member do
|
20
|
-
# get 'short'
|
21
|
-
# post 'toggle'
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# collection do
|
25
|
-
# get 'sold'
|
26
|
-
# end
|
27
|
-
# end
|
28
|
-
|
29
|
-
# Example resource route with sub-resources:
|
30
|
-
# resources :products do
|
31
|
-
# resources :comments, :sales
|
32
|
-
# resource :seller
|
33
|
-
# end
|
34
|
-
|
35
|
-
# Example resource route with more complex sub-resources:
|
36
|
-
# resources :products do
|
37
|
-
# resources :comments
|
38
|
-
# resources :sales do
|
39
|
-
# get 'recent', on: :collection
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
|
43
|
-
# Example resource route with concerns:
|
44
|
-
# concern :toggleable do
|
45
|
-
# post 'toggle'
|
46
|
-
# end
|
47
|
-
# resources :posts, concerns: :toggleable
|
48
|
-
# resources :photos, concerns: :toggleable
|
49
|
-
|
50
|
-
# Example resource route within a namespace:
|
51
|
-
# namespace :admin do
|
52
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
53
|
-
# # (app/controllers/admin/products_controller.rb)
|
54
|
-
# resources :products
|
55
|
-
# end
|
3
|
+
mount Vitrage::Engine => "/vitrage"
|
56
4
|
end
|
data/test/test_helper.rb
CHANGED
@@ -3,6 +3,7 @@ ENV["RAILS_ENV"] = "test"
|
|
3
3
|
|
4
4
|
require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
|
5
5
|
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../test/dummy/db/migrate", __FILE__)]
|
6
|
+
ActiveRecord::Migrator.migrations_paths << File.expand_path('../../db/migrate', __FILE__)
|
6
7
|
require "rails/test_help"
|
7
8
|
|
8
9
|
# Filter out Minitest backtrace while allowing backtrace from other libraries
|
metadata
CHANGED
@@ -1,29 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vitrage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Dymkov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sass-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: coffee-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: jquery-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: formtastic
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: evil_icons
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
27
97
|
- !ruby/object:Gem::Dependency
|
28
98
|
name: sqlite3
|
29
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,8 +121,36 @@ files:
|
|
51
121
|
- MIT-LICENSE
|
52
122
|
- README.md
|
53
123
|
- Rakefile
|
124
|
+
- app/assets/javascripts/vitrage/editor.js.coffee
|
125
|
+
- app/assets/javascripts/vitrage/vitrage.js
|
126
|
+
- app/assets/stylesheets/vitrage/editor.scss
|
127
|
+
- app/assets/stylesheets/vitrage/vitrage.css
|
128
|
+
- app/controllers/vitrage/pieces_controller.rb
|
129
|
+
- app/views/vitrage/_edit.html.erb
|
130
|
+
- app/views/vitrage/_edit_wraped_piece.html.erb
|
131
|
+
- app/views/vitrage/_form_wrap.html.erb
|
132
|
+
- app/views/vitrage/_show.html.erb
|
133
|
+
- app/views/vitrage/pieces/create.html.erb
|
134
|
+
- app/views/vitrage/pieces/edit.html.erb
|
135
|
+
- app/views/vitrage/pieces/new.html.erb
|
136
|
+
- app/views/vitrage/pieces/show.html.erb
|
137
|
+
- config/locales/vitrage_en.yml
|
138
|
+
- config/locales/vitrage_ru.yml
|
139
|
+
- config/routes.rb
|
140
|
+
- lib/generators/vitrage/install_generator.rb
|
141
|
+
- lib/generators/vitrage/piece_generator.rb
|
142
|
+
- lib/generators/vitrage/templates/migrations/create_vitrage_piece.rb
|
143
|
+
- lib/generators/vitrage/templates/migrations/create_vitrage_slots.rb
|
144
|
+
- lib/generators/vitrage/templates/views/piece_form_generator.html.erb
|
145
|
+
- lib/generators/vitrage/templates/views/piece_show_generator.html.erb
|
146
|
+
- lib/generators/vitrage/templates/vitrage_piece.rb
|
147
|
+
- lib/generators/vitrage/templates/vitrage_slot.rb
|
54
148
|
- lib/tasks/vitrage_tasks.rake
|
55
149
|
- lib/vitrage.rb
|
150
|
+
- lib/vitrage/acts_as_vitrage_owner.rb
|
151
|
+
- lib/vitrage/engine.rb
|
152
|
+
- lib/vitrage/helpers/action_view_extention.rb
|
153
|
+
- lib/vitrage/router.rb
|
56
154
|
- lib/vitrage/version.rb
|
57
155
|
- test/dummy/README.rdoc
|
58
156
|
- test/dummy/Rakefile
|
@@ -87,6 +185,7 @@ files:
|
|
87
185
|
- test/dummy/public/422.html
|
88
186
|
- test/dummy/public/500.html
|
89
187
|
- test/dummy/public/favicon.ico
|
188
|
+
- test/integration/navigation_test.rb
|
90
189
|
- test/test_helper.rb
|
91
190
|
- test/vitrage_test.rb
|
92
191
|
homepage: https://github.com/dymio/vitrage
|
@@ -147,5 +246,6 @@ test_files:
|
|
147
246
|
- test/dummy/public/favicon.ico
|
148
247
|
- test/dummy/Rakefile
|
149
248
|
- test/dummy/README.rdoc
|
249
|
+
- test/integration/navigation_test.rb
|
150
250
|
- test/test_helper.rb
|
151
251
|
- test/vitrage_test.rb
|