icentris-rules 0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +33 -0
  5. data/app/assets/images/pyr_rules/ui-anim_basic_16x16.gif +0 -0
  6. data/app/assets/javascripts/pyr_rules/rules.js +135 -0
  7. data/app/assets/stylesheets/pyr_rules/rules.css.scss +258 -0
  8. data/app/assets/stylesheets/scaffold.css +57 -0
  9. data/app/controllers/pyr_rules/actions_controller.rb +22 -0
  10. data/app/controllers/pyr_rules/events_controller.rb +17 -0
  11. data/app/controllers/pyr_rules/rules_controller.rb +233 -0
  12. data/app/helpers/pyr_rules/actions_helper.rb +2 -0
  13. data/app/helpers/pyr_rules/events_helper.rb +95 -0
  14. data/app/helpers/pyr_rules/rules_helper.rb +10 -0
  15. data/app/models/pyr_rules.rb +3 -0
  16. data/app/models/pyr_rules/action.rb +116 -0
  17. data/app/models/pyr_rules/rule.rb +201 -0
  18. data/app/rules/pyr_rules/action_handler.rb +94 -0
  19. data/app/rules/pyr_rules/controller_event_emitter.rb +34 -0
  20. data/app/rules/pyr_rules/email_action_handler.rb +6 -0
  21. data/app/rules/pyr_rules/event_concerns.rb +23 -0
  22. data/app/rules/pyr_rules/event_config_loader.rb +97 -0
  23. data/app/rules/pyr_rules/event_subscriber.rb +36 -0
  24. data/app/rules/pyr_rules/model_creation_handler.rb +25 -0
  25. data/app/rules/pyr_rules/model_event_emitter.rb +80 -0
  26. data/app/rules/pyr_rules/rule_context.rb +20 -0
  27. data/app/rules/pyr_rules/rules_config.rb +87 -0
  28. data/app/rules/pyr_rules/rules_engine.rb +38 -0
  29. data/app/rules/pyr_rules/web_request_logger.rb +6 -0
  30. data/app/views/pyr_rules/actions/index.html.erb +12 -0
  31. data/app/views/pyr_rules/events/_sidebar.html.erb +8 -0
  32. data/app/views/pyr_rules/events/index.html.erb +72 -0
  33. data/app/views/pyr_rules/events/show.html.erb +11 -0
  34. data/app/views/pyr_rules/rules/_form.html.erb +28 -0
  35. data/app/views/pyr_rules/rules/_ready_headers.js.erb +11 -0
  36. data/app/views/pyr_rules/rules/_rule_context_field.html.erb +10 -0
  37. data/app/views/pyr_rules/rules/_rules.html.erb +34 -0
  38. data/app/views/pyr_rules/rules/add_action_mapping.js.erb +13 -0
  39. data/app/views/pyr_rules/rules/edit.html.erb +14 -0
  40. data/app/views/pyr_rules/rules/index.html.erb +5 -0
  41. data/app/views/pyr_rules/rules/lookup_sub_properties.js.erb +13 -0
  42. data/app/views/pyr_rules/rules/new.html.erb +11 -0
  43. data/app/views/pyr_rules/rules/remove_action_mapping.js.erb +15 -0
  44. data/app/views/pyr_rules/rules/show.html.erb +98 -0
  45. data/app/views/shared/_action.html.erb +41 -0
  46. data/app/views/shared/_action_field_mapping.html.erb +33 -0
  47. data/app/views/shared/_event.html.erb +21 -0
  48. data/app/views/shared/_rule.html.erb +27 -0
  49. data/config/routes.rb +32 -0
  50. data/config/security.yml +9 -0
  51. data/db/seeds.rb +1 -0
  52. data/lib/pyr_rules.rb +34 -0
  53. data/lib/pyr_rules/engine.rb +72 -0
  54. data/lib/pyr_rules/generators/dummy_generator.rb +27 -0
  55. data/lib/pyr_rules/version.rb +3 -0
  56. data/lib/tasks/pyr_rules_tasks.rake +57 -0
  57. metadata +224 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YjUwY2I4MjhjOTViNWVjZWE2NTdiMjBhNjVhMTJjNmNkNjgyYjJmNQ==
