promethee 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +164 -19
  3. data/Rakefile +33 -2
  4. data/app/assets/images/icon-promethee.png +0 -0
  5. data/app/assets/images/logo-promethee-horizontal.svg +14 -0
  6. data/app/assets/images/logo-promethee-vertical.svg +14 -0
  7. data/app/assets/javascripts/promethee.js +59 -0
  8. data/app/assets/javascripts/promethee/controller.js +22 -0
  9. data/app/assets/stylesheets/promethee-editor.sass +105 -0
  10. data/app/assets/stylesheets/promethee-editor/_mixins.sass +19 -0
  11. data/app/assets/stylesheets/promethee-editor/_variables.sass +4 -0
  12. data/app/assets/stylesheets/promethee.sass +4 -0
  13. data/app/views/promethee/_edit.html.erb +172 -0
  14. data/app/views/promethee/_show.html.erb +6 -0
  15. data/app/views/promethee/components/_column.html.erb +8 -0
  16. data/app/views/promethee/components/_column_edit.html.erb +40 -0
  17. data/app/views/promethee/components/_image.html.erb +7 -0
  18. data/app/views/promethee/components/_image_edit.html.erb +60 -0
  19. data/app/views/promethee/components/_index.html.erb +3 -0
  20. data/app/views/promethee/components/_index_edit.html.erb +7 -0
  21. data/app/views/promethee/components/_row.html.erb +6 -0
  22. data/app/views/promethee/components/_row_edit.html.erb +53 -0
  23. data/app/views/promethee/components/_show.html.erb +4 -0
  24. data/app/views/promethee/components/_show_edit.html.erb +3 -0
  25. data/app/views/promethee/components/_text.html.erb +6 -0
  26. data/app/views/promethee/components/_text_edit.html.erb +59 -0
  27. data/app/views/promethee/components/_video.html.erb +16 -0
  28. data/app/views/promethee/components/_video_edit.html.erb +63 -0
  29. data/app/views/promethee/partials/_toolbar_buttons.html.erb +4 -0
  30. data/lib/promethee.rb +37 -2
  31. data/lib/promethee/component.rb +28 -0
  32. data/lib/promethee/component/attribute.rb +42 -0
  33. data/lib/promethee/component/attribute/boolean.rb +4 -0
  34. data/lib/promethee/component/attribute/float.rb +3 -0
  35. data/lib/promethee/component/attribute/integer.rb +3 -0
  36. data/lib/promethee/component/attribute/string.rb +3 -0
  37. data/lib/promethee/component/attributes.rb +50 -0
  38. data/lib/promethee/component/attributes/definer.rb +13 -0
  39. data/lib/promethee/component/base.rb +68 -0
  40. data/lib/promethee/component/collection.rb +17 -0
  41. data/lib/promethee/component/column.rb +8 -0
  42. data/lib/promethee/component/image.rb +6 -0
  43. data/lib/promethee/component/row.rb +3 -0
  44. data/lib/promethee/component/text.rb +5 -0
  45. data/lib/promethee/component/video.rb +5 -0
  46. data/lib/promethee/core_ext/form_builder.rb +6 -0
  47. data/lib/promethee/core_ext/form_helper.rb +6 -0
  48. data/lib/promethee/core_ext/tags.rb +18 -0
  49. data/lib/promethee/grid.rb +52 -0
  50. data/lib/promethee/rails/engine.rb +7 -0
  51. data/lib/promethee/rails/helper.rb +26 -0
  52. data/lib/promethee/rails/version.rb +5 -0
  53. data/lib/tasks/promethee/promethee.rake +4 -0
  54. metadata +202 -20
  55. data/.gitignore +0 -9
  56. data/CODE_OF_CONDUCT.md +0 -74
  57. data/Gemfile +0 -6
  58. data/LICENSE +0 -21
  59. data/bin/console +0 -14
  60. data/bin/setup +0 -8
  61. data/lib/promethee/version.rb +0 -3
  62. data/promethee.gemspec +0 -24
