vitrage 0.0.2 → 0.0.3
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.
- 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
|