sibu 0.1.0

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +33 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/sibu_manifest.js +2 -0
  6. data/app/assets/javascripts/sibu/sibu.js.erb +3 -0
  7. data/app/assets/stylesheets/sibu/sibu.scss.erb +36 -0
  8. data/app/controllers/sibu/application_controller.rb +6 -0
  9. data/app/controllers/sibu/pages_controller.rb +106 -0
  10. data/app/controllers/sibu/sites_controller.rb +59 -0
  11. data/app/helpers/sibu/application_helper.rb +7 -0
  12. data/app/helpers/sibu/pages_helper.rb +16 -0
  13. data/app/helpers/sibu/sites_helper.rb +4 -0
  14. data/app/jobs/sibu/application_job.rb +4 -0
  15. data/app/mailers/sibu/application_mailer.rb +6 -0
  16. data/app/models/concerns/sibu/image_uploader.rb +3 -0
  17. data/app/models/concerns/sibu/sections_concern.rb +53 -0
  18. data/app/models/sibu/application_record.rb +5 -0
  19. data/app/models/sibu/image.rb +5 -0
  20. data/app/models/sibu/page.rb +11 -0
  21. data/app/models/sibu/site.rb +34 -0
  22. data/app/models/sibu/site_template.rb +4 -0
  23. data/app/views/layouts/sibu/application.html.erb +18 -0
  24. data/app/views/layouts/sibu/edit_content.html.erb +49 -0
  25. data/app/views/layouts/sibu/site.html.erb +21 -0
  26. data/app/views/sibu/pages/_edit_panel.html.erb +19 -0
  27. data/app/views/sibu/pages/_form.html.erb +31 -0
  28. data/app/views/sibu/pages/destroy.html.erb +2 -0
  29. data/app/views/sibu/pages/edit.html.erb +9 -0
  30. data/app/views/sibu/pages/edit_content.html.erb +3 -0
  31. data/app/views/sibu/pages/edit_element.js.erb +4 -0
  32. data/app/views/sibu/pages/index.html.erb +39 -0
  33. data/app/views/sibu/pages/new.html.erb +9 -0
  34. data/app/views/sibu/pages/show.html.erb +1 -0
  35. data/app/views/sibu/pages/update.html.erb +2 -0
  36. data/app/views/sibu/pages/update_element.js.erb +7 -0
  37. data/app/views/sibu/sites/_form.html.erb +15 -0
  38. data/app/views/sibu/sites/destroy.html.erb +2 -0
  39. data/app/views/sibu/sites/edit.html.erb +9 -0
  40. data/app/views/sibu/sites/index.html.erb +37 -0
  41. data/app/views/sibu/sites/new.html.erb +9 -0
  42. data/app/views/sibu/sites/show.html.erb +1 -0
  43. data/app/views/sibu/sites/update.html.erb +2 -0
  44. data/config/initializers/shrine.rb +10 -0
  45. data/config/initializers/tag_helper.rb +75 -0
  46. data/config/routes.rb +17 -0
  47. data/db/migrate/20180124095041_create_sibu_sites.rb +12 -0
  48. data/db/migrate/20180124095213_create_sibu_pages.rb +15 -0
  49. data/db/migrate/20180124145030_create_sibu_site_templates.rb +10 -0
  50. data/db/migrate/20180125231638_add_user_id_to_sites.rb +5 -0
  51. data/db/migrate/20180126114522_rename_url_to_path_in_pages.rb +5 -0
  52. data/db/migrate/20180126114628_add_domain_to_sites.rb +5 -0
  53. data/db/migrate/20180127211533_create_sibu_images.rb +11 -0
  54. data/lib/sibu.rb +5 -0
  55. data/lib/sibu/engine.rb +7 -0
  56. data/lib/sibu/version.rb +3 -0
  57. data/lib/tasks/sibu_tasks.rake +4 -0
  58. metadata +185 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 94fb79f4ed5e7be7da2b75486ef62d4c49d5d480