@@ -0,0 +1,19 @@
1
+ =grid-builder-set-gutter-width($width)
2
+ $was: $grid-gutter-width
3
+ $grid-gutter-width: $width !global
4
+
5
+ .row
6
+ +make-row
7
+
8
+ +make-grid-columns
9
+ +make-grid(xs)
10
+ @media(min-width: 768px)
11
+ +make-grid(sm)
12
+
13
+ @media (min-width: 992px)
14
+ +make-grid(md)
15
+
16
+ @media (min-width: 1200px)
17
+ +make-grid(lg)
18
+
19
+ $grid-gutter-width: $was !global
@@ -0,0 +1,4 @@
1
+ $promethee-grey: #bbb
2
+ $promethee-transparent-grey: transparentize($promethee-grey, .8)
3
+
4
+ $promethee-light-grey: #eee
@@ -0,0 +1,4 @@
1
+ // @import 'promethee/colors'
2
+ @import 'bootstrap'
3
+
4
+ .promethee
@@ -0,0 +1,172 @@
1
+ <%
2
+ promethee_id = "promethee-#{SecureRandom.hex 10}"
3
+ promethee_data = promethee.data
4
+ promethee_data = promethee_data.to_json unless promethee_data.is_a? String
5
+ %>
6
+
7
+ <script>
8
+ var promethee = angular
9
+ .module('<%= promethee_id %>', ['ui.tinymce', 'dndLists'])
10
+ .constant('data', <%= promethee_data.html_safe %>)
11
+ .value('state', {
12
+ editing: false
13
+ })
14
+ .value('definitions', [])
15
+ .filter('htmlSafe', ['$sce', function($sce) {
16
+ return function(val) {
17
+ return $sce.trustAsHtml(val);
18
+ };
19
+ }])
20
+ .filter('urlSafe', ['$sce', function($sce) {
21
+ return function(val) {
22
+ return $sce.trustAsResourceUrl(val);
23
+ };
24
+ }])
25
+ .filter('humanize', function() {
26
+ return function(val) {
27
+ val = (val + '').replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').replace(/\s\s+/, ' ').trim();
28
+ return val[0].toUpperCase() + val.substring(1).toLowerCase();
29
+ };
30
+ });
31
+ </script>
32
+
33
+ <div id="<%= promethee_id %>"
34
+ class="promethee-editor"
35
+ ng-app="<%= promethee_id %>"
36
+ ng-controller="PrometheeController as prometheeController"
37
+ ng-class="{
38
+ 'fullscreen': fullscreen,
39
+ 'promethee-editor--preview': preview,
40
+ 'promethee-editor--preview--mobile': preview && previewMode == 'mobile',
41
+ 'promethee-editor--preview--tablet': preview && previewMode == 'tablet',
42
+ 'promethee-editor--preview--desktop': preview && previewMode == 'desktop'
43
+ }">
44
+
45
+ <% # TODO custom views %>
46
+ <% Dir['app/views/promethee/components/*'].each do |file| %>
47
+ <% end %>
48
+ <% # TODO iterate over files in gem %>
49
+ <% ['index', 'show', 'row', 'column', 'text', 'image', 'video'].each do |type| %>
50
+ <%= render partial: "promethee/components/#{type}_edit", locals: { promethee_id: promethee_id } %>
51
+ <% end %>
52
+
53
+ <input type="hidden" name="page[data]" id="page_data" value="{{data}}" />
54
+
55
+ <nav class="navbar navbar-default">
56
+ <div class="container-fluid">
57
+ <div class="navbar-header">
58
+ <%= image_tag 'icon-promethee.png', class: 'navbar-brand' %>
59
+ </div>
60
+ <div id="navbar">
61
+ <ul class="nav navbar-nav navbar-right">
62
+ <li ng-click="enablePreview()" ng-hide="preview"><a><%= fa_icon :eye %></a></li>
63
+ <li ng-click="previewMode = 'mobile'" ng-class="{ active: previewMode == 'mobile' }" ng-show="preview">
64
+ <a><%= fa_icon :mobile %></a>
65
+ </li>
66
+ <li ng-click="previewMode = 'tablet'" ng-class="{ active: previewMode == 'tablet' }" ng-show="preview"><a>
67
+ <%= fa_icon :tablet %></a>
68
+ </li>
69
+ <li ng-click="previewMode = 'desktop'" ng-class="{ active: previewMode == 'desktop' }" ng-show="preview"><a>
70
+ <%= fa_icon :desktop %></a>
71
+ </li>
72
+ <li ng-click="disablePreview()" ng-show="preview"><a><%= fa_icon 'eye-slash' %></a>
73
+ </li>
74
+ <li ng-click="enableFullscreen()" ng-hide="fullscreen"><a><%= fa_icon :expand %></a></li>
75
+ <li ng-click="disableFullscreen()" ng-show="fullscreen"><a><%= fa_icon :compress %></a></li>
76
+ </ul>
77
+ </div>
78
+ </div>
79
+ </nav>
80
+ <div class="promethee-editor__page" ng-class="{ 'container-fluid': fullscreen }">
81
+ <ng-include src="'promethee/components/index'"></ng-include>
82
+ </div>
83
+
84
+ <span type="button" class="btn btn-default btn-block" ng-click="addComponentTo(data)" style="margin-bottom: 6px">Add component</span>
85
+
86
+ <div class="promethee-editor__adder" ng-controller="AdderController">
87
+ <div class="modal fade in" tabindex="-1" role="dialog" style="display: {{adding ? 'block' : 'none'}}">
88
+ <div class="modal-dialog modal-lg" role="document">
89
+ <div class="modal-content">
90
+ <div class="modal-header">
91
+ <button type="button" class="close" ng-click="close()"><span aria-hidden="true">&times;</span></button>
92
+ <h4 class="modal-title">Select component</h4>
93
+ </div>
94
+ <div class="modal-body">
95
+ <div class="row">
96
+ <div ng-repeat="definition in definitions"
97
+ ng-click="pushComponent(definition)"
98
+ class="col-md-3">
99
+ <div class="thumbnail">
100
+ <img ng-src="{{definition.thumb}}" class="img-responsive">
101
+ <h4>{{definition.name}}</h4>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Work in progress -->
112
+ <!-- <iframe id="iframe"></iframe> !-->
113
+ </div>
114
+
115
+ <script>
116
+ promethee.controller('PrometheeController', ['data', '$scope', 'definitions', function(data, $scope, definitions) {
117
+ if (data === null || data === '') {
118
+ data = [];
119
+ }
120
+ $scope.data = data;
121
+ $scope.fullscreen = false;
122
+ $scope.preview = false;
123
+ $scope.previewMode = 'desktop';
124
+ $scope.component = {
125
+ children: data
126
+ };
127
+
128
+ $scope.allowedTypes = definitions.map(function(definition) {
129
+ return definition.data.type;
130
+ });
131
+
132
+ $scope.enablePreview = function() {
133
+ this.preview = true;
134
+ // Work in progress
135
+ // document.getElementById('iframe').contentWindow.document.documentElement.innerHTML = document.documentElement.innerHTML;
136
+ }
137
+
138
+ $scope.disablePreview = function() {
139
+ this.preview = false;
140
+ }
141
+
142
+ $scope.enableFullscreen = function() {
143
+ this.fullscreen = true;
144
+ }
145
+
146
+ $scope.disableFullscreen = function() {
147
+ this.fullscreen = false;
148
+ }
149
+
150
+ }]);
151
+
152
+ promethee.controller('AdderController', ['$scope', '$rootScope', 'definitions', function($scope, $rootScope, definitions) {
153
+
154
+ $scope.adding = null;
155
+ $scope.definitions = definitions;
156
+
157
+ $scope.close = function() {
158
+ $scope.adding = null;
159
+ };
160
+
161
+ $scope.pushComponent = function(definition) {
162
+ var definition = angular.copy(definition.data);
163
+ $scope.adding.push(definition);
164
+ $scope.close();
165
+ };
166
+
167
+ $rootScope.addComponentTo = function(components) {
168
+ $scope.adding = components;
169
+ };
170
+
171
+ }]);
172
+ </script>
@@ -0,0 +1,6 @@
1
+ <%
2
+ data = JSON.parse data, symbolize_names: true if data.is_a? String
3
+ %>
4
+ <div class="promethee">
5
+ <%= render partial: 'promethee/components/index', locals: { components: data } %>
6
+ </div>
@@ -0,0 +1,8 @@
1
+ <%
2
+ size = component[:attributes][:size]
3
+ offset = component[:attributes][:offset]
4
+ children = component[:children]
5
+ %>
6
+ <div class="col col-md-<%= size %><%= " col-md-offset-#{offset}" if offset > 0 %> <%= promethee_class_for component %>">
7
+ <%= render partial: 'promethee/components/index', locals: { components: children } %>
8
+ </div>
@@ -0,0 +1,40 @@
1
+ <script type="text/ng-template" id="promethee/components/column">
2
+ <div ng-controller="ColumnController">
3
+ <div class="col col-md-{{component.attributes.size}} col-md-offset-{{component.attributes.offset}}">
4
+ <div dnd-draggable="component" dnd-moved="remove()" dnd-type="component.type" class="promethee-editor__component promethee-editor__component--column">
5
+ <div class="promethee-editor__toolbar">
6
+ Column
7
+ <%= render 'promethee/partials/toolbar_buttons' %>
8
+ </div>
9
+ <div ng-show="editing" class="promethee-editor__wrapper">
10
+ <div class="form-group">
11
+ <label class="label-control">Size</label>
12
+ <input ng-model="component.attributes.size" class="form-control" type="number"/>
13
+ </div>
14
+ <div class="form-group">
15
+ <label class="label-control">Offset</label>
16
+ <input ng-model="component.attributes.offset" class="form-control" type="number"/>
17
+ </div>
18
+ </div>
19
+
20
+ <ng-include src="'promethee/components/index'"></ng-include>
21
+
22
+ <span type="button" class="btn btn-default btn-block" ng-click="addComponentTo(component.children)" style="margin: 0 6px 6px 6px;width: auto">Add component</span>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </script>
27
+
28
+ <script>
29
+ promethee.controller('ColumnController', ['$scope', 'definitions', function($scope, definitions) {
30
+
31
+ $scope.allowedTypes = definitions.map(function(definition) {
32
+ return definition.data.type;
33
+ });
34
+
35
+ $scope.remove = function() {
36
+ this.components.splice(this.components.indexOf(this.component), 1);
37
+ };
38
+
39
+ }]);
40
+ </script>
@@ -0,0 +1,7 @@
1
+ <%
2
+ src = component[:attributes][:src]
3
+ alt = component[:attributes][:alt]
4
+ %>
5
+ <div class="<%= promethee_class_for component %>">
6
+ <img class="img-responsive" src="<%= src %>" alt="<%= alt %>">
7
+ </div>
@@ -0,0 +1,60 @@
1
+ <script type="text/ng-template" id="promethee/components/image">
2
+ <div ng-controller="ImageController" style="position: relative">
3
+ <div dnd-draggable="component"
4
+ dnd-moved="remove()"
5
+ dnd-type="component.type"
6
+ class="promethee-editor__component promethee-editor__component--image promethee-editor__component--final">
7
+ <div class="promethee-editor__toolbar">
8
+ Image
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.src" class="form-control" type="text"/>
15
+ </div>
16
+ <div class="form-group">
17
+ <label class="label-control">Alt</label>
18
+ <input ng-model="component.attributes.alt" class="form-control" type="text"/>
19
+ </div>
20
+ </div>
21
+ <div ng-show="component.attributes.src">
22
+ <img ng-click="edit()" ng-src="{{component.attributes.src}}" class="img-responsive">
23
+ </div>
24
+ <div ng-hide="component.attributes.src">
25
+ <p ng-hide="editing" ng-click="edit()" class="text-center">Click to set the image</p>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </script>
30
+
31
+ <script>
32
+ angular.injector(['ng', '<%= promethee_id %>']).get('definitions').push({
33
+ name: 'Image',
34
+ thumb: 'http://via.placeholder.com/300x200',
35
+ data: {
36
+ type: 'image',
37
+ attributes: {
38
+ src: 'https://source.unsplash.com/random/1920x1080'
39
+ }
40
+ }
41
+ });
42
+
43
+ promethee.controller('ImageController', ['$scope', function($scope) {
44
+
45
+ $scope.editing = false;
46
+
47
+ $scope.edit = function() {
48
+ this.editing = true;
49
+ };
50
+
51
+ $scope.complete = function() {
52
+ this.editing = false;
53
+ };
54
+
55
+ $scope.remove = function() {
56
+ this.components.splice(this.components.indexOf(this.component), 1);
57
+ };
58
+
59
+ }]);
60
+ </script>
@@ -0,0 +1,3 @@
1
+ <% components.each do |component| %>
2
+ <%= render partial: 'promethee/components/show', locals: { component: component } %>
3
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <script type="text/ng-template" id="promethee/components/index">
2
+ <div class="promethee-editor__components" ng-init="components = component.children" dnd-list="components" dnd-allowed-types="allowedTypes">
3
+ <div ng-repeat="component in components">
4
+ <ng-include src="'promethee/components/show'"></ng-include>
5
+ </div>
6
+ </div>
7
+ </script>
@@ -0,0 +1,6 @@
1
+ <%
2
+ children = component[:children]
3
+ %>
4
+ <div class="row <%= promethee_class_for component %>">
5
+ <%= render partial: 'promethee/components/index', locals: { components: children } %>
6
+ </div>
@@ -0,0 +1,53 @@
1
+ <script type="text/ng-template" id="promethee/components/row">
2
+ <div ng-controller="RowController">
3
+ <div class="row">
4
+ <div dnd-draggable="component" dnd-moved="remove()" dnd-type="component.type" class="promethee-editor__component promethee-editor__component--row">
5
+ <div class="promethee-editor__toolbar">
6
+ Row
7
+ <%= render 'promethee/partials/toolbar_buttons' %>
8
+ </div>
9
+ <div ng-show="editing" class="promethee-editor__wrapper">
10
+ Nothing to edit (yet...)
11
+ </div>
12
+
13
+ <ng-include src="'promethee/components/index'"></ng-include>
14
+
15
+ <div class="clearfix"></div>
16
+ <span class="btn btn-default btn-block" ng-click="addColumn()" style="margin: 0 6px 6px 6px;width: auto">Add column</span>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </script>
21
+
22
+ <script>
23
+ angular.injector(['ng', '<%= promethee_id %>']).get('definitions').push({
24
+ name: 'Row',
25
+ thumb: 'http://via.placeholder.com/300x200',
26
+ data: {
27
+ type: 'row',
28
+ attributes: {},
29
+ children: []
30
+ }
31
+ });
32
+
33
+ promethee.controller('RowController', ['$scope', function($scope) {
34
+
35
+ $scope.allowedTypes = ['column'];
36
+
37
+ $scope.addColumn = function() {
38
+ this.component.children.push({
39
+ type: 'column',
40
+ attributes: {
41
+ size: 3,
42
+ offset: 0
43
+ },
44
+ children: []
45
+ })
46
+ }
47
+
48
+ $scope.remove = function() {
49
+ this.components.splice(this.components.indexOf(this.component), 1);
50
+ };
51
+
52
+ }]);
53
+ </script>
@@ -0,0 +1,4 @@
1
+ <%
2
+ type = component[:type]
3
+ %>
4
+ <%= render partial: "promethee/components/#{type}", locals: { component: component } %>
@@ -0,0 +1,3 @@
1
+ <script type="text/ng-template" id="promethee/components/show">
2
+ <ng-include src="'promethee/components/' + component.type"></ng-include>
3
+ </script>
@@ -0,0 +1,6 @@
1
+ <%
2
+ body = component[:attributes][:body].to_s
3
+ %>
4
+ <div class="<%= promethee_class_for component %>">
5
+ <%= body.html_safe %>
6
+ </div>
@@ -0,0 +1,59 @@
1
+ <script type="text/ng-template" id="promethee/components/text">
2
+ <div ng-controller="TextController">
3
+ <div dnd-draggable="component"
4
+ dnd-moved="remove()"
5
+ dnd-type="component.type"
6
+ class="promethee-editor__component promethee-editor__component--text promethee-editor__component--final">
7
+ <div class="promethee-editor__toolbar">
8
+ Text
9
+ <%= render 'promethee/partials/toolbar_buttons' %>
10
+ </div>
11
+ <div ng-show="editing">
12
+ <textarea ui-tinymce="tinymceOptions" ng-model="component.attributes.body"></textarea>
13
+ </div>
14
+ <div ng-hide="editing">
15
+ <div class="promethee-editor__wrapper" ng-bind-html="component.attributes.body | htmlSafe" ng-click="edit()"></div>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </script>
20
+
21
+ <script>
22
+ angular.injector(['ng', '<%= promethee_id %>']).get('definitions').push({
23
+ name: 'Text',
24
+ thumb: 'http://via.placeholder.com/300x200',
25
+ data: {
26
+ type: 'text',
27
+ attributes: {
28
+ body: 'Edit me'
29
+ }
30
+ }
31
+ });
32
+
33
+ promethee.controller('TextController', ['$scope', function($scope) {
34
+
35
+ $scope.editing = false;
36
+
37
+ $scope.edit = function() {
38
+ this.editing = true;
39
+ };
40
+
41
+ $scope.complete = function() {
42
+ this.editing = false;
43
+ };
44
+
45
+ $scope.remove = function() {
46
+ this.components.splice(this.components.indexOf(this.component), 1);
47
+ };
48
+
49
+ $scope.tinymceOptions = {
50
+ plugins: 'autoresize',
51
+ toolbar: 'styleselect | bold italic',
52
+ menubar: false,
53
+ statusbar: false,
54
+ branding: false,
55
+ autoresize_bottom_margin: 0
56
+ };
57
+
58
+ }]);
59
+ </script>