zena 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. data/History.txt +38 -1
  2. data/app/controllers/documents_controller.rb +7 -5
  3. data/app/controllers/nodes_controller.rb +47 -6
  4. data/app/controllers/user_sessions_controller.rb +12 -3
  5. data/app/controllers/virtual_classes_controller.rb +8 -2
  6. data/app/models/acl.rb +5 -2
  7. data/app/models/cached_page.rb +5 -5
  8. data/app/models/column.rb +27 -4
  9. data/app/models/group.rb +1 -1
  10. data/app/models/node.rb +106 -24
  11. data/app/models/note.rb +2 -1
  12. data/app/models/relation.rb +9 -4
  13. data/app/models/relation_proxy.rb +2 -2
  14. data/app/models/role.rb +12 -5
  15. data/app/models/site.rb +10 -9
  16. data/app/models/skin.rb +8 -0
  17. data/app/models/string_hash.rb +65 -0
  18. data/app/models/text_document.rb +1 -1
  19. data/app/models/user.rb +2 -0
  20. data/app/models/virtual_class.rb +43 -10
  21. data/app/views/comments/create.rjs +1 -32
  22. data/app/views/comments/edit.rjs +1 -1
  23. data/app/views/comments/update.rjs +1 -1
  24. data/app/views/documents/show.rhtml +1 -1
  25. data/app/views/groups/_form.rhtml +7 -0
  26. data/app/views/groups/_li.rhtml +1 -1
  27. data/app/views/nodes/500.html +2 -1
  28. data/app/views/nodes/destroy.rjs +2 -0
  29. data/app/views/sites/jobs.erb +2 -3
  30. data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
  31. data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
  32. data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
  33. data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
  34. data/app/views/versions/custom_tab.rhtml +1 -1
  35. data/app/views/versions/edit.rhtml +1 -1
  36. data/bricks/acls/lib/bricks/acls.rb +3 -3
  37. data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
  38. data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
  39. data/bricks/fs_skin/zena/init.rb +1 -0
  40. data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
  41. data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
  42. data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
  43. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
  44. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
  45. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
  46. data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
  47. data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
  48. data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
  49. data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
  50. data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
  51. data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
  52. data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
  53. data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
  54. data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
  55. data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
  56. data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
  57. data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
  58. data/bricks/fs_skin/zena/tasks.rb +26 -0
  59. data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
  60. data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
  61. data/bricks/grid/lib/bricks/grid.rb +4 -3
  62. data/bricks/tags/lib/bricks/tags.rb +1 -7
  63. data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
  64. data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
  65. data/config/bricks.yml +3 -3
  66. data/config/gems.yml +2 -3
  67. data/lib/tasks/zena.rake +7 -3
  68. data/lib/zafu.rb +7 -0
  69. data/lib/zafu/all.rb +21 -0
  70. data/lib/zafu/compiler.rb +7 -0
  71. data/lib/zafu/controller_methods.rb +58 -0
  72. data/lib/zafu/handler.rb +57 -0
  73. data/lib/zafu/info.rb +4 -0
  74. data/lib/zafu/markup.rb +309 -0
  75. data/lib/zafu/mock_helper.rb +42 -0
  76. data/lib/zafu/node_context.rb +203 -0
  77. data/lib/zafu/ordered_hash.rb +53 -0
  78. data/lib/zafu/parser.rb +676 -0
  79. data/lib/zafu/parsing_rules.rb +382 -0
  80. data/lib/zafu/process/ajax.rb +530 -0
  81. data/lib/zafu/process/conditional.rb +92 -0
  82. data/lib/zafu/process/context.rb +186 -0
  83. data/lib/zafu/process/forms.rb +143 -0
  84. data/lib/zafu/process/html.rb +186 -0
  85. data/lib/zafu/process/ruby_less_processing.rb +321 -0
  86. data/lib/zafu/security.rb +15 -0
  87. data/lib/zafu/template.rb +25 -0
  88. data/lib/zafu/test_helper.rb +19 -0
  89. data/lib/zafu/view_methods.rb +6 -0
  90. data/lib/zena.rb +1 -1
  91. data/lib/zena/acts/enrollable.rb +1 -1
  92. data/lib/zena/app.rb +4 -17
  93. data/lib/zena/console.rb +18 -1
  94. data/lib/zena/core_ext/file_utils.rb +13 -1
  95. data/lib/zena/core_ext/fixnum.rb +4 -0
  96. data/lib/zena/core_ext/float.rb +7 -0
  97. data/lib/zena/deploy.rb +4 -2
  98. data/lib/zena/deploy/app_init.rhtml +2 -1
  99. data/lib/zena/deploy/database.rhtml +1 -1
  100. data/lib/zena/info.rb +1 -1
  101. data/lib/zena/parser/zazen_rules.rb +4 -4
  102. data/lib/zena/routes.rb +1 -1
  103. data/lib/zena/test_controller.rb +1 -1
  104. data/lib/zena/use.rb +14 -1
  105. data/lib/zena/use/action.rb +4 -2
  106. data/lib/zena/use/ajax.rb +86 -38
  107. data/lib/zena/use/authlogic.rb +16 -1
  108. data/lib/zena/use/calendar.rb +37 -17
  109. data/lib/zena/use/conditional.rb +2 -2
  110. data/lib/zena/use/context.rb +30 -9
  111. data/lib/zena/use/dates.rb +39 -3
  112. data/lib/zena/use/display.rb +6 -19
  113. data/lib/zena/use/forms.rb +100 -79
  114. data/lib/zena/use/i18n.rb +40 -16
  115. data/lib/zena/use/query_builder.rb +0 -6
  116. data/lib/zena/use/query_node.rb +17 -4
  117. data/lib/zena/use/relations.rb +1 -3
  118. data/lib/zena/use/rendering.rb +10 -8
  119. data/lib/zena/use/scope_index.rb +5 -1
  120. data/lib/zena/use/search.rb +2 -1
  121. data/lib/zena/use/urls.rb +82 -77
  122. data/lib/zena/use/workflow.rb +12 -4
  123. data/lib/zena/use/zafu_safe_definitions.rb +37 -9
  124. data/lib/zena/use/zafu_templates.rb +49 -20
  125. data/lib/zena/use/zazen.rb +6 -2
  126. data/locale/it/LC_MESSAGES/zena.mo +0 -0
  127. data/locale/it/zena.mo +0 -0
  128. data/locale/it/zena.po +1982 -0
  129. data/public/images/arrow_back.png +0 -0
  130. data/public/images/remove_tag.png +0 -0
  131. data/public/javascripts/grid.js +800 -199
  132. data/public/javascripts/window.js +1 -1
  133. data/public/javascripts/zena.js +130 -21
  134. data/public/stylesheets/grid.css +11 -2
  135. data/public/stylesheets/zena.css +2 -1
  136. data/test/custom_queries/complex.host.yml +5 -0
  137. data/test/fixtures/files/TestNode.zafu +36 -0
  138. data/test/functional/nodes_controller_test.rb +18 -1
  139. data/test/integration/zafu_compiler/action.yml +2 -2
  140. data/test/integration/zafu_compiler/ajax.yml +44 -26
  141. data/test/integration/zafu_compiler/asset.yml +12 -2
  142. data/test/integration/zafu_compiler/basic.yml +0 -16
  143. data/test/integration/zafu_compiler/calendar.yml +6 -6
  144. data/test/integration/zafu_compiler/complex_ok.yml +23 -1
  145. data/test/integration/zafu_compiler/conditional.yml +5 -5
  146. data/test/integration/zafu_compiler/context.yml +6 -5
  147. data/test/integration/zafu_compiler/dates.yml +23 -2
  148. data/test/integration/zafu_compiler/display.yml +46 -2
  149. data/test/integration/zafu_compiler/errors.yml +2 -2
  150. data/test/integration/zafu_compiler/eval.yml +35 -7
  151. data/test/integration/zafu_compiler/forms.yml +47 -13
  152. data/test/integration/zafu_compiler/i18n.yml +2 -2
  153. data/test/integration/zafu_compiler/meta.yml +35 -1
  154. data/test/integration/zafu_compiler/query.yml +23 -4
  155. data/test/integration/zafu_compiler/relations.yml +10 -6
  156. data/test/integration/zafu_compiler/roles.yml +4 -4
  157. data/test/integration/zafu_compiler/rubyless.yml +11 -1
  158. data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
  159. data/test/integration/zafu_compiler/security.yml +10 -6
  160. data/test/integration/zafu_compiler/urls.yml +23 -6
  161. data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
  162. data/test/integration/zafu_compiler/zazen.yml +14 -0
  163. data/test/selenium/Add/add3.rsel +8 -8
  164. data/test/selenium/Destroy/0setup.rsel +12 -0
  165. data/test/selenium/Destroy/destroy1.rsel +16 -0
  166. data/test/selenium/Edit/edit2.rsel +9 -9
  167. data/test/selenium/Edit/edit5.rsel +9 -9
  168. data/test/selenium/Edit/edit6.rsel +9 -9
  169. data/test/selenium/Form/form4.rsel +17 -0
  170. data/test/selenium/Toggle/toggle1.rsel +2 -0
  171. data/test/selenium/Toggle/toggle2.rsel +18 -0
  172. data/test/sites/zena/columns.yml +3 -0
  173. data/test/sites/zena/versions.yml +7 -0
  174. data/test/unit/cached_page_test.rb +13 -13
  175. data/test/unit/column_test.rb +26 -0
  176. data/test/unit/node_test.rb +16 -1
  177. data/test/unit/project_test.rb +6 -1
  178. data/test/unit/relation_test.rb +1 -1
  179. data/test/unit/role_test.rb +1 -1
  180. data/test/unit/string_hash_test.rb +30 -0
  181. data/test/unit/virtual_class_test.rb +31 -17
  182. data/test/unit/zafu_markup_test.rb +414 -0
  183. data/test/unit/zafu_node_context_test.rb +375 -0
  184. data/test/unit/zafu_ordered_hash_test.rb +69 -0
  185. data/test/unit/zena/acts/enrollable_test.rb +1 -1
  186. data/test/unit/zena/parser/zafu_asset.yml +0 -10
  187. data/test/unit/zena/parser/zazen.yml +1 -1
  188. data/test/unit/zena/parser_test.rb +1 -72
  189. data/test/unit/zena/use/dates_test.rb +1 -1
  190. data/test/unit/zena/use/rendering_test.rb +24 -7
  191. data/test/unit/zena/use/scope_index_test.rb +17 -0
  192. data/test/unit/zena/use/zazen_test.rb +2 -1
  193. data/zena.gemspec +71 -37
  194. metadata +104 -83
  195. data/app/views/nodes/destroy.erb +0 -0
  196. data/bricks/static/lib/bricks/static.rb +0 -151
  197. data/bricks/static/zena/init.rb +0 -1
  198. data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
  199. data/bricks/static/zena/test/unit/static_test.rb +0 -33
  200. data/lib/zena/parser/zafu_rules.rb +0 -244
  201. data/lib/zena/parser/zafu_tags.rb +0 -198
  202. data/lib/zena/parser/zena_rules.rb +0 -23
