promethee 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +164 -19
- data/Rakefile +33 -2
- data/app/assets/images/icon-promethee.png +0 -0
- data/app/assets/images/logo-promethee-horizontal.svg +14 -0
- data/app/assets/images/logo-promethee-vertical.svg +14 -0
- data/app/assets/javascripts/promethee.js +59 -0
- data/app/assets/javascripts/promethee/controller.js +22 -0
- data/app/assets/stylesheets/promethee-editor.sass +105 -0
- data/app/assets/stylesheets/promethee-editor/_mixins.sass +19 -0
- data/app/assets/stylesheets/promethee-editor/_variables.sass +4 -0
- data/app/assets/stylesheets/promethee.sass +4 -0
- data/app/views/promethee/_edit.html.erb +172 -0
- data/app/views/promethee/_show.html.erb +6 -0
- data/app/views/promethee/components/_column.html.erb +8 -0
- data/app/views/promethee/components/_column_edit.html.erb +40 -0
- data/app/views/promethee/components/_image.html.erb +7 -0
- data/app/views/promethee/components/_image_edit.html.erb +60 -0
- data/app/views/promethee/components/_index.html.erb +3 -0
- data/app/views/promethee/components/_index_edit.html.erb +7 -0
- data/app/views/promethee/components/_row.html.erb +6 -0
- data/app/views/promethee/components/_row_edit.html.erb +53 -0
- data/app/views/promethee/components/_show.html.erb +4 -0
- data/app/views/promethee/components/_show_edit.html.erb +3 -0
- data/app/views/promethee/components/_text.html.erb +6 -0
- data/app/views/promethee/components/_text_edit.html.erb +59 -0
- data/app/views/promethee/components/_video.html.erb +16 -0
- data/app/views/promethee/components/_video_edit.html.erb +63 -0
- data/app/views/promethee/partials/_toolbar_buttons.html.erb +4 -0
- data/lib/promethee.rb +37 -2
- data/lib/promethee/component.rb +28 -0
- data/lib/promethee/component/attribute.rb +42 -0
- data/lib/promethee/component/attribute/boolean.rb +4 -0
- data/lib/promethee/component/attribute/float.rb +3 -0
- data/lib/promethee/component/attribute/integer.rb +3 -0
- data/lib/promethee/component/attribute/string.rb +3 -0
- data/lib/promethee/component/attributes.rb +50 -0
- data/lib/promethee/component/attributes/definer.rb +13 -0
- data/lib/promethee/component/base.rb +68 -0
- data/lib/promethee/component/collection.rb +17 -0
- data/lib/promethee/component/column.rb +8 -0
- data/lib/promethee/component/image.rb +6 -0
- data/lib/promethee/component/row.rb +3 -0
- data/lib/promethee/component/text.rb +5 -0
- data/lib/promethee/component/video.rb +5 -0
- data/lib/promethee/core_ext/form_builder.rb +6 -0
- data/lib/promethee/core_ext/form_helper.rb +6 -0
- data/lib/promethee/core_ext/tags.rb +18 -0
- data/lib/promethee/grid.rb +52 -0
- data/lib/promethee/rails/engine.rb +7 -0
- data/lib/promethee/rails/helper.rb +26 -0
- data/lib/promethee/rails/version.rb +5 -0
- data/lib/tasks/promethee/promethee.rake +4 -0
- metadata +202 -20
- data/.gitignore +0 -9
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -6
- data/LICENSE +0 -21
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/promethee/version.rb +0 -3
- data/promethee.gemspec +0 -24
@@ -0,0 +1,16 @@
|
|
1
|
+
<%
|
2
|
+
url = component[:attributes][:url].to_s
|
3
|
+
|
4
|
+
if 'vimeo'.in? url
|
5
|
+
video_id = url.to_s.gsub(/\A(?:https?:)?\/\/(?:(?:www|player)\.)?vimeo\.com\/(?:video\/)?(\d+).*?\z/, '\1')
|
6
|
+
iframe_src = "https://player.vimeo.com/video/#{video_id}?color=ffffff&title=0&byline=0&portrait=0"
|
7
|
+
elsif 'youtube'.in? url
|
8
|
+
video_id = url.to_s.split('watch?v=').last
|
9
|
+
iframe_src = "http://www.youtube.com/embed/#{video_id}"
|
10
|
+
end
|
11
|
+
%>
|
12
|
+
<div class="embed-responsive embed-responsive-16by9 <%= promethee_class_for component %>">
|
13
|
+
<% if iframe_src.present? %>
|
14
|
+
<iframe frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="allowfullscreen" src="<%= iframe_src %>"></iframe>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<script type="text/ng-template" id="promethee/components/video">
|
2
|
+
<div ng-controller="VideoController">
|
3
|
+
<div dnd-draggable="component"
|
4
|
+
dnd-moved="remove()"
|
5
|
+
dnd-type="component.type"
|
6
|
+
class="promethee-editor__component promethee-editor__component--video promethee-editor__component--final">
|
7
|
+
<div class="promethee-editor__toolbar">
|
8
|
+
Video
|
9
|
+
<%= render 'promethee/partials/toolbar_buttons' %>
|
10
|
+
</div>
|
11
|
+
<div ng-show="editing" class="promethee-editor__wrapper">
|
12
|
+
<div class="form-group">
|
13
|
+
<label class="label-control">Url</label>
|
14
|
+
<input ng-model="component.attributes.url" class="form-control" type="text"/>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div class="embed-responsive embed-responsive-16by9">
|
18
|
+
<iframe ng-if="embed" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="allowfullscreen" ng-src="{{embed | urlSafe}}"></iframe>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</script>
|
23
|
+
|
24
|
+
<script>
|
25
|
+
angular.injector(['ng', '<%= promethee_id %>']).get('definitions').push({
|
26
|
+
name: 'Video',
|
27
|
+
thumb: 'http://via.placeholder.com/300x200',
|
28
|
+
data: {
|
29
|
+
type: 'video',
|
30
|
+
attributes: {
|
31
|
+
url: 'https://vimeo.com/115082758'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
});
|
35
|
+
|
36
|
+
promethee.controller('VideoController', ['$scope', function($scope) {
|
37
|
+
|
38
|
+
$scope.editing = false;
|
39
|
+
|
40
|
+
$scope.remove = function() {
|
41
|
+
this.components.splice(this.components.indexOf(this.component), 1);
|
42
|
+
};
|
43
|
+
|
44
|
+
Object.defineProperty($scope, 'embed', {
|
45
|
+
get: function() {
|
46
|
+
var embed = null;
|
47
|
+
var url = this.component.attributes.url + '';
|
48
|
+
|
49
|
+
if(url.includes('vimeo')) {
|
50
|
+
var id = url.replace(/^(?:https?:)?\/\/(?:(?:www|player)\.)?vimeo\.com\/(?:video\/)?(\d+).*?$/, '$1');
|
51
|
+
embed = 'https://player.vimeo.com/video/' + id + '?color=ffffff&title=0&byline=0&portrait=0';
|
52
|
+
}
|
53
|
+
else if(url.includes('youtube')) {
|
54
|
+
var parts = url.split('watch?v=');
|
55
|
+
var id = parts[parts.length - 1];
|
56
|
+
embed = 'http://www.youtube.com/embed/' + id;
|
57
|
+
}
|
58
|
+
|
59
|
+
return embed;
|
60
|
+
}
|
61
|
+
})
|
62
|
+
}]);
|
63
|
+
</script>
|
data/lib/promethee.rb
CHANGED
@@ -1,5 +1,40 @@
|
|
1
|
-
require
|
1
|
+
require 'bootstrap-sass'
|
2
|
+
require 'font-awesome-rails'
|
3
|
+
require 'jquery-rails'
|
4
|
+
require 'jquery-ui-rails'
|
5
|
+
require 'tinymce-rails'
|
6
|
+
require 'angularjs-rails'
|
7
|
+
require 'angular-ui-tinymce/rails'
|
8
|
+
require 'material_icons'
|
2
9
|
|
3
10
|
module Promethee
|
4
|
-
|
11
|
+
module Rails
|
12
|
+
require 'promethee/rails/helper'
|
13
|
+
require 'promethee/rails/engine'
|
14
|
+
require 'promethee/rails/version'
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'promethee/component'
|
18
|
+
require 'promethee/component/attribute'
|
19
|
+
require 'promethee/component/attribute/boolean'
|
20
|
+
require 'promethee/component/attribute/integer'
|
21
|
+
require 'promethee/component/attribute/float'
|
22
|
+
require 'promethee/component/attribute/string'
|
23
|
+
|
24
|
+
require 'promethee/component/attributes'
|
25
|
+
require 'promethee/component/attributes/definer'
|
26
|
+
|
27
|
+
require 'promethee/component/base'
|
28
|
+
require 'promethee/component/collection'
|
29
|
+
require 'promethee/component/row'
|
30
|
+
require 'promethee/component/column'
|
31
|
+
require 'promethee/component/text'
|
32
|
+
require 'promethee/component/image'
|
33
|
+
require 'promethee/component/video'
|
34
|
+
|
35
|
+
require 'promethee/grid'
|
36
|
+
|
37
|
+
require 'promethee/core_ext/tags'
|
38
|
+
require 'promethee/core_ext/form_helper'
|
39
|
+
require 'promethee/core_ext/form_builder'
|
5
40
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Promethee::Component
|
2
|
+
def self.types
|
3
|
+
Base.descendants.map &:type
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.as type
|
7
|
+
begin
|
8
|
+
class_name = "::Promethee::Component::#{type.to_s.classify}"
|
9
|
+
require "promethee/component/#{type}" unless Object.const_defined? class_name
|
10
|
+
class_name.constantize
|
11
|
+
rescue LoadError
|
12
|
+
raise "Unknown Prométhée component type \"#{type}\". Available types: \"#{types.join '", "'}\"."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from data
|
17
|
+
raise "Invalid data provided, expected a Hash got a #{data.class}." unless data.is_a? Hash
|
18
|
+
|
19
|
+
data = data.deep_dup
|
20
|
+
|
21
|
+
data[:attributes] = {} unless data[:attributes].is_a? Hash
|
22
|
+
data[:children] = [] unless data[:children].is_a? Array
|
23
|
+
|
24
|
+
data[:children].map! { |data| from data }
|
25
|
+
|
26
|
+
as(data[:type]).new attributes: data[:attributes], children: data[:children]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Promethee::Component::Attribute
|
2
|
+
class Base
|
3
|
+
attr_reader :name, :value
|
4
|
+
|
5
|
+
def initialize name, value = default
|
6
|
+
@name = name.to_s.to_sym
|
7
|
+
self.value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def value= value
|
11
|
+
@value = value == default ? default : cast(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def default
|
15
|
+
self.class.default
|
16
|
+
end
|
17
|
+
|
18
|
+
def cast value
|
19
|
+
self.class.cast.call value
|
20
|
+
end
|
21
|
+
|
22
|
+
def dup
|
23
|
+
self.class.new name, (value.dup rescue value)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.type
|
29
|
+
to_s.split('::').last.underscore
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.default value = nil
|
33
|
+
@value = value unless value.nil?
|
34
|
+
@value
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.cast &block
|
38
|
+
@cast = block if block_given?
|
39
|
+
@cast ||= -> (value) { value }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Promethee::Component::Attributes
|
2
|
+
def update hash
|
3
|
+
(names & hash.keys.map(&:to_sym)).each { |name| attributes[name].value = hash[name] }
|
4
|
+
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_hash
|
9
|
+
attributes.map{ |name, attribute| [name, attribute.value] }.to_h
|
10
|
+
end
|
11
|
+
alias_method :to_h, :to_hash
|
12
|
+
alias_method :as_json, :to_hash
|
13
|
+
|
14
|
+
def [](method)
|
15
|
+
send method
|
16
|
+
end
|
17
|
+
|
18
|
+
def keys
|
19
|
+
attributes.keys
|
20
|
+
end
|
21
|
+
alias_method :names, :keys
|
22
|
+
|
23
|
+
def each &block
|
24
|
+
attributes.values.each &block
|
25
|
+
end
|
26
|
+
|
27
|
+
def << attribute
|
28
|
+
attributes[attribute.name] = attribute
|
29
|
+
|
30
|
+
define_singleton_method(attribute.name) { attribute.value }
|
31
|
+
define_singleton_method("#{attribute.name}=") { |value| attribute.value = value }
|
32
|
+
end
|
33
|
+
|
34
|
+
def dup
|
35
|
+
duplicate = self.class.new
|
36
|
+
each { |attribute| duplicate << attribute.dup }
|
37
|
+
|
38
|
+
duplicate
|
39
|
+
end
|
40
|
+
|
41
|
+
def copy hash
|
42
|
+
dup.update hash
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def attributes
|
48
|
+
@attributes ||= {}
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Promethee::Component::Attributes::Definer
|
2
|
+
attr_reader :component
|
3
|
+
|
4
|
+
def initialize(component)
|
5
|
+
@component = component
|
6
|
+
end
|
7
|
+
|
8
|
+
::Promethee::Component::Attribute::Base.descendants.each do |attribute|
|
9
|
+
define_method attribute.type do |name, default: nil|
|
10
|
+
component.attributes << attribute.new(name, default)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Promethee::Component::Base
|
2
|
+
attr_reader :attributes, :children
|
3
|
+
|
4
|
+
def initialize(attributes: {}, children: [])
|
5
|
+
@attributes = self.class.attributes.copy attributes
|
6
|
+
@children = Promethee::Component::Collection.new children
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_hash *options
|
10
|
+
{
|
11
|
+
type: type,
|
12
|
+
attributes: attributes.to_hash,
|
13
|
+
children: children.to_ary
|
14
|
+
}
|
15
|
+
end
|
16
|
+
alias_method :to_h, :to_hash
|
17
|
+
alias_method :as_json, :to_hash
|
18
|
+
|
19
|
+
def to_html
|
20
|
+
ApplicationController.renderer.render partial: "promethee/components/#{type}", locals: { component: self }
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](method)
|
24
|
+
send method
|
25
|
+
end
|
26
|
+
|
27
|
+
def class_name
|
28
|
+
"promethee__component promethee__component--#{type}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
self.class.type
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.attributes
|
36
|
+
@attributes ||= Promethee::Component::Attributes.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.children
|
40
|
+
@children ||= []
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.type
|
44
|
+
to_s.split('::').last.underscore.to_sym
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.final?
|
48
|
+
children.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
# def self.class_name
|
52
|
+
# "promethee-editor__component promethee__component--#{type}#{' promethee__component--final' if final?}"
|
53
|
+
# end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def self.has_attributes
|
58
|
+
yield Promethee::Component::Attributes::Definer.new(self) if block_given?
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.has_children *components
|
62
|
+
children.concat(components.flatten.map{ |component| component.is_a?(Class) && component < self ? component : Promethee::Component.as(component) }).uniq!
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
alias_method :has_child, :has_children
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Promethee::Component::Collection < Array
|
2
|
+
def to_ary
|
3
|
+
map &:to_hash
|
4
|
+
end
|
5
|
+
alias_method :to_a, :to_ary
|
6
|
+
alias_method :as_json, :to_ary
|
7
|
+
|
8
|
+
def to_html
|
9
|
+
map(&:to_html).join.html_safe
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from data
|
13
|
+
raise "Invalid data provided, expected a Array got a #{data.class}." unless data.is_a? Array
|
14
|
+
|
15
|
+
new data.map{ |component| Promethee::Component.from component }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
ActionView::Helpers::FormBuilder.class_eval do
|
2
|
+
# https://github.com/rails/rails/blob/13c5aa818e9284fe30f83469b340e579195bda3f/actionview/lib/action_view/helpers/form_helper.rb#L2148
|
3
|
+
def promethee(method, options = {})
|
4
|
+
@template.promethee_editor(@object_name, method, objectify_options(options))
|
5
|
+
end
|
6
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
ActionView::Helpers::FormHelper.class_eval do
|
2
|
+
# https://github.com/rails/rails/blob/13c5aa818e9284fe30f83469b340e579195bda3f/actionview/lib/action_view/helpers/form_helper.rb#L1193
|
3
|
+
def promethee_editor(object_name, method, options = {})
|
4
|
+
ActionView::Helpers::Tags::PrometheeEditor.new(object_name, method, self, options).render
|
5
|
+
end
|
6
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'promethee'
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
module Helpers
|
5
|
+
module Tags
|
6
|
+
# https://github.com/rails/rails/blob/bdc581616b760d1e2be3795c6f0f3ab4b1e125a5/actionview/lib/action_view/helpers/tags/text_field.rb
|
7
|
+
class PrometheeEditor < Base
|
8
|
+
def render
|
9
|
+
options = @options.stringify_keys
|
10
|
+
add_default_name_and_id(options)
|
11
|
+
data = options.fetch("value") { value_before_type_cast(object) }
|
12
|
+
|
13
|
+
Promethee::Grid.new(data, name: options["name"]).edit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|