4
+ data.tar.gz: 36ac40fe3388192c777786841dd34e48288bd932
5
+ SHA512:
6
+ metadata.gz: ff50420aa841d23e9b7eb846ded520e0fafee12e54561a2289872f991ebe0c4aaa6f9645f5b8a00120ca4477cd1223c4e1070582349111777d404c2cda2e0f56
7
+ data.tar.gz: 670a6deddbde376b06cecd419995e2e4864bef2cac6a3c95bb1e6d7ee93ceaa4424434140b401752d9847b5dd24fc4950f95f2be779d7eb43b1391fa668750da
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Jean-Baptiste Vilain
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,33 @@
1
+ # Sibu - A site builder engine for Ruby on Rails
2
+ This is an engine for Ruby on Rails that enables creation of static
3
+ websites in a simple & wysiwyg way.
4
+
5
+ ## Usage
6
+ How to use my plugin.
7
+
8
+ ## Installation
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'sibu'
13
+ ```
14
+
15
+ And then execute:
16
+ ```bash
17
+ $ bundle
18
+ ```
19
+
20
+ Or install it yourself as:
21
+ ```bash
22
+ $ gem install sibu
23
+ ```
24
+
25
+ ## Improvements
26
+ - Use a specific controller & helper for site display
27
+ - Move page templates to SiteTemplate model
28
+
29
+ ## Contributing
30
+ Contribution directions go here.
31
+
32
+ ## License
33
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Sibu'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'test'
31
+ t.pattern = 'test/**/*_test.rb'
32
+ t.verbose = false
33
+ end
34
+
35
+
36
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/sibu .js
2
+ //= link_directory ../stylesheets/sibu .css
@@ -0,0 +1,3 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require_self
@@ -0,0 +1,36 @@
1
+ sb-edit,
2
+ [class*='sb-'] {
3
+ position: relative;
4
+
5
+ &:hover > .sb-overlay {
6
+ cursor: pointer;
7
+ display: flex;
8
+ }
9
+ }
10
+
11
+ .sb-overlay {
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ z-index: 999;
16
+ width: 100%;
17
+ height: 100%;
18
+ display: none;
19
+ flex-wrap: wrap;
20
+ align-items: center;
21
+ justify-content: center;
22
+ text-align: center;
23
+
24
+ > * {
25
+ flex: 1 1 0%;
26
+ }
27
+ }
28
+
29
+ #edit_panel {
30
+ position: absolute;
31
+ left: 0;
32
+ bottom: 0;
33
+ width: 100%;
34
+ display: none;
35
+ z-index: 1000;
36
+ }
@@ -0,0 +1,6 @@
1
+ module Sibu
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ before_action Rails.application.config.sibu[:auth_filter]
5
+ end
6
+ end
@@ -0,0 +1,106 @@
1
+ require_dependency "sibu/application_controller"
2
+
3
+ module Sibu
4
+ class PagesController < ApplicationController
5
+ before_action :set_page, only: [:edit, :update, :destroy, :edit_element, :update_element, :edit_section]
6
+ before_action :set_site, only: [:index, :new]
7
+ before_action :set_edit_context, only: [:edit_element, :update_element]
8
+ skip_before_action Rails.application.config.sibu[:auth_filter], only: [:show]
9
+
10
+ def index
11
+ @pages = @site.pages.order(:created_at)
12
+ end
13
+
14
+ def show
15
+ if params[:site_id].blank?
16
+ @site = Sibu::Site.find_by_domain(request.domain)
17
+ if @site
18
+ @page = @site.page(params[:path])
19
+ view_template = @page ? 'show' : @site.not_found
20
+ else
21
+ view_template = Rails.application.config.sibu[:not_found]
22
+ end
23
+ else
24
+ @site = Sibu::Site.find(params[:site_id])
25
+ @page = Sibu::Page.find(params[:id])
26
+ view_template = 'show'
27
+ end
28
+
29
+ render view_template, layout: 'sibu/site'
30
+ end
31
+
32
+ def new
33
+ @page = Sibu::Page.new(site_id: @site.id)
34
+ end
35
+
36
+ def create
37
+ @page = Sibu::Page.new(page_params)
38
+ if @page.save
39
+ redirect_to site_pages_url(@page.site_id), "La page a bien été créée."
40
+ else
41
+ flash.now[:alert] = "Une erreur s'est produite lors de la création de la page."
42
+ render :new
43
+ end
44
+ end
45
+
46
+ def edit
47
+ end
48
+
49
+ def update
50
+ if @page.update(page_params)
51
+ redirect_to site_pages_url(@page.site_id), notice: "La page a bien été mise à jour."
52
+ else
53
+ flash.now[:alert] = "Une erreur s'est produite lors de l'enregistrement de la page."
54
+ render :edit
55
+ end
56
+ end
57
+
58
+ def destroy
59
+ end
60
+
61
+ def edit_content
62
+ @page = Sibu::Page.find(params[:page_id])
63
+ @site = @page.site if @page
64
+ render :edit_content, layout: 'sibu/edit_content'
65
+ end
66
+
67
+ def edit_element
68
+ end
69
+
70
+ def update_element
71
+ @updated = @entity.update_element(@section_id, @element_id, element_params)
72
+ end
73
+
74
+ def edit_section
75
+ end
76
+
77
+ def update_section
78
+ end
79
+
80
+ private
81
+
82
+ def set_page
83
+ @page = Sibu::Page.find(params[:id])
84
+ @site = @page.site if @page
85
+ end
86
+
87
+ def set_site
88
+ @site = Sibu::Site.find(params[:site_id])
89
+ end
90
+
91
+ def set_edit_context
92
+ @entity_type = params[:entity]
93
+ @section_id = params[:section_id]
94
+ @element_id = params[:element_id]
95
+ @entity = @entity_type == 'site' ? @site : @page
96
+ end
97
+
98
+ def page_params
99
+ params.require(:page).permit!
100
+ end
101
+
102
+ def element_params
103
+ params.require(:element).permit!
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,59 @@
1
+ require_dependency "sibu/application_controller"
2
+
3
+ module Sibu
4
+ class SitesController < ApplicationController
5
+ before_action :set_site, only: [:show, :edit, :update, :destroy]
6
+ skip_before_action Rails.application.config.sibu[:auth_filter], only: [:show]
7
+
8
+ def index
9
+ @sites = Sibu::Site.where(user_id: send(Rails.application.config.sibu[:current_user]).id)
10
+ end
11
+
12
+ def show
13
+ @page = @site.page('')
14
+ redirect_to site_page_path(@site.id, @page.id)
15
+ end
16
+
17
+ def new
18
+ @site = Sibu::Site.new(user_id: send(Rails.application.config.sibu[:current_user]).id)
19
+ end
20
+
21
+ def create
22
+ @site = Sibu::Site.new(site_params)
23
+ @site.init_data(:default)
24
+ if @site.save
25
+ redirect_to sites_url, notice: "Le site a bien été créé."
26
+ else
27
+ flash.now[:alert] = "Une erreur s'est produite lors de la création du site."
28
+ render :new
29
+ end
30
+ end
31
+
32
+ def edit
33
+ end
34
+
35
+ def update
36
+ if @site.update(site_params)
37
+ redirect_to sites_url, notice: "Le site a bien été mis à jour."
38
+ else
39
+ flash.now[:alert] = "Une erreur s'est produite lors de l'enregistrement du site."
40
+ render :edit
41
+ end
42
+ end
43
+
44
+ def destroy
45
+ @site.destroy
46
+ redirect_to sites_url, notice: "Le site a bien été supprimé."
47
+ end
48
+
49
+ private
50
+
51
+ def set_site
52
+ @site = Sibu::Site.find(params[:id])
53
+ end
54
+
55
+ def site_params
56
+ params.require(:site).permit!
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module Sibu
2
+ module ApplicationHelper
3
+ def conf
4
+ Rails.application.config.sibu
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module Sibu
2
+ module PagesHelper
3
+ def link_path(page_id)
4
+ p = @site.page_by_id(page_id)
5
+ p ? (@site.domain.blank? ? site_page_path(@site.id, p.id) : "/#{p.path}") : "#"
6
+ end
7
+
8
+ def page_templates
9
+ [['Accueil', 'home'], ['Offre', 'offer'], ['Galerie', 'gallery'], ['Destination', 'destination']]
10
+ end
11
+
12
+ def page_languages
13
+ [['Français', 'fr'], ['Anglais', 'en']]
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module Sibu
2
+ module SitesHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Sibu
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Sibu
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ class ImageUploader < Shrine
2
+ # plugins and uploading logic
3
+ end
@@ -0,0 +1,53 @@
1
+ module Sibu
2
+ module SectionsConcern
3
+ include ActiveSupport::Concern
4
+
5
+ def section(*ids)
6
+ if ids.length == 1
7
+ s = nil
8
+ if sections.blank?
9
+ self.sections = {}
10
+ else
11
+ s = sections[ids[0]]
12
+ end
13
+ if s.nil?
14
+ s = []
15
+ self.sections[ids[0]] = s
16
+ save
17
+ end
18
+ s
19
+ elsif ids.length == 2
20
+ s = section(ids[0])
21
+ sub = s.select {|elt| elt["id"] == ids[1]}
22
+ unless sub
23
+ sub = {"id" => ids[1], "elements" => []}
24
+ self.sections[ids[0]] << sub
25
+ save
26
+ end
27
+ sub
28
+ end
29
+ end
30
+
31
+ def element(section_id, element_id)
32
+ elt = section(section_id).select {|e| e["id"] == element_id}.first
33
+ elt || {}
34
+ end
35
+
36
+ def update_section(*ids, value)
37
+ end
38
+
39
+ # Note : only 2 levels supported for now
40
+ def update_element(*ids, value)
41
+ updated = nil
42
+ if ids.length > 1
43
+ if self.sections[ids[0]].any? {|elt| elt["id"] == ids[1]}
44
+ self.sections[ids[0]].map! {|elt| elt["id"] == ids[1] ? elt.value : elt}
45
+ else
46
+ self.sections[ids[0]] << {"id" => ids[1]}.merge(value)
47
+ end
48
+ updated = value if save
49
+ end
50
+ updated
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module Sibu
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Sibu
2
+ class Image < ApplicationRecord
3
+ include ImageUploader::Attachment.new(:file)
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module Sibu
2
+ class Page < ApplicationRecord
3
+ include Sibu::SectionsConcern
4
+
5
+ belongs_to :site, :class_name => 'Sibu::Site'
6
+
7
+ store :metadata, accessors: [:title, :description], coder: JSON
8
+
9
+ validates_presence_of :name, :site, :language, :template
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ module Sibu
2
+ class Site < ApplicationRecord
3
+ include Sibu::SectionsConcern
4
+
5
+ belongs_to :site_template, :class_name => 'Sibu::SiteTemplate'
6
+ has_many :pages, :class_name => 'Sibu::Page', dependent: :destroy
7
+
8
+ validates_presence_of :name, :site_template
9
+
10
+ def page_template(page)
11
+ "#{site_template.path}/#{page.template}"
12
+ end
13
+
14
+ def not_found
15
+ "#{site_template.path}/not_found"
16
+ end
17
+
18
+ def page(path)
19
+ pages.where(path: path).first
20
+ end
21
+
22
+ def page_by_id(page_id)
23
+ pages.where(id: page_id).first
24
+ end
25
+
26
+ def init_data(source)
27
+ site_data = Rails.application.config.sibu[:site_data][source]
28
+ self.sections = site_data.sections
29
+ site_data.pages.each do |p|
30
+ self.pages << Sibu::Page.new(p)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ module Sibu
2
+ class SiteTemplate < ApplicationRecord
3
+ end
4
+ end
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html class="sibu">
3
+ <head>
4
+ <title><%= conf[:title] %></title>
5
+ <%= stylesheet_link_tag conf[:stylesheet], media: 'all' %>
6
+ <%= javascript_include_tag conf[:javascript] %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+ <% [:top_panel, :side_panel, :content_panel, :bottom_panel].each do |panel| %>
11
+ <% unless conf[panel].blank? %>
12
+ <div class="sibu_panel">
13
+ <%= render conf[panel] %>
14
+ </div>
15
+ <% end %>
16
+ <% end %>
17
+ </body>
18
+ </html>
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= conf[:title] %></title>
5
+ <%= stylesheet_link_tag conf[:stylesheet], media: 'all' %>
6
+ <%= javascript_include_tag conf[:javascript] %>
7
+ <%= stylesheet_link_tag 'sibu/sibu', media: 'all' %>
8
+ <%= javascript_include_tag 'sibu/sibu' %>
9
+ <% if @site %>
10
+ <%= stylesheet_link_tag @site.site_template.path, media: "all" %>
11
+ <%= javascript_include_tag @site.site_template.path %>
12
+ <% end %>
13
+ <%= csrf_meta_tags %>
14
+ </head>
15
+ <body>
16
+ <% [:top_panel, :side_panel, :content_panel, :bottom_panel].each do |panel| %>
17
+ <% unless conf[panel].blank? %>
18
+ <div class="<%= 'sibu_panel' unless panel == :content_panel %>">
19
+ <%= render conf[panel] %>
20
+ </div>
21
+ <% end %>
22
+ <% end %>
23
+ <div id="edit_panel" class="sibu_view"></div>
24
+
25
+ <script>
26
+ $(function() {
27
+ initOverlays();
28
+ });
29
+
30
+ function initOverlays() {
31
+ var elts = $("[class*='sb-']");
32
+ elts.each(function() {
33
+ var elt = $(this);
34
+ elt.find(".sb-overlay").remove();
35
+ var section = elt.parents("sb-edit").first();
36
+ var eltId = elt.data("id"), sectionId = section.data("id"), entity = section.data("entity");
37
+ elt.append(
38
+ '<div class="sb-overlay sibu_panel">' +
39
+ '<a href="<%= edit_element_site_page_path(@site.id, @page.id) %>?element_id=' + eltId + '&section_id=' + sectionId +
40
+ '&entity=' + entity + '" data-remote="true">Modifier</a>' +
41
+ '</div>'
42
+ );
43
+ });
44
+
45
+ }
46
+ </script>
47
+ <%= yield :scripts %>
48
+ </body>
49
+ </html>
@@ -0,0 +1,21 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= @page ? @page.title : 'Page inconnue' %></title>
5
+ <meta charset="UTF-8">
6
+ <meta name="description" content="<%= @page.description if @page %>">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+
9
+ <% if @site %>
10
+ <%= stylesheet_link_tag @site.site_template.path, media: "all" %>
11
+ <%= javascript_include_tag @site.site_template.path %>
12
+ <% end %>
13
+ <%= csrf_meta_tags %>
14
+ </head>
15
+ <body>
16
+
17
+ <%= yield %>
18
+
19
+ <%= yield :scripts %>
20
+ </body>
21
+ </html>
@@ -0,0 +1,19 @@
1
+ <h2>Modifier l'élément</h2>
2
+ <div id="edit_msg"></div>
3
+ <div class="sibu_form">
4
+ <%= form_tag(update_element_site_page_path(@site.id, @page.id), method: :patch, remote: true) do |f| %>
5
+ <div class="sibu_field">
6
+ <%= label_tag 'element[text]', 'Texte' %>
7
+ <%= text_area_tag 'element[text]' %>
8
+ </div>
9
+ <%= hidden_field_tag :section_id, @section_id %>
10
+ <%= hidden_field_tag :element_id, @element_id %>
11
+ <%= hidden_field_tag :entity, @entity_type %>
12
+ <div class="sibu_actions">
13
+ <%= submit_tag 'Valider' %>
14
+ <%= link_to 'Annuler', '#', onclick: '$("#edit_panel").slideUp("fast"); return false;' %>
15
+ </div>
16
+ <% end %>
17
+ </div>
18
+
19
+
@@ -0,0 +1,31 @@
1
+ <%= form_for([@site, @page]) do |f| %>
2
+ <div class="sibu_field">
3
+ <%= f.label :name, 'Nom de la page' %>
4
+ <%= f.text_field :name, placeholder: "Ex : Accueil, contact..." %>
5
+ </div>
6
+ <div class="sibu_field">
7
+ <%= f.label :template, 'Modèle' %>
8
+ <%= f.select(:template, page_templates, {prompt: 'Sélectionnez un modèle de page'}) %>
9
+ </div>
10
+ <div class="sibu_field">
11
+ <%= f.label :path, "Chemin d'accès" %>
12
+ <%= f.text_field :path, placeholder: "Adresse de la page" %>
13
+ </div>
14
+ <div class="sibu_field">
15
+ <%= f.label :language, "Langue" %>
16
+ <%= f.select(:language, page_languages, {prompt: 'Sélectionnez une langue'}) %>
17
+ </div>
18
+ <div class="sibu_field">
19
+ <%= f.label :title, 'Titre' %>
20
+ <%= f.text_field :title, placeholder: "Titre de la page" %>
21
+ </div>
22
+ <div class="sibu_field">
23
+ <%= f.label :description, 'Description' %>
24
+ <%= f.text_area :description, placeholder: "Description de la page" %>
25
+ </div>
26
+ <%= f.hidden_field :site_id %>
27
+ <div class="sibu_actions">
28
+ <%= f.submit 'Valider' %>
29
+ <%= link_to 'Annuler', :back %>
30
+ </div>
31
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <h1>Pages#destroy</h1>
2
+ <p>Find me in app/views/sibu/pages/destroy.html.erb</p>
@@ -0,0 +1,9 @@
1
+ <div class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Retour', :back %>
4
+ </div>
5
+ <h2>Modifier une page</h2>
6
+ <div class="sibu_form">
7
+ <%= render 'form' %>
8
+ </div>
9
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="edit_content">
2
+ <%= render "shared/#{@site.site_template.path}/site" %>
3
+ </div>
@@ -0,0 +1,4 @@
1
+ var editPanel = $("#edit_panel");
2
+ editPanel.html("<%= j(render 'edit_panel') %>");
3
+ editPanel.find("#element").val("<%= @entity.element(@section_id, @element_id)["text"] %>");
4
+ editPanel.slideDown("fast");
@@ -0,0 +1,39 @@
1
+ <div id="pages" class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Créer une page', new_site_page_path(@site.id) %> | <%= link_to 'Retour', :back %>
4
+ </div>
5
+ <h2>Pages du site "<%= @site.name %>"</h2>
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>Nom</th>
10
+ <th>Modèle</th>
11
+ <th>Chemin d'accès</th>
12
+ <th>Mise à jour</th>
13
+ <th></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <% @pages.each do |p| %>
18
+ <tr>
19
+ <td><%= p.name %></td>
20
+ <td><%= p.template %></td>
21
+ <td><%= p.path %></td>
22
+ <td><%= l p.updated_at %></td>
23
+ <td>
24
+ <%= link_to 'Voir', site_page_path(@site.id, p), target: '_blank' %> |
25
+ <%= link_to 'Editer', site_page_edit_content_path(site_id: @site.id, page_id: p.id) %> |
26
+ <%= link_to 'Modifier', edit_site_page_path(@site.id, p) %> |
27
+ <%= link_to 'Supprimer', site_page_path(@site.id, p), method: :delete, data: {confirm: "Supprimer la page \"#{p.name}\" ?"} %>
28
+ </td>
29
+ </tr>
30
+ <% end %>
31
+ <% if @pages.empty? %>
32
+ <tr>
33
+ <td colspan="4">Aucune page créée pour le moment.</td>
34
+ </tr>
35
+ <% end %>
36
+ </tbody>
37
+ </table>
38
+ </div>
39
+
@@ -0,0 +1,9 @@
1
+ <div class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Retour', :back %>
4
+ </div>
5
+ <h2>Créer une page</h2>
6
+ <div class="sibu_form">
7
+ <%= render 'form' %>
8
+ </div>
9
+ </div>
@@ -0,0 +1 @@
1
+ <%= render "shared/#{@site.site_template.path}/site" %>
@@ -0,0 +1,2 @@
1
+ <h1>Pages#update</h1>
2
+ <p>Find me in app/views/sibu/pages/update.html.erb</p>
@@ -0,0 +1,7 @@
1
+ <% if @updated.nil? %>
2
+ $("#edit_panel #edit_msg").html("<p class='sibu_alert'>Une erreur s'est produite lors de l'enregistrement.</p>");
3
+ <% else %>
4
+ $("#edit_panel").slideUp();
5
+ $("sb-edit[data-id='<%= @section_id %>']").find("[data-id='<%= @element_id %>']").text("<%= @updated["text"] %>");
6
+ initOverlays();
7
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <%= form_for @site do |f| %>
2
+ <div class="sibu_field">
3
+ <%= f.label :name, 'Nom du site' %>
4
+ <%= f.text_field :name, placeholder: "Ex : Site de l'Hôtel du Lac" %>
5
+ </div>
6
+ <div class="sibu_field">
7
+ <%= f.label :site_template_id, 'Modèle' %>
8
+ <%= f.collection_select(:site_template_id, Sibu::SiteTemplate.all, :id, :name, {prompt: 'Sélectionnez un modèle de site'}) %>
9
+ </div>
10
+ <%= f.hidden_field :user_id %>
11
+ <div class="sibu_actions">
12
+ <%= f.submit 'Valider' %>
13
+ <%= link_to 'Annuler', :back %>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <h1>Sites#destroy</h1>
2
+ <p>Find me in app/views/sibu/sites/destroy.html.erb</p>
@@ -0,0 +1,9 @@
1
+ <div class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Retour', :back %>
4
+ </div>
5
+ <h2>Modifier un site</h2>
6
+ <div class="sibu_form">
7
+ <%= render 'form' %>
8
+ </div>
9
+ </div>
@@ -0,0 +1,37 @@
1
+ <div class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Créer un site', new_site_path %>
4
+ </div>
5
+ <h2>Liste des sites</h2>
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>Nom</th>
10
+ <th>Modèle</th>
11
+ <th>Mise à jour</th>
12
+ <th></th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% @sites.each do |s| %>
17
+ <tr>
18
+ <td><%= s.name %></td>
19
+ <td><%= s.site_template.name if s.site_template %></td>
20
+ <td><%= l s.updated_at %></td>
21
+ <td>
22
+ <%= link_to 'Voir', site_path(s), target: '_blank' %> |
23
+ <%= link_to 'Pages', site_pages_path(s) %> |
24
+ <%= link_to 'Modifier', edit_site_path(s) %> |
25
+ <%= link_to 'Supprimer', site_path(s), method: :delete, data: {confirm: "Supprimer le site \"#{s.name}\" ?"} %>
26
+ </td>
27
+ </tr>
28
+ <% end %>
29
+ <% if @sites.empty? %>
30
+ <tr>
31
+ <td colspan="4">Aucun site créé pour le moment.</td>
32
+ </tr>
33
+ <% end %>
34
+ </tbody>
35
+ </table>
36
+ </div>
37
+
@@ -0,0 +1,9 @@
1
+ <div class="sibu_view">
2
+ <div class="actions">
3
+ <%= link_to 'Retour', :back %>
4
+ </div>
5
+ <h2>Créer un site</h2>
6
+ <div class="sibu_form">
7
+ <%= render 'form' %>
8
+ </div>
9
+ </div>
@@ -0,0 +1 @@
1
+ <%= render "shared/#{@site.site_template.path}/site" %>
@@ -0,0 +1,2 @@
1
+ <h1>Sites#update</h1>
2
+ <p>Find me in app/views/sibu/sites/update.html.erb</p>
@@ -0,0 +1,10 @@
1
+ require "shrine"
2
+ require "shrine/storage/file_system"
3
+
4
+ Shrine.storages = {
5
+ cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
6
+ store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"), # permanent
7
+ }
8
+
9
+ Shrine.plugin :activerecord
10
+ Shrine.plugin :cached_attachment_data
@@ -0,0 +1,75 @@
1
+ module ActionView
2
+ module Helpers
3
+ module TagHelper
4
+ # Todo : handle default values => sections can be totally empty or have at least 1 elt
5
+ # If "emptyable", how do we add the 1st elt ? If not, how do we provide a default value ?
6
+ class SectionHelper
7
+ include ActionView::Helpers::TagHelper
8
+
9
+ attr_reader :entity_type
10
+
11
+ [:h1, :h2, :h3, :h4, :h5, :h6, :p, :span, :div].each do |t|
12
+ define_method(t) do |id, html_opts = {}|
13
+ html_opts.merge!({class: "sb-#{t} #{html_opts[:class]}", data: {id: id}}) if @edit
14
+ content_tag(t, (@elements.dig(id, "text") || "Texte à modifier"), html_opts)
15
+ end
16
+ end
17
+
18
+ def initialize(*ids, entity, edit_mode)
19
+ @id = ids.join('|')
20
+ @entity_type = entity.is_a?(Sibu::Page) ? 'page' : 'site'
21
+ elts = entity.section(*ids)
22
+ @elements = elts.blank? ? {"default" => {}} : Hash[elts.map {|e| [e["id"], e.except("id")]}]
23
+ @edit = edit_mode
24
+ end
25
+
26
+ # Note : add sb-img back - see how the extra div could be removed
27
+ def img(id, html_opts = {})
28
+ content = id == "default" ? {"src" => "/default.jpg"} : (@elements[id] || {"src" => "/default.jpg"})
29
+ if @edit
30
+ content_tag(:div, content_tag(:img, nil, content.merge(html_opts)), {class: "rel h100 #{html_opts[:class]}", data: {id: id}})
31
+ else
32
+ content_tag(:img, nil, content.merge(html_opts))
33
+ end
34
+ end
35
+
36
+ def lnk(id)
37
+ @elements[id] || {"href" => "#", "text" => "Nouveau lien"}
38
+ end
39
+
40
+ # def subsection(id, &block)
41
+ # section
42
+ # s = SectionHelper.new(id, @entity_type, @elements[id], @edit)
43
+ # if !@edit
44
+ # capture(s, &block)
45
+ # else
46
+ # "<sb-edit data-id='#{id}' data-entity='#{@entity_type}'>#{capture(s, &block)}</sb-edit>".html_safe
47
+ # end
48
+ # end
49
+
50
+ def elements(&block)
51
+ @elements.each_pair(&block)
52
+ end
53
+ end
54
+
55
+ def section(id, entity = @page, &block)
56
+ s = SectionHelper.new(id, entity, action_name != 'show')
57
+ if action_name == 'show'
58
+ capture(s, &block)
59
+ else
60
+ "<sb-edit data-id='#{id}' data-entity='#{s.entity_type}'>#{capture(s, &block)}</sb-edit>".html_safe
61
+ end
62
+ end
63
+
64
+ def subsection(id, sub_id, entity = @page, &block)
65
+ entity_type = entity.is_a?(Sibu::Page) ? 'page' : 'site'
66
+ s = SectionHelper.new(id, sub_id, entity, action_name != 'show')
67
+ # if action_name == 'show'
68
+ capture(s, &block)
69
+ # else
70
+ # "<sb-edit data-id='#{id}' data-entity='#{s.entity_type}'>#{capture(s, &block)}</sb-edit>".html_safe
71
+ # end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,17 @@
1
+ Sibu::Engine.routes.draw do
2
+
3
+ get '/', to: 'pages#show', constraints: lambda {|req| req.domain != Rails.application.config.sibu[:domain]}
4
+ get '*path', to: 'pages#show', constraints: lambda {|req| req.domain != Rails.application.config.sibu[:domain]}
5
+
6
+ scope path_names: {new: 'creer', edit: 'modifier'} do
7
+ resources :sites do
8
+ resources :pages do
9
+ get :edit_content, to: 'pages#edit_content', path: 'editer'
10
+ get :edit_element, on: :member
11
+ get :edit_section, on: :member
12
+ patch 'update_element', on: :member
13
+ patch 'update_section', on: :member
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSibuSites < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :sibu_sites do |t|
4
+ t.string :name
5
+ t.integer :site_template_id
6
+ t.text :metadata
7
+ t.jsonb :sections
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSibuPages < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :sibu_pages do |t|
4
+ t.string :name
5
+ t.integer :site_id
6
+ t.text :metadata
7
+ t.string :language
8
+ t.string :url
9
+ t.string :template
10
+ t.jsonb :sections
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ class CreateSibuSiteTemplates < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :sibu_site_templates do |t|
4
+ t.string :name
5
+ t.string :path
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class AddUserIdToSites < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :sibu_sites, :user_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RenameUrlToPathInPages < ActiveRecord::Migration[5.1]
2
+ def change
3
+ rename_column :sibu_pages, :url, :path
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddDomainToSites < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :sibu_sites, :domain, :string
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateSibuImages < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :sibu_images do |t|
4
+ t.integer :user_id
5
+ t.text :metadata
6
+ t.text :data
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ require "sibu/engine"
2
+
3
+ module Sibu
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'tinymce-rails'
2
+
3
+ module Sibu
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Sibu
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Sibu
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :sibu do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sibu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jean-Baptiste Vilain
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: shrine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.8'
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: tinymce-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tinymce-rails-langs
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'
97
+ description: Sibu is an engine for Ruby on Rails that enables creation of static websites
98
+ in a simple & wysiwyg way.
99
+ email:
100
+ - jbvilain@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - MIT-LICENSE
106
+ - README.md
107
+ - Rakefile
108
+ - app/assets/config/sibu_manifest.js
109
+ - app/assets/javascripts/sibu/sibu.js.erb
110
+ - app/assets/stylesheets/sibu/sibu.scss.erb
111
+ - app/controllers/sibu/application_controller.rb
112
+ - app/controllers/sibu/pages_controller.rb
113
+ - app/controllers/sibu/sites_controller.rb
114
+ - app/helpers/sibu/application_helper.rb
115
+ - app/helpers/sibu/pages_helper.rb
116
+ - app/helpers/sibu/sites_helper.rb
117
+ - app/jobs/sibu/application_job.rb
118
+ - app/mailers/sibu/application_mailer.rb
119
+ - app/models/concerns/sibu/image_uploader.rb
120
+ - app/models/concerns/sibu/sections_concern.rb
121
+ - app/models/sibu/application_record.rb
122
+ - app/models/sibu/image.rb
123
+ - app/models/sibu/page.rb
124
+ - app/models/sibu/site.rb
125
+ - app/models/sibu/site_template.rb
126
+ - app/views/layouts/sibu/application.html.erb
127
+ - app/views/layouts/sibu/edit_content.html.erb
128
+ - app/views/layouts/sibu/site.html.erb
129
+ - app/views/sibu/pages/_edit_panel.html.erb
130
+ - app/views/sibu/pages/_form.html.erb
131
+ - app/views/sibu/pages/destroy.html.erb
132
+ - app/views/sibu/pages/edit.html.erb
133
+ - app/views/sibu/pages/edit_content.html.erb
134
+ - app/views/sibu/pages/edit_element.js.erb
135
+ - app/views/sibu/pages/index.html.erb
136
+ - app/views/sibu/pages/new.html.erb
137
+ - app/views/sibu/pages/show.html.erb
138
+ - app/views/sibu/pages/update.html.erb
139
+ - app/views/sibu/pages/update_element.js.erb
140
+ - app/views/sibu/sites/_form.html.erb
141
+ - app/views/sibu/sites/destroy.html.erb
142
+ - app/views/sibu/sites/edit.html.erb
143
+ - app/views/sibu/sites/index.html.erb
144
+ - app/views/sibu/sites/new.html.erb
145
+ - app/views/sibu/sites/show.html.erb
146
+ - app/views/sibu/sites/update.html.erb
147
+ - config/initializers/shrine.rb
148
+ - config/initializers/tag_helper.rb
149
+ - config/routes.rb
150
+ - db/migrate/20180124095041_create_sibu_sites.rb
151
+ - db/migrate/20180124095213_create_sibu_pages.rb
152
+ - db/migrate/20180124145030_create_sibu_site_templates.rb
153
+ - db/migrate/20180125231638_add_user_id_to_sites.rb
154
+ - db/migrate/20180126114522_rename_url_to_path_in_pages.rb
155
+ - db/migrate/20180126114628_add_domain_to_sites.rb
156
+ - db/migrate/20180127211533_create_sibu_images.rb
157
+ - lib/sibu.rb
158
+ - lib/sibu/engine.rb
159
+ - lib/sibu/version.rb
160
+ - lib/tasks/sibu_tasks.rake
161
+ homepage: http://hotentic.com
162
+ licenses:
163
+ - MIT
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.6.13
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Sibu - A Site Builder for Ruby on Rails
185
+ test_files: []