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.
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