vitrage 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +97 -2
  3. data/Rakefile +2 -0
  4. data/app/assets/javascripts/vitrage/editor.js.coffee +126 -0
  5. data/app/assets/javascripts/vitrage/vitrage.js +3 -0
  6. data/app/assets/stylesheets/vitrage/editor.scss +61 -0
  7. data/app/assets/stylesheets/vitrage/vitrage.css +5 -0
  8. data/app/controllers/vitrage/pieces_controller.rb +108 -0
  9. data/app/views/vitrage/_edit.html.erb +13 -0
  10. data/app/views/vitrage/_edit_wraped_piece.html.erb +18 -0
  11. data/app/views/vitrage/_form_wrap.html.erb +12 -0
  12. data/app/views/vitrage/_show.html.erb +3 -0
  13. data/app/views/vitrage/pieces/create.html.erb +1 -0
  14. data/app/views/vitrage/pieces/edit.html.erb +1 -0
  15. data/app/views/vitrage/pieces/new.html.erb +4 -0
  16. data/app/views/vitrage/pieces/show.html.erb +1 -0
  17. data/config/locales/vitrage_en.yml +4 -0
  18. data/config/locales/vitrage_ru.yml +4 -0
  19. data/config/routes.rb +2 -0
  20. data/lib/generators/vitrage/install_generator.rb +26 -0
  21. data/lib/generators/vitrage/piece_generator.rb +45 -0
  22. data/lib/generators/vitrage/templates/migrations/create_vitrage_piece.rb +19 -0
  23. data/lib/generators/vitrage/templates/migrations/create_vitrage_slots.rb +16 -0
  24. data/lib/generators/vitrage/templates/views/piece_form_generator.html.erb +13 -0
  25. data/lib/generators/vitrage/templates/views/piece_show_generator.html.erb +2 -0
  26. data/lib/generators/vitrage/templates/vitrage_piece.rb +10 -0
  27. data/lib/generators/vitrage/templates/vitrage_slot.rb +10 -0
  28. data/lib/vitrage.rb +6 -0
  29. data/lib/vitrage/acts_as_vitrage_owner.rb +15 -0
  30. data/lib/vitrage/engine.rb +8 -0
  31. data/lib/vitrage/helpers/action_view_extention.rb +24 -0
  32. data/lib/vitrage/router.rb +21 -0
  33. data/lib/vitrage/version.rb +1 -1
  34. data/test/dummy/config/routes.rb +1 -53
  35. data/test/integration/navigation_test.rb +10 -0
  36. data/test/test_helper.rb +1 -0
  37. metadata +104 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4cb54cda342076512c65c1afca7718ee5cb652e
4
- data.tar.gz: d9cd77e545316f9587420f5a9264a93b4c7fdf60
3
+ metadata.gz: c668c147525e7adc7619a7c059273fdbed9cfd0d
4
+ data.tar.gz: c8c65f7cfffd9a0d231eddeb8133670bff403942
5
5
  SHA512:
6
- metadata.gz: 310bf43f633a73a4e81cb4c2533f5cf76d49e3f875df11fd4bb5243abf5e7f4cce7d4223cabeb44696aace13f49a5f97b5b529036cdbd46d4afcf63ebecfa75f
7
- data.tar.gz: 7ad7f48d6ed6b766465efe1539fb7ad3a122cf2c8987cbfab8f69849e6c78a60999cb3015fbf714b296219eb10f5a45fec22ab0cee4c7db166786db4a697be4b
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
- Web-Page content manage for Rails, based on separated content pieces (blocks).
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.txt).
105
+ Vitrage is released under the [MIT License](MIT-LICENSE).
11
106
 
12
107
 
13
108
  Contributing
data/Rakefile CHANGED
@@ -14,6 +14,8 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
14
  rdoc.rdoc_files.include('lib/**/*.rb')
15
15
  end
16
16
 
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
17
19
 
18
20
 
19
21
 
@@ -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,3 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require vitrage/editor
@@ -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,5 @@
1
+ /*
2
+ *= require evil-icons
3
+ *= require vitrage/editor
4
+ *= require_self
5
+ */
@@ -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,3 @@
1
+ <% owner.vitrage_slots.each do |slot| %>
2
+ <%= render partial: "vitrage/#{slot.piece.class.name.demodulize.underscore}", locals: { piece: slot.piece } %>
3
+ <% end %>
@@ -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,4 @@
1
+ <div class="vtrg-edit-wrapper editmode">
2
+ <div class="vtrg-edit-block-cover"><%= evil_icon 'ei-spinner', size: "m" %></div>
3
+ <%= render partial: "vitrage/form_wrap", locals: { piece: @piece } %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= render partial: "vitrage/#{@item.class.name.demodulize.underscore}", locals: { piece: @piece } %>
@@ -0,0 +1,4 @@
1
+ en:
2
+ vitrage:
3
+ edit: "Edit"
4
+ destroy: "Delete"
@@ -0,0 +1,4 @@
1
+ ru:
2
+ vitrage:
3
+ edit: "Редактировать"
4
+ destroy: "Удалить"
@@ -0,0 +1,2 @@
1
+ Vitrage::Engine.routes.draw do
2
+ end
@@ -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,2 @@
1
+ <%# Add any view code here. Variable 'piece' has object of your piece model %>
2
+ <%# piece.body %>
@@ -0,0 +1,10 @@
1
+ module VitragePieces
2
+ class <%= class_name %> < <%= parent_class_name.classify %>
3
+ has_one :slot, class_name: "VitrageOwnersPiecesSlot", as: :piece
4
+
5
+ def params_for_permit
6
+ [<%= attributes.each.map{|at| ":#{at.name}"}.join(', ')%>]
7
+ end
8
+
9
+ end
10
+ 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
@@ -1,2 +1,8 @@
1
+ require "vitrage/engine"
2
+ require "vitrage/router"
3
+ require "vitrage/acts_as_vitrage_owner"
4
+ require "vitrage/helpers/action_view_extention"
5
+
1
6
  module Vitrage
7
+ extend Vitrage::Router
2
8
  end
@@ -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,8 @@
1
+ module Vitrage
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Vitrage
4
+ require 'jquery-rails'
5
+ require 'formtastic'
6
+ require 'evil_icons'
7
+ end
8
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Vitrage
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -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
- # You can have the root of your site routed with "root"
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
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+
3
+ class NavigationTest < ActionDispatch::IntegrationTest
4
+ fixtures :all
5
+
6
+ # test "the truth" do
7
+ # assert true
8
+ # end
9
+ end
10
+
@@ -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.2
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-01-26 00:00:00.000000000 Z
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