dorsale 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/dorsale/application.js +0 -12
- data/app/assets/javascripts/dorsale/tabs_loader.coffee +7 -0
- data/app/assets/stylesheets/dorsale/all.sass +11 -0
- data/app/assets/stylesheets/dorsale/contexts.sass +44 -0
- data/app/assets/stylesheets/dorsale/filters.sass +3 -0
- data/app/assets/stylesheets/dorsale/forms.sass +15 -0
- data/app/assets/stylesheets/dorsale/styles.sass +16 -0
- data/app/assets/stylesheets/dorsale/tables.sass +17 -0
- data/app/controllers/dorsale/small_data/filters_controller.rb +25 -0
- data/app/helpers/dorsale/comments_helper.rb +1 -1
- data/app/helpers/dorsale/context_helper.rb +37 -0
- data/app/helpers/dorsale/form_helper.rb +26 -0
- data/app/helpers/dorsale/text_helper.rb +15 -0
- data/app/models/dorsale/comment.rb +0 -1
- data/app/models/dorsale/small_data/filter.rb +50 -0
- data/app/models/dorsale/small_data/filter_strategy.rb +27 -0
- data/app/views/dorsale/_actions.html.slim +22 -0
- data/app/views/dorsale/_contextual.html.slim +5 -0
- data/config/routes.rb +4 -0
- data/lib/dorsale/engine.rb +17 -0
- data/lib/dorsale/polymorphic_id.rb +38 -0
- data/lib/dorsale/simple_form.rb +166 -0
- data/lib/dorsale/simple_form_bootstrap.rb +136 -0
- data/lib/dorsale/version.rb +1 -1
- data/spec/dummy/log/test.log +2198 -0
- data/spec/routing/dorsale/small_data_routing_spec.rb +15 -0
- data/spec/spec_helper.rb +5 -0
- metadata +153 -24
- data/app/assets/javascripts/dorsale/addresses.js +0 -2
- data/app/assets/stylesheets/dorsale/addresses.css +0 -4
- data/app/assets/stylesheets/dorsale/application.css +0 -13
@@ -1,13 +1 @@
|
|
1
|
-
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
-
// listed below.
|
3
|
-
//
|
4
|
-
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
-
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
-
//
|
7
|
-
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
-
// compiled file.
|
9
|
-
//
|
10
|
-
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
-
// about supported directives.
|
12
|
-
//
|
13
1
|
//= require_tree .
|
@@ -0,0 +1,11 @@
|
|
1
|
+
@import bootstrap
|
2
|
+
@import bootstrap-sprockets
|
3
|
+
@import font-awesome
|
4
|
+
@import font-awesome-sprockets
|
5
|
+
|
6
|
+
@import dorsale/comments
|
7
|
+
@import dorsale/tables
|
8
|
+
@import dorsale/contexts
|
9
|
+
@import dorsale/forms
|
10
|
+
@import dorsale/styles
|
11
|
+
@import dorsale/filters
|
@@ -0,0 +1,44 @@
|
|
1
|
+
.context
|
2
|
+
@extend .well
|
3
|
+
text-align: center
|
4
|
+
position: relative
|
5
|
+
margin-bottom: 15px !important
|
6
|
+
|
7
|
+
.fa
|
8
|
+
@extend .fa-fw
|
9
|
+
|
10
|
+
> .fa
|
11
|
+
font-size: 400%
|
12
|
+
color: black
|
13
|
+
padding: 10px
|
14
|
+
margin: auto
|
15
|
+
display: block
|
16
|
+
|
17
|
+
strong, h2
|
18
|
+
@extend .text-muted
|
19
|
+
|
20
|
+
h2
|
21
|
+
margin: 10px
|
22
|
+
font-size: 150%
|
23
|
+
font-weight: bold
|
24
|
+
|
25
|
+
p.infos
|
26
|
+
margin: 5px
|
27
|
+
text-align: left
|
28
|
+
|
29
|
+
strong
|
30
|
+
display: inline-block
|
31
|
+
width: 50%
|
32
|
+
|
33
|
+
.btn-group
|
34
|
+
position: absolute
|
35
|
+
top: 0
|
36
|
+
right: 0
|
37
|
+
|
38
|
+
.btn
|
39
|
+
border-top: 0
|
40
|
+
border-right: 0
|
41
|
+
border-radius: 0 0 0 3px
|
42
|
+
|
43
|
+
img
|
44
|
+
max-width: 100%
|
@@ -0,0 +1,17 @@
|
|
1
|
+
table.default
|
2
|
+
@extend .table
|
3
|
+
@extend .table-striped
|
4
|
+
@extend .table-bordered
|
5
|
+
@extend .table-hover
|
6
|
+
|
7
|
+
th
|
8
|
+
text-align: center
|
9
|
+
vertical-align: middle !important
|
10
|
+
|
11
|
+
td[class*="date"]
|
12
|
+
width: 8em
|
13
|
+
text-align: center
|
14
|
+
|
15
|
+
td[class*="count"]
|
16
|
+
width: 1em
|
17
|
+
text-align: center
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module SmallData
|
3
|
+
class FiltersController < ApplicationController
|
4
|
+
|
5
|
+
def create
|
6
|
+
filters = params[:filters] || {}
|
7
|
+
|
8
|
+
filters.each do |key, value|
|
9
|
+
filters[key] = "" if value == "0"
|
10
|
+
end
|
11
|
+
|
12
|
+
Filter.new(cookies).store(filters)
|
13
|
+
|
14
|
+
urls = [
|
15
|
+
params[:back_url],
|
16
|
+
request.referer,
|
17
|
+
(main_app.root_path rescue nil)
|
18
|
+
]
|
19
|
+
|
20
|
+
redirect_to urls.select(&:present?).first
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module ContextHelper
|
3
|
+
def context_icon(id)
|
4
|
+
icon(id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def context_title(title)
|
8
|
+
content_tag(:h2){ title }
|
9
|
+
end
|
10
|
+
|
11
|
+
def context_info(name, info)
|
12
|
+
return if info.blank?
|
13
|
+
%(<p class="infos"><strong>#{name} : </strong>#{info}</p>).html_safe
|
14
|
+
end
|
15
|
+
|
16
|
+
def actions_for(obj, opts={})
|
17
|
+
url = opts[:url]
|
18
|
+
edit_url = opts[:edit_url]
|
19
|
+
delete_url = opts[:delete_url]
|
20
|
+
|
21
|
+
url = polymorphic_path(obj) if url.nil?
|
22
|
+
edit_url = url + "/edit" if edit_url.nil?
|
23
|
+
delete_url = url if delete_url.nil?
|
24
|
+
|
25
|
+
render partial: "dorsale/actions", locals: {
|
26
|
+
:obj => obj,
|
27
|
+
:url => url,
|
28
|
+
:edit_url => edit_url,
|
29
|
+
:delete_url => delete_url,
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def render_contextual
|
34
|
+
render "dorsale/contextual"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module FormHelper
|
3
|
+
def form_buttons(opts = {})
|
4
|
+
back_url = opts[:back_url]
|
5
|
+
back_url = url_for(:back).html_safe if back_url.nil?
|
6
|
+
|
7
|
+
content_tag("div", class: "actions cdiv") do
|
8
|
+
submit = tag("input", type: "submit", class: "btn btn-success btn-sm", value: "Valider", id: "submit")
|
9
|
+
cancel = content_tag("a", href: back_url, class: "btn btn-primary btn-sm"){ "Annuler" }
|
10
|
+
cancel = "" if back_url == false
|
11
|
+
submit + cancel
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def horizontal_form_for(obj, opts={}, &block)
|
16
|
+
opts = {
|
17
|
+
:wrapper => "horizontal_form",
|
18
|
+
:html => {
|
19
|
+
:class => "form-horizontal"
|
20
|
+
}
|
21
|
+
}.deep_merge(opts)
|
22
|
+
|
23
|
+
simple_form_for(obj, opts, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module TextHelper
|
3
|
+
def euros(n)
|
4
|
+
number_to_currency(n)
|
5
|
+
end
|
6
|
+
|
7
|
+
def percentage(n)
|
8
|
+
number_to_percentage(n, precision: 2, format: "%n %")
|
9
|
+
end
|
10
|
+
|
11
|
+
def text2html(str)
|
12
|
+
h(str).gsub("\r", "").gsub("\n", "<br />").html_safe
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module SmallData
|
3
|
+
class Filter
|
4
|
+
|
5
|
+
def initialize(jar)
|
6
|
+
@jar = jar
|
7
|
+
end
|
8
|
+
|
9
|
+
def store(filters)
|
10
|
+
@jar['filters'] = filters.to_json
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
if @jar['filters']
|
15
|
+
begin
|
16
|
+
JSON.parse @jar['filters']
|
17
|
+
rescue JSON::ParserError
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
else
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(key)
|
26
|
+
read[key.to_s]
|
27
|
+
end
|
28
|
+
|
29
|
+
def set(key, value)
|
30
|
+
array = read
|
31
|
+
array[key.to_s] = value
|
32
|
+
store(array)
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply(query)
|
36
|
+
read.each do |key, value|
|
37
|
+
filter = strategy(key)
|
38
|
+
|
39
|
+
if filter && filter.applies?(self.target)
|
40
|
+
filter.set(key, value)
|
41
|
+
query = filter.apply(query)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return query
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module SmallData
|
3
|
+
class FilterStrategy
|
4
|
+
def initialize(target)
|
5
|
+
@target = target
|
6
|
+
end
|
7
|
+
|
8
|
+
def set(key, value)
|
9
|
+
@key = key
|
10
|
+
@value = value
|
11
|
+
return self
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(query)
|
15
|
+
if @value and @value != ''
|
16
|
+
do_apply(query)
|
17
|
+
else
|
18
|
+
query
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def applies?(target)
|
23
|
+
@target == target
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.btn-group
|
2
|
+
button.btn.btn-default.btn-sm.dropdown-toggle.actions data-toggle="dropdown"
|
3
|
+
= "Actions "
|
4
|
+
= icon :"caret-down"
|
5
|
+
ul.dropdown-menu
|
6
|
+
- if url && url != request.path_info
|
7
|
+
li
|
8
|
+
a.link_edit href=url
|
9
|
+
= icon :"file-o"
|
10
|
+
= " Afficher"
|
11
|
+
|
12
|
+
- if edit_url && edit_url != request.path_info
|
13
|
+
li
|
14
|
+
a.link_edit href=edit_url
|
15
|
+
= icon :pencil
|
16
|
+
= " Editer"
|
17
|
+
|
18
|
+
- if delete_url
|
19
|
+
li
|
20
|
+
a.link_delete href=delete_url data-method="delete" data-confirm="Confirmer ?"
|
21
|
+
= icon :trash
|
22
|
+
= " Supprimer"
|
data/config/routes.rb
CHANGED
data/lib/dorsale/engine.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
require "slim-rails"
|
2
|
+
require "sass-rails"
|
3
|
+
require "bootstrap-sass"
|
4
|
+
require "font-awesome-sass"
|
5
|
+
require "simple_form"
|
6
|
+
require "coffee-rails"
|
7
|
+
require "jquery-rails"
|
8
|
+
require "kaminari"
|
9
|
+
require "turbolinks"
|
10
|
+
require "bootstrap-kaminari-views"
|
11
|
+
require "bh"
|
12
|
+
require "rails-i18n"
|
13
|
+
require "cancan"
|
14
|
+
|
15
|
+
require "dorsale/simple_form"
|
16
|
+
require "dorsale/simple_form_bootstrap"
|
17
|
+
|
1
18
|
module Dorsale
|
2
19
|
class Engine < ::Rails::Engine
|
3
20
|
isolate_namespace Dorsale
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dorsale
|
2
|
+
module PolymorphicId
|
3
|
+
module ClassMethods
|
4
|
+
def polymorphic_id_for(relation_name)
|
5
|
+
module_src = File.read(__FILE__).split("__END__").last
|
6
|
+
module_src = module_src.gsub("relation", relation_name.to_s)
|
7
|
+
send :include, eval(module_src)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(model)
|
12
|
+
model.send(:extend, Dorsale::PolymorphicId::ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
def guid
|
16
|
+
return nil if new_record?
|
17
|
+
|
18
|
+
"#{self.class}-#{self.id}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# __END__
|
24
|
+
|
25
|
+
Module.new do
|
26
|
+
def relation_guid
|
27
|
+
return nil if relation_type.blank? || relation_id.blank?
|
28
|
+
|
29
|
+
"#{relation_type}-#{relation_id}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def relation_guid=(guid)
|
33
|
+
return self.relation = nil if guid.blank?
|
34
|
+
|
35
|
+
type, id = guid.split("-")
|
36
|
+
self.relation = type.constantize.find(id)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# Use this setup block to configure all options available in SimpleForm.
|
2
|
+
SimpleForm.setup do |config|
|
3
|
+
# Wrappers are used by the form builder to generate a
|
4
|
+
# complete input. You can remove any component from the
|
5
|
+
# wrapper, change the order or even add your own to the
|
6
|
+
# stack. The options given below are used to wrap the
|
7
|
+
# whole input.
|
8
|
+
config.wrappers :default, class: :input,
|
9
|
+
hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
10
|
+
## Extensions enabled by default
|
11
|
+
# Any of these extensions can be disabled for a
|
12
|
+
# given input by passing: `f.input EXTENSION_NAME => false`.
|
13
|
+
# You can make any of these extensions optional by
|
14
|
+
# renaming `b.use` to `b.optional`.
|
15
|
+
|
16
|
+
# Determines whether to use HTML5 (:email, :url, ...)
|
17
|
+
# and required attributes
|
18
|
+
b.use :html5
|
19
|
+
|
20
|
+
# Calculates placeholders automatically from I18n
|
21
|
+
# You can also pass a string as f.input placeholder: "Placeholder"
|
22
|
+
b.use :placeholder
|
23
|
+
|
24
|
+
## Optional extensions
|
25
|
+
# They are disabled unless you pass `f.input EXTENSION_NAME => true`
|
26
|
+
# to the input. If so, they will retrieve the values from the model
|
27
|
+
# if any exists. If you want to enable any of those
|
28
|
+
# extensions by default, you can change `b.optional` to `b.use`.
|
29
|
+
|
30
|
+
# Calculates maxlength from length validations for string inputs
|
31
|
+
b.optional :maxlength
|
32
|
+
|
33
|
+
# Calculates pattern from format validations for string inputs
|
34
|
+
b.optional :pattern
|
35
|
+
|
36
|
+
# Calculates min and max from length validations for numeric inputs
|
37
|
+
b.optional :min_max
|
38
|
+
|
39
|
+
# Calculates readonly automatically from readonly attributes
|
40
|
+
b.optional :readonly
|
41
|
+
|
42
|
+
## Inputs
|
43
|
+
b.use :label_input
|
44
|
+
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
45
|
+
b.use :error, wrap_with: { tag: :span, class: :error }
|
46
|
+
|
47
|
+
## full_messages_for
|
48
|
+
# If you want to display the full error message for the attribute, you can
|
49
|
+
# use the component :full_error, like:
|
50
|
+
#
|
51
|
+
# b.use :full_error, wrap_with: { tag: :span, class: :error }
|
52
|
+
end
|
53
|
+
|
54
|
+
# The default wrapper to be used by the FormBuilder.
|
55
|
+
config.default_wrapper = :default
|
56
|
+
|
57
|
+
# Define the way to render check boxes / radio buttons with labels.
|
58
|
+
# Defaults to :nested for bootstrap config.
|
59
|
+
# inline: input + label
|
60
|
+
# nested: label > input
|
61
|
+
config.boolean_style = :nested
|
62
|
+
|
63
|
+
# Default class for buttons
|
64
|
+
config.button_class = 'btn'
|
65
|
+
|
66
|
+
# Method used to tidy up errors. Specify any Rails Array method.
|
67
|
+
# :first lists the first message for each field.
|
68
|
+
# Use :to_sentence to list all errors for each field.
|
69
|
+
# config.error_method = :first
|
70
|
+
|
71
|
+
# Default tag used for error notification helper.
|
72
|
+
config.error_notification_tag = :div
|
73
|
+
|
74
|
+
# CSS class to add for error notification helper.
|
75
|
+
config.error_notification_class = 'error_notification'
|
76
|
+
|
77
|
+
# ID to add for error notification helper.
|
78
|
+
# config.error_notification_id = nil
|
79
|
+
|
80
|
+
# Series of attempts to detect a default label method for collection.
|
81
|
+
# config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
|
82
|
+
|
83
|
+
# Series of attempts to detect a default value method for collection.
|
84
|
+
# config.collection_value_methods = [ :id, :to_s ]
|
85
|
+
|
86
|
+
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
87
|
+
# config.collection_wrapper_tag = nil
|
88
|
+
|
89
|
+
# You can define the class to use on all collection wrappers. Defaulting to none.
|
90
|
+
# config.collection_wrapper_class = nil
|
91
|
+
|
92
|
+
# You can wrap each item in a collection of radio/check boxes with a tag,
|
93
|
+
# defaulting to :span. Please note that when using :boolean_style = :nested,
|
94
|
+
# SimpleForm will force this option to be a label.
|
95
|
+
# config.item_wrapper_tag = :span
|
96
|
+
|
97
|
+
# You can define a class to use in all item wrappers. Defaulting to none.
|
98
|
+
# config.item_wrapper_class = nil
|
99
|
+
|
100
|
+
# How the label text should be generated altogether with the required text.
|
101
|
+
# config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
|
102
|
+
|
103
|
+
# You can define the class to use on all labels. Default is nil.
|
104
|
+
# config.label_class = nil
|
105
|
+
|
106
|
+
# You can define the default class to be used on forms. Can be overriden
|
107
|
+
# with `html: { :class }`. Defaulting to none.
|
108
|
+
# config.default_form_class = nil
|
109
|
+
|
110
|
+
# You can define which elements should obtain additional classes
|
111
|
+
# config.generate_additional_classes_for = [:wrapper, :label, :input]
|
112
|
+
|
113
|
+
# Whether attributes are required by default (or not). Default is true.
|
114
|
+
# config.required_by_default = true
|
115
|
+
|
116
|
+
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
|
117
|
+
# These validations are enabled in SimpleForm's internal config but disabled by default
|
118
|
+
# in this configuration, which is recommended due to some quirks from different browsers.
|
119
|
+
# To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
|
120
|
+
# change this configuration to true.
|
121
|
+
config.browser_validations = false
|
122
|
+
|
123
|
+
# Collection of methods to detect if a file type was given.
|
124
|
+
# config.file_methods = [ :mounted_as, :file?, :public_filename ]
|
125
|
+
|
126
|
+
# Custom mappings for input types. This should be a hash containing a regexp
|
127
|
+
# to match as key, and the input type that will be used when the field name
|
128
|
+
# matches the regexp as value.
|
129
|
+
# config.input_mappings = { /count/ => :integer }
|
130
|
+
|
131
|
+
# Custom wrappers for input types. This should be a hash containing an input
|
132
|
+
# type as key and the wrapper that will be used for all inputs with specified type.
|
133
|
+
# config.wrapper_mappings = { string: :prepend }
|
134
|
+
|
135
|
+
# Namespaces where SimpleForm should look for custom input classes that
|
136
|
+
# override default inputs.
|
137
|
+
# config.custom_inputs_namespaces << "CustomInputs"
|
138
|
+
|
139
|
+
# Default priority for time_zone inputs.
|
140
|
+
# config.time_zone_priority = nil
|
141
|
+
|
142
|
+
# Default priority for country inputs.
|
143
|
+
# config.country_priority = nil
|
144
|
+
|
145
|
+
# When false, do not use translations for labels.
|
146
|
+
# config.translate_labels = true
|
147
|
+
|
148
|
+
# Automatically discover new inputs in Rails' autoload path.
|
149
|
+
# config.inputs_discovery = true
|
150
|
+
|
151
|
+
# Cache SimpleForm inputs discovery
|
152
|
+
# config.cache_discovery = !Rails.env.development?
|
153
|
+
|
154
|
+
# Default class for inputs
|
155
|
+
# config.input_class = nil
|
156
|
+
|
157
|
+
# Define the default class of the input wrapper of the boolean input.
|
158
|
+
config.boolean_label_class = 'checkbox'
|
159
|
+
|
160
|
+
# Defines if the default input wrapper class should be included in radio
|
161
|
+
# collection wrappers.
|
162
|
+
# config.include_default_input_wrapper_class = true
|
163
|
+
|
164
|
+
# Defines which i18n scope will be used in Simple Form.
|
165
|
+
# config.i18n_scope = 'simple_form'
|
166
|
+
end
|