5
+ data.tar.gz: !binary |-
6
+ MWIzYjI5NDdlNGM0OTczYzdiOGI5ZTc5YTU4MDkwNzM3MjBlNjNkMA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZmQ5YzQ3OTAxM2I1NWI3OTg0YjZiMDgyZDMyNTgzZDNlYmRiZGMxNDQzMGNk
10
+ YzYyZDlkN2JkZmM2Nzk3YzU1ODFiMjlkZTk2M2E0YmQyMTFjYWMyODZlYWE5
11
+ M2UxYWU1NjIwNjkwNzVlNTNlZTIyMDZjM2ZjOGJlNjI2ODYzZGM=
12
+ data.tar.gz: !binary |-
13
+ N2RiNmM0OTZmZWJjMThiYmQzZTlmNjM3YmUxYTE0YTc1MWEwOWE5ODAzNjc1
14
+ NjlmODczZDhhN2FkNWE0ZjUzNGVlMDc0Nzk5YTVjZTBkYmRlNzJjMmFjMDM5
15
+ OWE5MzM3MmJlNDRiYmIwZGY2ZDk3ZGQxZDNkNjY0ZGMyZGVhMzQ=
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
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,3 @@
1
+ = Rules
2
+
3
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,33 @@
1
+ puts "...Rakefile"
2
+ #!/usr/bin/env rake
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.pattern = File.expand_path('../spec/**/*_spec.rb', __FILE__)
7
+ end
8
+
9
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
10
+ load 'rails/tasks/engine.rake'
11
+
12
+ task :default => :spec
13
+
14
+ # desc 'Generates a dummy app for testing'
15
+ # task :dummy_app => [:setup, :migrate]
16
+
17
+ # task :setup do
18
+ # require 'rails'
19
+ # require 'pyr_rules'
20
+ # require 'pyr_rules/generators/dummy_generator'
21
+
22
+ # dummy = File.expand_path('../spec/dummy', __FILE__)
23
+ # sh "rm -rf #{dummy}"
24
+ # MyEngine::DummyGenerator.start(
25
+ # %W(. --quiet --force --skip-bundle --old-style-hash --dummy-path=#{dummy})
26
+ # )
27
+ # end
28
+
29
+ # task :migrate do
30
+ # rakefile = File.expand_path('../spec/dummy/Rakefile', __FILE__)
31
+ # sh("rake -f #{rakefile} pyr_rules_engine:install:migrations")
32
+ # sh("rake -f #{rakefile} db:create db:migrate db:test:prepare")
33
+ # end
@@ -0,0 +1,135 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
3
+
4
+ var droppableConfiguration = {
5
+ accept: ".context-draggable",
6
+ activeClass: "ui-state-hover",
7
+ hoverClass: "ui-state-active",
8
+ drop: function( event, ui ) {
9
+ var rule_id = $(this).attr("data-rule-id");
10
+ var action_id = $(this).attr("data-action-id");
11
+ var field_type = ui.draggable.attr("data-fieldtype");
12
+ var rule_field = ui.draggable.attr("data-fieldname") + ":" + ui.draggable.attr("data-fieldtype");
13
+ var action_field = $(this).attr("data-fieldname") + ":" + $(this).attr("data-fieldtype");
14
+ add_action_mapping( action_id, action_field, rule_field, field_type );
15
+ }
16
+ };
17
+
18
+ $(function() {
19
+ $( ".context-draggable" ).draggable({
20
+ cursor: "move",
21
+ cursorAt: { top: -2, left: -20 },
22
+ containment: $("#main-content").parent(),
23
+ helper: function( event ) {
24
+ return $( "<div style='color:black;'>" + $(this).html() + "</div>" );
25
+ }});
26
+
27
+ $( ".context-droppable" ).droppable( droppableConfiguration );
28
+
29
+ $( "#event_lookup_autocomplete" )
30
+ // don't navigate away from the field on tab when selecting an item
31
+ .bind( "keydown", function( event ) {
32
+ if ( event.keyCode === $.ui.keyCode.TAB &&
33
+ $( this ).data( "ui-autocomplete" ).menu.active ) {
34
+ event.preventDefault();
35
+ }
36
+ })
37
+ .autocomplete({
38
+ source: function( request, response ) {
39
+ $.getJSON( "/pyr_rules/rules/lookup_events.json", {
40
+ q: extractLast( request.term )
41
+ }, response );
42
+ },
43
+ search: function() {
44
+ // custom minLength
45
+ var q = extractLast( this.value );
46
+ if ( q.length < 2 ) {
47
+ return false;
48
+ }
49
+ },
50
+ focus: function() {
51
+ // prevent value inserted on focus
52
+ return false;
53
+ },
54
+ select: function( event, ui ) {
55
+ url = "/pyr_rules/rules/" + rule_id + "/add_event?event=" + ui.item.id;
56
+ window.location.replace(url);
57
+ return false;
58
+
59
+ }
60
+ });
61
+
62
+
63
+ $( "#action_lookup_autocomplete" )
64
+ // don't navigate away from the field on tab when selecting an item
65
+ .bind( "keydown", function( event ) {
66
+ if ( event.keyCode === $.ui.keyCode.TAB &&
67
+ $( this ).data( "ui-autocomplete" ).menu.active ) {
68
+ event.preventDefault();
69
+ }
70
+ })
71
+ .autocomplete({
72
+ source: function( request, response ) {
73
+ $.getJSON( "/pyr_rules/rules/lookup_actions.json", {
74
+ q: extractLast( request.term )
75
+ }, response );
76
+ },
77
+ search: function() {
78
+ // custom minLength
79
+ var q = extractLast( this.value );
80
+ if ( q.length < 2 ) {
81
+ return false;
82
+ }
83
+ },
84
+ focus: function() {
85
+ // prevent value inserted on focus
86
+ return false;
87
+ },
88
+ select: function( event, ui ) {
89
+ url = "/pyr_rules/rules/" + rule_id + "/add_action?action_class=" + ui.item.id;
90
+ window.location.replace(url);
91
+ return false;
92
+
93
+ }
94
+ });
95
+ });
96
+
97
+ function add_action_mapping(action_id, action_field, rule_field, field_type) {
98
+ if (field_type=="class_lookup") {
99
+ window.location = "/pyr_rules/rules/" + rule_id + "/add_action_mapping?action_id=" +
100
+ action_id + "&rule_field=" + rule_field + "&action_field=" + action_field
101
+
102
+ } else {
103
+ $.ajax({
104
+ url: "/pyr_rules/rules/" + rule_id + "/add_action_mapping.js?action_id=" +
105
+ action_id + "&rule_field=" + rule_field + "&action_field=" + action_field
106
+ });
107
+ }
108
+ }
109
+
110
+ function remove_action_mapping(actionId, fieldName, fieldType) {
111
+ if (fieldType=="class_lookup") {
112
+ window.location = "/pyr_rules/rules/" + rule_id + "/remove_action_mapping?action_id=" +
113
+ actionId + "&action_field=" + fieldName +":" + fieldType
114
+
115
+ } else {
116
+ $.ajax({
117
+ url:"/pyr_rules/rules/" + rule_id + "/remove_action_mapping.js?action_id=" +
118
+ actionId + "&action_field=" + fieldName +":" + fieldType
119
+ });
120
+ }
121
+ }
122
+
123
+ function remove_sub_properties(div_selector) {
124
+ $("#rule_field_" + div_selector).children(".context-draggable").remove();
125
+ $("#expand_link_" + div_selector).toggleClass("hidden");
126
+ $("#collapse_link_" + div_selector).toggleClass("hidden");
127
+ }
128
+
129
+ function split( val ) {
130
+ return val.split( /,\s*/ );
131
+ }
132
+ function extractLast( term ) {
133
+ return split( term ).pop();
134
+ }
135
+
@@ -0,0 +1,258 @@
1
+ $rules-widget-color-danger: #993333;
2
+ $rules-widget-color-danger-lighten: lighten($rules-widget-color-danger, 20);
3
+ $rules-widget-color-success: #336633;
4
+ $rules-widget-color-success-lighten: lighten($rules-widget-color-success, 20);
5
+ $rules-widget-color-success-darken: $rules-widget-color-success;
6
+ $rules-widget-color-draggable: #00a3e0;
7
+ $rules-widget-color-inverse-text: #fff;
8
+
9
+ #rules-manager {
10
+ border-collapse: collapse;
11
+ display: table;
12
+ width: 100%;
13
+
14
+ .row {
15
+ display: table-row;
16
+ margin: 0;
17
+
18
+ .col-md-4 {
19
+ display: table-cell;
20
+ background-color: #eee;
21
+ border-left: 1px solid #000;
22
+ border-right: 1px solid #000;
23
+ float: none;
24
+ width: 33%;
25
+
26
+ &:nth-child(even) {
27
+ background-color: #ddd;
28
+ }
29
+
30
+ &:first-child {
31
+ .rules-widget {
32
+ .context {
33
+ background-color: #fff;
34
+ color: #000;
35
+ }
36
+
37
+ .title {
38
+ color: #000;
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ .rule-widget-header {
47
+ position:relative;
48
+ margin-bottom:10px;
49
+ height:75px;
50
+ text-align:center;
51
+ }
52
+
53
+ .rule-widget-autocomplete {
54
+ position:absolute;
55
+ bottom:0px;
56
+ left:0px;
57
+ width:350px;
58
+ }
59
+
60
+
61
+ .rules-widget {
62
+ background-color: #bbb;
63
+ padding: 5px;
64
+ margin: 0px 10px 20px;
65
+ border-radius: 5px;
66
+ border: 1px solid rgba(0, 0, 0, 0.1);
67
+ position: relative;
68
+ min-width: 250px;
69
+ max-width: 95%;
70
+
71
+ .out_arrow {
72
+ color: #999;
73
+ font-size: 36px;
74
+ line-height: 36px;
75
+ text-shadow: 1px 1px rgba(0, 0, 0, 0.5);
76
+ position: absolute;
77
+ right: -40px;
78
+ top: 0px;
79
+ z-index: 100;
80
+ }
81
+
82
+ .in_arrow {
83
+ position: absolute;
84
+ top: 0px;
85
+ left: -42px;
86
+ text-shadow: 1px 1px rgba(0, 0, 0, 0.5);
87
+ font-size: 36px;
88
+ line-height: 36px;
89
+ color:#999;
90
+ }
91
+
92
+ .title {
93
+ margin:5px 0px 10px 5px;
94
+ font-weight: bold;
95
+ font-size: 16px;
96
+ color: $rules-widget-color-danger;
97
+
98
+ &.ready {
99
+ color: $rules-widget-color-success;
100
+ }
101
+
102
+ text {
103
+ max-width:440px;
104
+ margin:0 5 10;
105
+ width:100%;
106
+ }
107
+ }
108
+
109
+ .criteria {
110
+ min-height:60px;
111
+ max-height:200px;
112
+ max-width:440px;
113
+ margin:0 5 10;
114
+ width:100%;
115
+ }
116
+
117
+
118
+ .classname {
119
+ display: none;
120
+ color:white;
121
+ font-style:italic;
122
+ padding-left: 5px;
123
+ position:absolute;
124
+ bottom:2px;
125
+ width:100%;
126
+ }
127
+
128
+ .collapse-group {
129
+ margin-top:-10px;
130
+
131
+ .in {
132
+ margin-top: 15px;
133
+ }
134
+
135
+ a {
136
+ color: $rules-widget-color-inverse-text;
137
+
138
+ &.collapse-context {
139
+ position: absolute;
140
+ top: 10px;
141
+ right: 30px;
142
+ }
143
+ }
144
+ }
145
+
146
+ .action-links {
147
+ position: absolute;
148
+ top: 8px;
149
+ right: 10px;
150
+ z-index: 100;
151
+
152
+ &.btn {
153
+ top: 4px;
154
+ }
155
+
156
+ a {
157
+ color: $rules-widget-color-danger;
158
+ font-size: 1.2em;
159
+ }
160
+
161
+ button {
162
+ margin-top: 3px;
163
+ }
164
+ }
165
+
166
+ .context {
167
+ background-color: $rules-widget-color-draggable;
168
+ border: 1px solid rgba(0, 0, 0, 0.1);
169
+ border-radius: 3px;
170
+ color: $rules-widget-color-inverse-text;
171
+ margin: 3px;
172
+ padding: 5px;
173
+
174
+ .context:not(.used) {
175
+ border: 0;
176
+ }
177
+
178
+ .source-mapping {
179
+ color: #fff;
180
+ padding: 2px;
181
+ }
182
+
183
+ &.ui-state-hover {
184
+ color: #000;
185
+
186
+ &.ui-state-active {
187
+ background-color: $rules-widget-color-draggable;
188
+ }
189
+ }
190
+
191
+ &.ui-draggable {
192
+ cursor: default;
193
+ }
194
+ }
195
+
196
+ .used {
197
+ background-color: $rules-widget-color-success-lighten;
198
+
199
+ > .context:not(.used) {
200
+ border: 1px solid rgba(0, 0, 0, 0.1);
201
+ }
202
+ }
203
+
204
+ .unavailable {
205
+ background-color:#888;
206
+ text-decoration:line-through;
207
+ }
208
+
209
+ .needs-mapping {
210
+ background-color: $rules-widget-color-danger-lighten;
211
+ }
212
+
213
+ .action-context-mapped {
214
+ color: #fff;
215
+ background-color: $rules-widget-color-success-lighten;
216
+ padding: 5px 20px 5px 5px
217
+ }
218
+
219
+ .text-area {
220
+ position:relative;
221
+ background-color: #eee;
222
+ border-radius: 3px;
223
+ margin:10px 5px 0px;
224
+ padding:7px;
225
+
226
+ .name {
227
+ font-size: 14px;
228
+ font-weight:bold;
229
+ line-height: 35px;
230
+ padding-left: 5px;
231
+ }
232
+
233
+ textarea {
234
+ text-align: left;
235
+ width:100%;
236
+ padding:5px;
237
+ font-size:1.2em;
238
+ }
239
+ }
240
+ }
241
+
242
+ .ui-widget-content {
243
+ background-color:azure !important;
244
+ }
245
+ .ui-autocomplete {
246
+ z-index: 1150;
247
+ }
248
+
249
+ .ui-autocomplete-loading {
250
+ background: white url('/assets/pyr_rules/ui-anim_basic_16x16.gif') right center no-repeat;
251
+ }
252
+
253
+ .delete-source-mapping {
254
+ position: absolute;
255
+ right: 5px;
256
+ color: $rules-widget-color-danger;
257
+ cursor: pointer;
258
+ }