@@ -1227,7 +1227,7 @@ var Windows = {
1227
1227
  modalWindows: [],
1228
1228
  observers: [],
1229
1229
  focusedWindow: null,
1230
- maxZIndex: 0,
1230
+ maxZIndex: 100,
1231
1231
  overlayShowEffectOptions: {duration: 0.5},
1232
1232
  overlayHideEffectOptions: {duration: 0.5},
1233
1233
 
@@ -30,7 +30,7 @@ Zena.open_window = function(url, id, event, pos_x, pos_y) {
30
30
  }
31
31
  // edit window, not in an iframe
32
32
  if (event && (event == true || event.shiftKey || (window == window.parent && window.current_sel))) {
33
- var popup = window.open(url, name, 'location=0,width=300,height=400,resizable=1');
33
+ var popup = window.open(url, id, 'location=0,width=300,height=400,resizable=1');
34
34
  if (pos_x && pos_y) {
35
35
  popup.moveTo(pos_x, pos_y);
36
36
  } else {
@@ -59,13 +59,8 @@ Zena.open_window = function(url, id, event, pos_x, pos_y) {
59
59
  pos_y = 0;
60
60
  }
61
61
  } else {
62
- if (Zena.window_offset) {
63
- Zena.window_offset = Zena.window_offset + 15;
64
- } else {
65
- Zena.window_offset = 15;
66
- }
67
- pos_x = Zena.window_offset;
68
- pos_y = Zena.window_offset;
62
+ pos_x = event.x - 12;
63
+ pos_y = event.y - 12;
69
64
  }
70
65
 
71
66
  var win = new Window({
@@ -93,7 +88,13 @@ Zena.open_window = function(url, id, event, pos_x, pos_y) {
93
88
  Zena.editor_preview = function(url, element, value) {
94
89
  var key = element.name;
95
90
  var full_url = url + '?key=' + key.slice(5, key.length - 1);
96
- new Ajax.Request(full_url, {method:'get', asynchronous:true, evalScripts:true, parameters:{content: value }});
91
+ new Ajax.Request(full_url, {
92
+ // value too large for get.
93
+ method:'post',
94
+ asynchronous:true,
95
+ evalScripts:true,
96
+ parameters:{content: value}
97
+ });
97
98
  }
98
99
 
99
100
  // preview version.
@@ -654,11 +655,7 @@ Zena.popup_keydown = function(evt) {
654
655
  var gallery = Zena.popup_gallery;
655
656
 
656
657
  var code = evt.keyCode;
657
- //if (!e) var e = window.event;
658
- //if (e.keyCode) code = e.keyCode;
659
- //else if (e.which) code = e.which;
660
658
  var character = String.fromCharCode(code);
661
- //alert('Character was ' + character);
662
659
 
663
660
  if (code == Event.KEY_LEFT) {
664
661
  if (gallery.prev) {
@@ -720,7 +717,6 @@ Zena.popup = function(elem) {
720
717
  Event.observe(document.body, 'keydown', function(e) {
721
718
  var evt = e || window.event;
722
719
  $('pg_info').innerHTML = evt.keyCode;
723
- //alert('key :' + evt.keyCode);
724
720
  });
725
721
  }
726
722
  if (!this.popup_gallery || this.popup_gallery.klass != config.klass) {
@@ -875,7 +871,8 @@ Zena.toggle = function(elem, definition, id) {
875
871
  onSuccess: function() {
876
872
  definition['list'] = definition['list'].without(id);
877
873
  Zena.set_toggle(elem.id, definition);
878
- }
874
+ if (definition['js']) definition['js'](elem);
875
+ }
879
876
  });
880
877
  } else {
881
878
  // turn on
@@ -885,8 +882,21 @@ Zena.toggle = function(elem, definition, id) {
885
882
  evalScripts:true,
886
883
  parameters: 'node[' + definition['role'] + '_id]=' + id,
887
884
  onSuccess: function() {
885
+ if (definition['arity'] == 'one') {
886
+ // uncheck all
887
+ definition['list'] = {};
888
+ // search for siblings
889
+ elem.siblings().each(function(s) {
890
+ try {
891
+ s.select('input.cb')[0].checked = false;
892
+ s.removeClassName('on');
893
+ s.addClassName('off');
894
+ } catch (err) {}
895
+ });
896
+ }
888
897
  definition['list'].push(id);
889
898
  Zena.set_toggle(elem.id, definition);
899
+ if (definition['js']) definition['js'](elem);
890
900
  }
891
901
  });
892
902
  }
@@ -904,8 +914,8 @@ Zena.m_toggle = function(id) {
904
914
 
905
915
  var pm_counter = 1;
906
916
  Zena.plus_minus = function(elem, start, plus, minus) {
907
- plus = plus == undefined ? '[+]' : plus;
908
- minus = minus == undefined ? '[-]' : minus;
917
+ var plus = plus == undefined ? '[+]' : plus;
918
+ var minus = minus == undefined ? '[-]' : minus;
909
919
 
910
920
  var tag = elem.tagName;
911
921
  pm_counter = pm_counter + 1;
@@ -913,12 +923,15 @@ Zena.plus_minus = function(elem, start, plus, minus) {
913
923
  var show = start == 'on' ? 'display:none;' : '';
914
924
  var hide = start == 'on' ? '' : 'display:none;';
915
925
  var trigger_tag = " <a id='off_"+id+"' style='"+show+"' onclick='Zena.m_toggle(\"" + id +"\")' class='plus_btn'>"+plus+"</a><a id='on_"+id+"' style='"+hide+"' onclick='Zena.m_toggle(\"" + id +"\")' class='minus_btn'>"+minus+"</a>";
916
- var new_tag = "<"+tag+" style='"+hide+"' id='txt_"+id+"' class='txt" + ' ' + elem.className + "'>" + elem.innerHTML + "</"+tag+">";
917
926
  if (tag.toUpperCase() == 'SPAN' || !elem.previous()) {
918
- Element.replace(elem, trigger_tag + ' ' + new_tag);
927
+ Element.insert(elem, {before:trigger_tag});
919
928
  } else {
920
929
  Element.insert(elem.previous(), {bottom:trigger_tag});
921
- Element.replace(elem, new_tag);
930
+ }
931
+ elem.addClassName('txt')
932
+ elem.id = 'txt_'+id
933
+ if (start != 'on') {
934
+ elem.setStyle({display:'none'})
922
935
  }
923
936
  }
924
937
 
@@ -954,4 +967,100 @@ Zena.insert_inner = function(dom, position, content) {
954
967
  var insertions = {};
955
968
  insertions[position] = d.childElements()[0].innerHTML;
956
969
  Element.insert(dom, insertions);
957
- }
970
+ }
971
+
972
+ Zena.prepare_query = function(data, base, res) {
973
+ var res = res || {}
974
+ // transform {node:{a:'b'}} into {'node[a]':'b'}
975
+ $H(data).each(function(pair) {
976
+ var key = pair.key
977
+ var val = pair.value
978
+ if (base) {
979
+ key = base+'['+key+']'
980
+ }
981
+ if (typeof(val) == 'object') {
982
+ Zena.prepare_query(val, key, res)
983
+ } else {
984
+ res[key] = val
985
+ }
986
+ })
987
+ return res
988
+ }
989
+
990
+ Zena.do = function(method, dom, query) {
991
+ var dom = $(dom)
992
+
993
+ var zip
994
+ if (typeof(query) == 'string') {
995
+ query = {id:query}
996
+ }
997
+ if (query.id) {
998
+ zip = query.id
999
+ delete query.id
1000
+ } else {
1001
+ zip = dom.getAttribute('data-z')
1002
+ }
1003
+
1004
+ var url
1005
+ if (method == 'get') {
1006
+ url = '/nodes/' + zip + '/zafu'
1007
+ } else if (method == 'post') {
1008
+ url = '/nodes'
1009
+ } else {
1010
+ // put
1011
+ url = '/nodes/' + zip
1012
+ }
1013
+
1014
+ if (Object.prototype.toString.apply(query) === '[object Array]') {
1015
+ var list = query
1016
+ var todo = list.length
1017
+ for (var i=0; i < list.length; i++) {
1018
+ new Ajax.Request(url, {
1019
+ method:method,
1020
+ parameters:Zena.prepare_query(list[i]),
1021
+ asynchronous:true,
1022
+ onSuccess: function() {
1023
+ todo--;
1024
+ if (todo == 0) {
1025
+ Zena.reload(dom)
1026
+ }
1027
+ },
1028
+ onFailure: function() {
1029
+ alert("Could not "+method+" "+Object.toJSON(query))
1030
+ }
1031
+ });
1032
+ }
1033
+ } else {
1034
+ query.dom_id = dom.id
1035
+ if (!query.s) query.s = $(document.body).getAttribute('data-z')
1036
+ if (!query.t_url) query.t_url = $(document.body).getAttribute('data-t') + '/' + (dom.getAttribute('data-t') || dom.id)
1037
+ new Ajax.Request(url, {
1038
+ method:method,
1039
+ parameters:Zena.prepare_query(query),
1040
+ asynchronous:true,
1041
+ evalScripts:true,
1042
+ });
1043
+ }
1044
+ }
1045
+
1046
+ Zena.get = function(dom_name, query) {
1047
+ Zena.do('get', dom_name, query || {});
1048
+ return false;
1049
+ }
1050
+ Zena.reload = Zena.get;
1051
+
1052
+ Zena.put = function(dom_name, query) {
1053
+ Zena.do('put', dom_name, query || {});
1054
+ return false;
1055
+ }
1056
+
1057
+ Zena.post = function(dom_name, query) {
1058
+ Zena.do('post', dom_name, query || {});
1059
+ return false;
1060
+ }
1061
+
1062
+ Zena.loading = function(e) {
1063
+ e.addClassName('zloading')
1064
+ }
1065
+
1066
+
@@ -2,9 +2,12 @@
2
2
  .grid tr.action td {border-width:0 0 1px 0; font-size:70%}
3
3
  .grid tr.action td.action {border:0}
4
4
  .grid td.input, .grid th.input { padding:0;}
5
- .grid td.input input, .grid th.input input { margin:0; padding:0;font-size:inherit;}
6
- .grid td.changed {background:#E5DDD7}
5
+ .grid .input input, .grid .input textarea { margin:0; padding:0;font-size:inherit;}
6
+ .grid td.changed, .grid .new td.changed {background:#E5DDD7}
7
+ .grid .new td {background:#B2DFEE}
8
+ .grid .new td.action {background:none}
7
9
  .grid .saved { background:#A3FF4F}
10
+ .grid td.error, .grid tr.error td { background:#FFB6C1; border-color:red}
8
11
  .grid td.undone, .grid td.changed.undone, .grid th.undone, .grid th.changed.undone { background:#F3F07F}
9
12
  .grid .action span {cursor:pointer; visibility:hidden;}
10
13
  .grid:hover .action span {visibility:visible;}
@@ -16,4 +19,10 @@
16
19
  .grid_btn {margin:1em 0}
17
20
  .grid_btn a.save {background:#80B62D}
18
21
  .grid_btn a.undo {background:#AAB76D}
22
+ .grid_msg {border:1px solid #888; background:#eee; border-radius:4px; padding:5px; display:table}
19
23
 
24
+ .tags li {border-radius:2px; background:#ccc url('/images/remove_tag.png') no-repeat; padding:2px 5px 2px 15px; margin:3px; display:inline; background-position:2px 4px}
25
+ .tags li.add {background:#8c8 url('/images/add.png') no-repeat;background-position:1px 2px}
26
+
27
+ .grid .asc {background:#7b7}
28
+ .grid .desc {background:#fa0}
@@ -59,7 +59,7 @@ table.errors td { padding:2px 5px; background:inherit; border:none;}
59
59
 
60
60
  /* dev */
61
61
  .devb, #dev { background:#eee; font-size:10px;
62
- padding:5px; border:2px solid #222; text-align:left; color:#444; z-index:9999; border-width:2px 0 0 2px;}
62
+ padding:5px; border:2px solid #222; text-align:left; color:#444; z-index:100; border-width:2px 0 0 2px;}
63
63
  #dev { position:fixed; bottom:0px; right:0px;}
64
64
  .devb a { color:inherit; }
65
65
  .devb ul, .devb li { margin:0; padding:0; list-style:none; background:none; list-style-image:none;}
@@ -87,3 +87,4 @@ ins.differ, ins.differ * { background:#cfc; text-decoration:none; padding:1px 2p
87
87
  #pg_info a { width:100px; height:40px;}
88
88
  #pg_next {position:absolute; right:0; background:url('/images/popup_next.png?1276089554') no-repeat right top;}
89
89
  #pg_prev {position:absolute; left:0; background:url('/images/popup_prev.png?1276089554') no-repeat left top;}
90
+ .zloading {opacity:0.4}
@@ -63,7 +63,12 @@ Node:
63
63
  - courses.custom_a AS repeat_every
64
64
  - form.last_date AS last_date
65
65
  - form.last_date + INTERVAL courses.custom_a MONTH AS next_date
66
+ # Current hack to properly cast values to Time during read
67
+ - form.last_date + INTERVAL courses.custom_a MONTH AS idx_datetime1
66
68
  - MAX(IF(assigned_pages.custom_a,assigned_pages.custom_a,5)) AS priority
69
+ types:
70
+ next_date: time
71
+ last_date: time
67
72
  tables:
68
73
  - nodes AS courses
69
74
  # assigned to
@@ -63,6 +63,16 @@
63
63
  </table>
64
64
  </div>
65
65
 
66
+ <div class='test' id='destroy1' do='selenium'>
67
+ <h3>destroy1</h3>
68
+ <p>Using "action='destroy'" to remove elements.</p>
69
+ <ul id='destroy_list' do='block' do='projects in site'>
70
+ <li do='add' klass='Project' after='self'/>
71
+ <li do='form'><r:input name='title'/></li>
72
+ <li class='#{title}' do='each'><r:link/> <span id='destroy_#{title}' do='link' action='destroy' update='destroy_list' do='t'>destroy</span></li>
73
+ </ul>
74
+ </div>
75
+
66
76
  <div class='test' id='edit1' do='selenium'>
67
77
  <h3>edit1</h3>
68
78
  <p>Edit in place, form built from block.</p>
@@ -162,6 +172,18 @@
162
172
  </ul>
163
173
  </div>
164
174
 
175
+ //! toggle2
176
+ <div class='test' id='toggle2' do='selenium'>
177
+ <h3>toggle2</h3>
178
+ <p>Toggle with js. <span id='toggle2_count' do='block'>toggle2_count=<r:references find='count'/></span></p>
179
+ <ul class='references' do='references'>
180
+ <li do='each' do='title'/>
181
+ </ul>
182
+ <ul do='projects in site'>
183
+ <li do='each' toggle='reference' for='start' js='Zena.reload("toggle2_count")' do='title'/>
184
+ </ul>
185
+ </div>
186
+
165
187
  <div class='test' id='paginate1' do='selenium'>
166
188
  <h3>paginate1</h3>
167
189
  <p>Ajax pagination.</p>
@@ -240,6 +262,20 @@
240
262
  </r:form>
241
263
  </div>
242
264
 
265
+ //! form4
266
+ <div class='test' id='form4' do='selenium'>
267
+ <h3>form4</h3>
268
+ <p>Form to update hash property.</p>
269
+ <p id='form4_one' do='settings["one"]'/>
270
+ <p id='form4_two' do='settings["two"]'/>
271
+ <r:form node[v_status]='50'>
272
+ <ul>
273
+ <li><r:input label='t' name='settings[two]'/></li>
274
+ <li><r:input type='submit'/></li>
275
+ </ul>
276
+ </r:form>
277
+ </div>
278
+
243
279
  <div class='test' id='drop1' do='selenium'>
244
280
  <h3>drop1</h3>
245
281
  <p>Create a relation by drag and dropping.</p>
@@ -376,7 +376,6 @@ class NodesControllerTest < Zena::Controller::TestCase
376
376
  end
377
377
  end # by changing a link comment
378
378
 
379
-
380
379
  context 'by changing a link date' do
381
380
  subject do
382
381
  {:action => 'update', :controller => 'nodes', :id => nodes_zip(:opening), :node => {:link_id => links_id(:opening_in_art), :l_date => '2011-03-29 17:51'}}
@@ -416,7 +415,25 @@ class NodesControllerTest < Zena::Controller::TestCase
416
415
  end # with a bad value
417
416
 
418
417
  end # by changing skin
418
+
419
+ context 'by changing a hash value' do
420
+ setup do
421
+ Column.create(:role_id => roles_id(:Task), :ptype => 'hash', :name => 'foo')
422
+ end
423
+
424
+ subject do
425
+ {:action => 'update', :controller => 'nodes', :id => nodes_zip(:people), :node => {:foo => {:bar => 'hello'}}}
426
+ end
419
427
 
428
+ should 'change parameter' do
429
+ put_subject
430
+ node = secure(Node) { nodes(:people) }
431
+ foo = node.foo
432
+ assert_equal 'hello', foo['bar']
433
+ # Should not raise cast error
434
+ assert node.update_attributes('title' => 'pep')
435
+ end
436
+ end
420
437
  end # updating a node
421
438
 
422
439
  # ======================================= Template update
@@ -69,7 +69,7 @@ action:
69
69
  swap:
70
70
  src: "<span do='block' do='swap' attr='weight' states='100,-100' do='weight'/>"
71
71
  tem: '/:dom_id => %Q\{list1\}, :t_url => "action/swap/list1"/'
72
- '/action/swap/en/list1.erb': "/<span id='<%= ndom_id\(@node\) %>'>/"
72
+ '/action/swap/en/list1.erb': "/<span .*id='<%= ndom_id\(@node\) %>'/"
73
73
 
74
74
  swap_with_params:
75
75
  src: "<span do='block' do='swap' node[origin]='%{me}' attr='weight' states='100,-100' do='weight'/>"
@@ -86,7 +86,7 @@ swap_in_each:
86
86
 
87
87
  swap_in_each_with_block:
88
88
  src: "<r:pages in='site limit 2'><li do='each'><p do='block'><span do='swap' publish='true' attr='origin' states='todo,done,alert'/></p></li></r:pages>"
89
- res: "/<p id='list2_29'>.*list2_29.*<p id='list2_33'>.*list2_33/"
89
+ res: "/<p .*id='list2_29'.*>.*list2_29.*<p .*id='list2_33'.*>.*list2_33/"
90
90
 
91
91
  hand_made_swap:
92
92
  src: "<r:link update='_page' node[origin]='next_in_list(origin, \"todo,done\")' action='update'/>"
@@ -6,13 +6,13 @@ default:
6
6
 
7
7
  block:
8
8
  src: "<r:parent><r:block name='foobar' do='title'/></r:parent>"
9
- tem: "<% if var1 = @node.parent %><div id='foobar'><%= var1.prop['title'] %></div><% end %>"
10
- 'ajax/block/en/foobar.erb': "<div id='<%= ndom_id(@node) %>'><%= @node.prop['title'] %></div>"
9
+ tem: "<% if var1 = @node.parent %><div id='foobar' data-z='<%= var1.zip %>'><%= var1.prop['title'] %></div><% end %>"
10
+ 'ajax/block/en/foobar.erb': "<div id='<%= ndom_id(@node) %>' data-z='<%= @node.zip %>'><%= @node.prop['title'] %></div>"
11
11
 
12
12
  add:
13
13
  src: "<ul id='children' do='nodes'><li do='each' do='link'/><li do='add'/></ul>"
14
14
  tem: "/\[\"children_add\", \"children_0\"\].each\(Element.toggle\)/"
15
- 'ajax/add/en/children_form.erb': "/class='form' id='<%= ndom_id\(@node\) %>'/"
15
+ 'ajax/add/en/children_form.erb': "/class='form' .*id='<%= ndom_id\(@node\) %>'/"
16
16
  'ajax/add/en/children.erb': "<li id='<%= ndom_id(@node) %>'><a href='<%= zen_path(@node) %>'><%= @node.prop['title'] %></a></li>"
17
17
 
18
18
  edit_not_each:
@@ -24,6 +24,12 @@ edit_in_block:
24
24
  res: "/Ajax.Request\(\"/nodes/22/zafu\?dom_id=list1&"
25
25
  'ajax/edit/in/block/en/list1_form.erb': "/f.text_field :title.*alt='cancel/"
26
26
 
27
+ block_in_block:
28
+ src: "<div do='block' name='a'>A:<r:root do='link' update='a'/><r:filter live='true' update='b'/><div do='block' name='b'>B:</div></div>"
29
+ # Make sure the correct template is built, not a2 or something.
30
+ 'ajax/block/in/block/en/a.erb': "/A:/"
31
+ 'ajax/block/in/block/en/b.erb': "/B:/"
32
+
27
33
  edit_in_block_publish:
28
34
  src: "<li do='block'><r:title/> <r:edit publish='true'/></li>"
29
35
  res: "/Ajax.Request\(\"/nodes/22/zafu\?dom_id=list1/"
@@ -55,7 +61,7 @@ form_update:
55
61
  add_each_no_form:
56
62
  src: "<ul do='children' id='things'><li do='each'>I <p do='title'>blah</p></li><li do='add'/></ul>"
57
63
  tem: "!/</ul><ul></ul>/" # bug in closing group with [add].
58
- res: "/<ul><li.*id='things_add'.*li.*class='form' id='things_0'.*form.*I <p><input id=.things_title. name=.node\[title\]. .*type=.text..*hidden/"
64
+ res: "/<ul><li.*id='things_add'.*li.*class='form' .*id='things_0'.*form.*I <p><input id=.things_title. name=.node\[title\]. .*type=.text..*hidden/"
59
65
 
60
66
  add_each_no_form_date:
61
67
  src: "<ul do='children' id='things'><li do='each'>I <p do='show' attr='event_at' tformat='short_date'>blah</p></li><li do='add'/></ul>"
@@ -74,7 +80,7 @@ each_add_with_form:
74
80
  <li do='add'>add new</li>
75
81
  <li do='form'><input name='title'/> this is the form</li>
76
82
  </ol>
77
- res: "/<li id='list1_30'>bird.*<li id='list1_31'>flower.*<li.*list1_add.*list1_0.*toggle.*<li style.*none.*list1_0.*Ajax.Request.*input type='hidden' name='t_url' value=.ajax/each/add/with/form/list1.*input type='hidden' name='node\[parent_id\]' value=.29./"
83
+ res: "/<li id='list1_30'>bird.*<li id='list1_31'>flower.*<li.*list1_add.*list1_0.*toggle.*<li.*style.*none.*list1_0.*Ajax.Request.*input type='hidden' name='t_url' value=.ajax/each/add/with/form/list1.*input type='hidden' name='node\[parent_id\]' value=.29./"
78
84
 
79
85
  each_add_with_form_in_sub_block:
80
86
  context:
@@ -177,24 +183,24 @@ live_filter:
177
183
  src: "<r:filter live='true'/><r:block><ol do='pages where title like \"#{params[:f]}%\"'><li do='each' do='title'/></ol></r:block>"
178
184
  # Make sure a unique_name is set for the given block
179
185
  tem: "/name='t_url' value='ajax/live/filter/list1'.*<% filter_form\(@node.*ml1.value LIKE \?.*, \"#\{params\[:f\]\}%\"/"
180
- 'ajax/live/filter/en/list1.erb': "/<div id='<%= ndom_id\(@node\).*, \"#\{params\[:f\]\}%\".*var2.prop\['title'\]/"
181
- res: "/<input type='text' name='f'.*<div id='list1'><ol><li>crocodiles</li><li>status title</li></ol></div>/"
186
+ 'ajax/live/filter/en/list1.erb': "/<div .*id='<%= ndom_id\(@node\).*, \"#\{params\[:f\]\}%\".*var2.prop\['title'\]/"
187
+ res: "/<input type='text' name='f'.*<div .*id='list1'.*><ol><li>crocodiles</li><li>status title</li></ol></div>/"
182
188
 
183
189
  live_filter_single_element:
184
190
  context:
185
191
  node: cleanWater
186
192
  src: "<r:filter live='true'/><r:block><r:page where='title like \"#{params[:f]}%\"' find='first'><b do='title'/></r:page></r:block>"
187
193
  tem: "/, \"#\{params\[:f\]\}%\"/"
188
- 'ajax/live/filter/single/element/en/list1.erb': "/<div id=.*params\[:f\].*var1.prop\['title'\]/"
189
- res: "/<input type='text' name='f'.*<div id='list1'><b>crocodiles</b></div>/"
194
+ 'ajax/live/filter/single/element/en/list1.erb': "/<div .*id=.*params\[:f\].*var1.prop\['title'\]/"
195
+ res: "/<input type='text' name='f'.*<div .*id='list1'.*><b>crocodiles</b></div>/"
190
196
 
191
197
  live_filter_select_options:
192
198
  context:
193
199
  node: cleanWater
194
200
  src: "<r:filter live='true' do='select' param='f' tprefix='foo' values='1,2'/><r:block><ol do='pages where title like \"#{params[:f]}%\"'><li do='each' do='title'/></ol></r:block>"
195
201
  tem: "/select name=.f.><%= options_for_select.*.foo_1., .1..*, param_value\(.f.\).to_s/"
196
- 'ajax/live/filter/select/options/en/list1.erb': "/<div id='<%= ndom_id\(@node\) %>'.*params\[:f\]/"
197
- res: "/<select name='f'.*<div id='list1'><ol><li>crocodiles</li><li>status title</li></ol></div>/"
202
+ 'ajax/live/filter/select/options/en/list1.erb': "/<div .*id='<%= ndom_id\(@node\) %>'.*params\[:f\]/"
203
+ res: "/<select name='f'.*<div .*id='list1'.*><ol><li>crocodiles</li><li>status title</li></ol></div>/"
198
204
 
199
205
  draggable_do_syntax:
200
206
  src: "<r:images in='site' do='each' draggable='all' do='img' mode='pv'/>"
@@ -220,7 +226,7 @@ drag_with_form:
220
226
  <td class='edit'> <r:edit class='edit'>éditer</r:edit></td>
221
227
  </tr>
222
228
  </table>"
223
- tem: "/<span class='drag' id='<%= %Q\{list3_#\{var2.zip\}\}.*<% add_drag_id\(%Q\{list3_#\{var2.zip\}\}/"
229
+ tem: "/<span class='drag' id='<%= %Q\{list2_#\{var2.zip\}\}.*<% add_drag_id\(%Q\{list2_#\{var2.zip\}\}/"
224
230
 
225
231
  drag_with_form_not_in_form:
226
232
  src: "<table do='pages in site'>
@@ -255,7 +261,7 @@ draggable_in_block:
255
261
  # should use 'hooba' class
256
262
  src: "<r:block><r:link draggable='hooba'/></r:block>"
257
263
  tem: "/add_drag_id\(%Q\{drag_\#\{@node.zip\}\}, .*hooba/"
258
- res: "<div id='list1'><span class='drag' id='drag_22'><span class='hooba'>&nbsp;</span><a href='/oo/projects-list/Clean-Water-project/page22.html'>status title</a></span></div>"
264
+ res: "<div id='list1' data-z='22'><span class='drag' id='drag_22'><span class='hooba'>&nbsp;</span><a href='/oo/projects-list/Clean-Water-project/page22.html'>status title</a></span></div>"
259
265
  js: "/Zena.draggable\(item, \"hooba\"\)/"
260
266
 
261
267
  draggable_with_id_set:
@@ -290,8 +296,8 @@ edit_link:
290
296
  'ajax/edit/link/fr/list1.erb': "/:link_id => @node.link_id/"
291
297
 
292
298
  start_id:
293
- src: "<r:form><input type='hidden' name='s' value='#{start_id}'/></r:form>"
294
- res: "/<input type='hidden' name='s' value='22'/></"
299
+ src: "<r:form><input name='s' type='hidden' value='#{start_id}'/></r:form>"
300
+ res: "/<input name='s' type='hidden' value='22'/></"
295
301
 
296
302
  drop_add_link:
297
303
  context:
@@ -299,7 +305,7 @@ drop_add_link:
299
305
  src: "<div do='drop' add='favorite'></div>"
300
306
  # without the ugly inspect, this would be '#{id}' or "\#{id}"
301
307
  tem: "/drop_node_path.*\"node\[favorite_id\]\" => \"\\\\#\{id\}\"/"
302
- res: "<div class='drop' id='list1'></div>"
308
+ res: "<div class='drop' id='list1' data-z='22'></div>"
303
309
  js: "/Droppables.add\('list1'.*/nodes/22/drop.*node\[favorite_id\]=%23%7Bid%7D"
304
310
 
305
311
  drop_var_scope:
@@ -312,14 +318,14 @@ drop_done_remove:
312
318
 
313
319
  drop_param:
314
320
  src: "<r:drop change='params' d='%{foo}'>params[:d] = <r:show eval='params[:d]'/></r:drop>"
315
- tem: "/<div class='drop' id='list1'><% add_drop_id\(%Q\{list1\}, :url => drop_node_path\(@node.*:d => \"foo\", :change => \"params\"/"
316
- res: "<div class='drop' id='list1'>params[:d] = </div>"
321
+ tem: "/<div class='drop' id='list1'.*><% add_drop_id\(%Q\{list1\}, :url => drop_node_path\(@node.*:d => \"foo\", :change => \"params\"/"
322
+ res: "<div class='drop' id='list1' data-z='22'>params[:d] = </div>"
317
323
  js: '/Droppables.add\(.list1.*d=foo/'
318
324
 
319
325
  drop_in_each:
320
326
  src: "<ul do='pages'><li do='each'><ul do='drop' set='reference'>...</ul></li></ul>"
321
- tem: "/<ul class='drop' id='<%= %Q\{list2_#\{var2.zip\}\} %>'><% add_drop_id\(%Q\{list2_#\{var2.zip\}\}/"
322
- 'ajax/drop/in/each/en/list2.erb': "/<ul class='drop' id=.*ndom_id.*add_drop_id.*drop_node_path.*ndom_id/"
327
+ tem: "/<ul class='drop' .*id='<%= %Q\{list2_#\{var2.zip\}\} %>'.*><% add_drop_id\(%Q\{list2_#\{var2.zip\}\}/"
328
+ 'ajax/drop/in/each/en/list2.erb': "/<ul class='drop' .*id=.*ndom_id.*add_drop_id.*drop_node_path.*ndom_id/"
323
329
 
324
330
  drop_param_in_each:
325
331
  src: "<r:pages do='each' do='drop' change='params' d='%{foo}'><r:show eval='params[:d]'/></r:pages>"
@@ -341,13 +347,15 @@ drop_in_each_id:
341
347
  # Should use prefix from "drop", not list of favorites.
342
348
  res: "/drop13_39/"
343
349
  # Show drop element
344
- 'ajax/drop/in/each/id/en/drop12.erb': "/^\s*<ul.*<li id='<%= %Q\{drop13_#\{var2.zip\}\} %>"
350
+ 'ajax/drop/in/each/id/en/drop12.erb': "/^\s*<ul.*<li .*id='<%= %Q\{drop13_#\{var2.zip\}\} %>"
345
351
  # Show each element
346
352
  'ajax/drop/in/each/id/en/drop13.erb': '/^\s*<li/'
347
353
 
348
354
  update_target:
349
355
  src: "UT: <div id='foo' do='block'>...</div> <r:link update='foo'/>"
350
- tem: "/UT: <div id='foo'>...</div> .*Ajax.Request.*:dom_id => %Q\{foo\}/"
356
+ tem: "/UT: <div .*id='foo'.*>...</div> .*Ajax.Request.*:dom_id => %Q\{foo\}/"
357
+ # New syntax should be
358
+ # tem: "/UT: <div .*id='foo'>...</div> .*Zena.get('foo', {id:<%= @node.zip %>})/"
351
359
 
352
360
  update_target_encode_params:
353
361
  context:
@@ -358,11 +366,11 @@ update_target_encode_params:
358
366
 
359
367
  include_update_target:
360
368
  src: "IUT: <r:include template='/ajax/update/target'><r:with part='foo'><r:show attr='title'/></r:with></r:include>"
361
- tem: "/IUT: UT: <div id='foo'><%= h @node.prop\['title'\] %></div> <a .*zen_path.*onclick='new Ajax.Request/"
369
+ tem: "/IUT: UT: <div .*id='foo'.*><%= h @node.prop\['title'\] %></div> <a .*zen_path.*onclick='new Ajax.Request/"
362
370
 
363
371
  id_in_each_group_should_be_scoped:
364
372
  src: "<ul do='comments from nodes in site' do='group' by='discussion_id'><li do='each'><r:node do='block' do='title'/></li></ul>"
365
- tem: "/<div id='<%= %Q\{list1_#\{var4.zip\}_list2\} %>'>/"
373
+ tem: "/<div .*id='<%= %Q\{list1_#\{var4.zip\}_list2\} %>'/"
366
374
 
367
375
  link_page_next:
368
376
  context:
@@ -380,7 +388,7 @@ link_page_list:
380
388
  toggle:
381
389
  src: "<span do='toggle' set='favorite' for='visitor.node'/>"
382
390
  res: "<span class='toggle' id='list1_22'></span>"
383
- js: "/var1 = \{\"list\":\[39\], \"url\":\"/nodes/13\", \"role\":\"favorite\".*\"list1_22\"\].each.function.item. \{ Zena.set_toggle/"
391
+ js: "/var1 = \{list:\[39\], url:\"/nodes/13\", role:\"favorite\".*\"list1_22\"\].each.function.item. \{ Zena.set_toggle/"
384
392
 
385
393
  toggle_attribute_in_each:
386
394
  context:
@@ -394,7 +402,7 @@ toggle_dyn_attribute_in_each:
394
402
  node: cleanWater
395
403
  rel: favorite
396
404
  src: "<ul do='pages'><li do='each' toggle='#{params[:rel]}' for='visitor.node' do='title'/></ul>"
397
- tem: "/add_toggle_id\(\"list1_#\{var2.zip\}\", \"var2_tog\", \"#\{params\[:rel\]\}\"\)/"
405
+ tem: "/add_toggle_id\(\"list1_#\{var2.zip\}\", \"var2_tog\", \"#\{params\[:rel\]\}\",\{\}\)/"
398
406
  res: "/<ul><li class='toggle' id='list1_26'>crocodiles</li>/"
399
407
  js: "/list1_26.*each/"
400
408
 
@@ -418,6 +426,16 @@ js_dyn:
418
426
  res: "x y"
419
427
  js: "<script type=\"text/javascript\">\n//<![CDATA[\nalert('ho status title');\n//]]>\n</script>"
420
428
 
429
+ js_less_then:
430
+ src: "x <r:js>if (i < 4) alert('ho <r:title/>');</r:js> y"
431
+ tem: "x <% js_data << capture do %>if (i < 4) alert('ho <%= @node.prop['title'] %>');<% end %> y"
432
+ res: "x y"
433
+ js: "<script type=\"text/javascript\">\n//<![CDATA[\nif (i < 4) alert('ho status title');\n//]]>\n</script>"
434
+
435
+ js_in_attr:
436
+ src: "<a onclick='if (i < 4) alert(\"go\");'>hop</a>"
437
+ tem: "<a onclick='if (i < 4) alert(\"go\");'>hop</a>"
438
+
421
439
  filter_in_list:
422
440
  # Should move to up node and not raise an error.
423
441
  src: "<ul do='pages in site'><r:block></r:block><li do='filter' live='true'/></ul>"