zena 1.0.0.beta2 → 1.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.txt +12 -0
- data/app/controllers/application_controller.rb +0 -1
- data/app/controllers/columns_controller.rb +11 -1
- data/app/controllers/nodes_controller.rb +79 -19
- data/app/controllers/versions_controller.rb +0 -2
- data/app/controllers/virtual_classes_controller.rb +19 -6
- data/app/models/column.rb +5 -1
- data/app/models/comment.rb +1 -6
- data/app/models/node.rb +21 -3
- data/app/models/role.rb +21 -0
- data/app/models/site.rb +7 -2
- data/app/models/template.rb +3 -3
- data/app/models/text_document.rb +4 -4
- data/app/models/user.rb +21 -8
- data/app/views/columns/_li.html.erb +1 -0
- data/app/views/nodes/_groups.rhtml +1 -1
- data/app/views/sites/_form.erb +3 -1
- data/app/views/sites/_li.erb +1 -0
- data/app/views/sites/index.erb +1 -1
- data/app/views/virtual_classes/_form.erb +11 -2
- data/app/views/virtual_classes/_li.erb +5 -2
- data/bin/zena +1 -1
- data/bricks/math/lib/bricks/math.rb +1 -1
- data/bricks/mongrel/README +3 -0
- data/bricks/mongrel/zena/deploy.rb +56 -0
- data/bricks/passenger/README +3 -0
- data/bricks/passenger/zena/deploy.rb +49 -0
- data/config/bricks.yml +6 -0
- data/config/deploy.rb +24 -18
- data/config/gems.yml +3 -3
- data/db/migrate/20100915062903_add_api_group_id_to_site.rb +9 -0
- data/lib/tasks/zena.rake +39 -35
- data/lib/zena.rb +5 -6
- data/lib/zena/acts/enrollable.rb +37 -6
- data/lib/zena/app.rb +4 -2
- data/lib/zena/deploy.rb +110 -150
- data/lib/zena/deploy/awstats.conf.rhtml +4 -4
- data/lib/zena/deploy/httpd.rhtml +2 -1
- data/lib/zena/deploy/stats.vhost.rhtml +7 -7
- data/lib/zena/deploy/vhost.rhtml +1 -1
- data/lib/zena/deploy/vhost_www.rhtml +4 -4
- data/lib/zena/foxy_parser.rb +6 -5
- data/lib/zena/info.rb +1 -1
- data/lib/zena/integration/test_case.rb +8 -3
- data/lib/zena/parser.rb +11 -11
- data/lib/zena/parser/zafu_tags.rb +2 -2
- data/lib/zena/remote.rb +16 -0
- data/lib/zena/remote/connection.rb +67 -0
- data/lib/zena/remote/interface.rb +405 -0
- data/lib/zena/remote/klass.rb +14 -0
- data/lib/zena/remote/mock.rb +58 -0
- data/lib/zena/remote/node.rb +76 -0
- data/lib/zena/routes.rb +2 -1
- data/lib/zena/use.rb +9 -4
- data/lib/zena/use/ajax.rb +3 -3
- data/lib/zena/use/authlogic.rb +8 -1
- data/lib/zena/use/context.rb +22 -21
- data/lib/zena/use/dates.rb +26 -3
- data/lib/zena/use/display.rb +33 -5
- data/lib/zena/use/forms.rb +90 -12
- data/lib/zena/use/fulltext.rb +1 -1
- data/lib/zena/use/i18n.rb +118 -31
- data/lib/zena/use/query_builder.rb +7 -5
- data/lib/zena/use/query_node.rb +30 -4
- data/lib/zena/use/rendering.rb +1 -1
- data/lib/zena/use/search.rb +10 -7
- data/lib/zena/use/urls.rb +3 -3
- data/lib/zena/use/zafu_attributes.rb +2 -2
- data/lib/zena/use/zafu_eval.rb +1 -1
- data/lib/zena/use/zafu_safe_definitions.rb +1 -0
- data/lib/zena/use/zafu_templates.rb +1 -1
- data/lib/zena/zafu_compiler.rb +5 -1
- data/public/javascripts/zena.js +4 -4
- data/public/stylesheets/admin.css +1 -0
- data/test/custom_queries/complex.host.yml +3 -3
- data/test/fixtures/files/translations_fr.yml +4 -1
- data/test/functional/application_controller_test.rb +2 -2
- data/test/functional/nodes_controller_test.rb +57 -5
- data/test/functional/users_controller_test.rb +10 -9
- data/test/functional/virtual_classes_controller_test.rb +48 -0
- data/test/integration/navigation_test.rb +13 -1
- data/test/integration/query_node/filters.yml +5 -0
- data/test/integration/query_node_test.rb +1 -1
- data/test/integration/zafu_compiler/ajax.yml +13 -19
- data/test/integration/zafu_compiler/basic.yml +0 -72
- data/test/integration/zafu_compiler/complex.yml +1 -1
- data/test/integration/zafu_compiler/complex_ok.yml +19 -0
- data/test/integration/zafu_compiler/dates.yml +62 -1
- data/test/integration/zafu_compiler/display.yml +4 -4
- data/test/integration/zafu_compiler/forms.yml +19 -7
- data/test/integration/zafu_compiler/i18n.yml +56 -1
- data/test/integration/zafu_compiler/later.yml +23 -1
- data/test/integration/zafu_compiler/relations.yml +1 -1
- data/test/integration/zafu_compiler/roles.yml +29 -1
- data/test/integration/zafu_compiler/safe_definitions.yml +1 -1
- data/test/integration/zafu_compiler/zafu_attributes.yml +2 -1
- data/test/integration/zafu_compiler_test.rb +5 -3
- data/test/sites/zena/columns.yml +3 -0
- data/test/sites/zena/roles.yml +0 -1
- data/test/sites/zena/sites.yml +1 -0
- data/test/sites/zena/versions.yml +2 -0
- data/test/unit/node_test.rb +27 -9
- data/test/unit/relation_proxy_test.rb +7 -4
- data/test/unit/remote_test.rb +379 -0
- data/test/unit/user_test.rb +47 -0
- data/test/unit/zena/acts/enrollable_test.rb +36 -7
- data/test/unit/zena/acts/serializable_test.rb +14 -2
- data/test/unit/zena/use/i18n_test.rb +32 -5
- data/test/unit/zena/use/query_node_test.rb +13 -1
- data/zena.gemspec +25 -11
- metadata +24 -10
@@ -0,0 +1,58 @@
|
|
1
|
+
module Zena
|
2
|
+
module Remote
|
3
|
+
module Mock
|
4
|
+
# Redirect actual request to the integration test.
|
5
|
+
class Request < HTTParty::Request
|
6
|
+
def perform_actual_request
|
7
|
+
# body should contain xml data for post and put (@raw_request.body ?)
|
8
|
+
method = @raw_request.method.downcase
|
9
|
+
path = @raw_request.path
|
10
|
+
body = @raw_request.body
|
11
|
+
|
12
|
+
response = $test_connection.test_request(method, path, body, options[:headers], false)
|
13
|
+
transform_response(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Transform an ActionController::Response into a Net::HTTP response.
|
18
|
+
# Based on code from fakeweb (thanks Chrisk !)
|
19
|
+
def transform_response(ac_res)
|
20
|
+
code, msg = 200, 'OK'
|
21
|
+
response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
|
22
|
+
response.instance_variable_set(:@body, ac_res.body)
|
23
|
+
ac_res.headers.each do |name, value|
|
24
|
+
if value.respond_to?(:each)
|
25
|
+
value.each { |v| response.add_field(name, v) }
|
26
|
+
else
|
27
|
+
response[name] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
response.instance_variable_set(:@read, true)
|
32
|
+
|
33
|
+
class << response
|
34
|
+
def read_body(*args, &block)
|
35
|
+
yield @body if block_given?
|
36
|
+
@body
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
response
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Include this module to mock the connection and use the integration test to execute
|
45
|
+
# the actual request operations.
|
46
|
+
module Connection
|
47
|
+
|
48
|
+
def self.included(base)
|
49
|
+
def base.perform_request(http_method, path, options) #:nodoc:
|
50
|
+
options = default_options.dup.merge(options)
|
51
|
+
process_cookies(options)
|
52
|
+
request = Zena::Remote::Mock::Request.new(http_method, path, options).perform
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end # Connection
|
56
|
+
end # Mock
|
57
|
+
end # Remote
|
58
|
+
end # Zena
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Zena
|
2
|
+
module Remote
|
3
|
+
class Node
|
4
|
+
include Zena::Remote::Interface::InstanceMethods
|
5
|
+
attr_accessor :connection, :attributes, :errors
|
6
|
+
|
7
|
+
def initialize(connection, hash)
|
8
|
+
@connection = connection
|
9
|
+
@attributes = {}
|
10
|
+
self.attributes = hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def attributes=(new_attributes)
|
14
|
+
raise Exception.new("Invalid attributes. Expecting a hash, found #{new_attributes.inspect}") unless new_attributes.kind_of?(Hash)
|
15
|
+
new_attributes.stringify_keys.each do |key, value|
|
16
|
+
if value.kind_of?(Array)
|
17
|
+
# setting multiple ids
|
18
|
+
key = "#{key}_ids" unless key =~ /_ids$/
|
19
|
+
@attributes[key] = value.map do |elem|
|
20
|
+
if elem.kind_of?(Remote::Node)
|
21
|
+
elem.id
|
22
|
+
else
|
23
|
+
elem
|
24
|
+
end
|
25
|
+
end
|
26
|
+
elsif value.kind_of?(Remote::Node)
|
27
|
+
key = "#{key}_id" unless key =~ /_id$/
|
28
|
+
@attributes[key] = value.id
|
29
|
+
elsif key =~ /_ids$/ && value.kind_of?(String)
|
30
|
+
@attributes[key] = value.split(',').map(&:to_i)
|
31
|
+
else
|
32
|
+
@attributes[key] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def id
|
38
|
+
@attributes['id']
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(method, *args)
|
42
|
+
method = method.to_s
|
43
|
+
if args.size == 1 && method =~ /(.*)=$/
|
44
|
+
key = $1
|
45
|
+
elem = args.first
|
46
|
+
if elem.kind_of?(Remote::Node)
|
47
|
+
key = "#{key}_id" unless key =~ /_ids?$/
|
48
|
+
@attributes[key] = elem.id
|
49
|
+
elsif elem.kind_of?(Array)
|
50
|
+
key = "#{key}_ids" unless key =~ /_ids?$/
|
51
|
+
@attributes[key] = elem.map do |value|
|
52
|
+
value.kind_of?(Remote::Node) ? value.id : value
|
53
|
+
end
|
54
|
+
else
|
55
|
+
@attributes[$1] = elem
|
56
|
+
end
|
57
|
+
elsif args.size == 0
|
58
|
+
if @attributes.has_key?(method)
|
59
|
+
@attributes[method]
|
60
|
+
elsif method =~ /_ids?$/
|
61
|
+
@attributes[method] ||= []
|
62
|
+
else
|
63
|
+
# build query
|
64
|
+
if method.pluralize == method
|
65
|
+
res = all(method)
|
66
|
+
else
|
67
|
+
res = first(method)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end # Remote
|
76
|
+
end # Zena
|
data/lib/zena/routes.rb
CHANGED
@@ -25,7 +25,8 @@ module Zena
|
|
25
25
|
:collection => { :asearch => :get, :search => :get },
|
26
26
|
:member => { :import => :post, :export => :get, :save_text => :put,
|
27
27
|
:order => :any, :clear_order => :any,
|
28
|
-
:zafu => :get, :drop => :put, :attribute => :get
|
28
|
+
:zafu => :get, :drop => :put, :attribute => :get,
|
29
|
+
:find => :get # same as search but starting on current node instead of root
|
29
30
|
}.merge(Zena::Use::Grid::Routes) do |nodes|
|
30
31
|
nodes.resources :versions,
|
31
32
|
:member => { :edit => :get,
|
data/lib/zena/use.rb
CHANGED
@@ -9,16 +9,16 @@ module Zena
|
|
9
9
|
class << self
|
10
10
|
attr_accessor :modules
|
11
11
|
|
12
|
-
#
|
12
|
+
# Declare a module (or list of modules) that should be used in Zena. The module should implement
|
13
13
|
# sub-modules named ControllerMethods, ViewMethods or ZafuMethods in order to add features to
|
14
14
|
# the controller, view or zafu compiler respectively.
|
15
15
|
def module(*modules)
|
16
16
|
create_module_hash
|
17
17
|
|
18
18
|
modules.flatten.each do |mod|
|
19
|
-
MODULE_NAME.each do |key,
|
19
|
+
MODULE_NAME.each do |key, sub_module_name|
|
20
20
|
begin
|
21
|
-
self.modules[key] << mod.const_get(
|
21
|
+
self.modules[key] << mod.const_get(sub_module_name)
|
22
22
|
rescue NameError
|
23
23
|
# ignore
|
24
24
|
end
|
@@ -28,11 +28,16 @@ module Zena
|
|
28
28
|
|
29
29
|
def each_module_for(name)
|
30
30
|
create_module_hash
|
31
|
-
(
|
31
|
+
modules_for(name).each do |mod|
|
32
32
|
yield(mod)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def modules_for(name)
|
37
|
+
create_module_hash
|
38
|
+
self.modules[name] || []
|
39
|
+
end
|
40
|
+
|
36
41
|
private
|
37
42
|
def create_module_hash
|
38
43
|
if self.modules.nil?
|
data/lib/zena/use/ajax.rb
CHANGED
@@ -232,7 +232,7 @@ module Zena
|
|
232
232
|
|
233
233
|
dom_id = node.dom_id(:erb => false)
|
234
234
|
|
235
|
-
out %Q{<%= form_remote_tag(:url => zafu_node_path(#{node}), :method => :get, :html => {:id => \"#{dom_id}_f\"}) %>
|
235
|
+
out %Q{<%= form_remote_tag(:url => zafu_node_path(#{node}.zip), :method => :get, :html => {:id => \"#{dom_id}_f\"}) %>
|
236
236
|
<div class='hidden'>
|
237
237
|
<input type='hidden' name='t_url' value='#{template_url(upd)}'/>
|
238
238
|
<input type='hidden' name='dom_id' value='#{upd}'/>
|
@@ -297,7 +297,7 @@ module Zena
|
|
297
297
|
return parser_error("missing 'set' or 'add' parameter") unless role = @params.delete(:set) || @params.delete(:add)
|
298
298
|
return parser_error("missing 'for' parameter") unless finder = @params.delete(:for)
|
299
299
|
|
300
|
-
finder = RubyLess.translate(
|
300
|
+
finder = RubyLess.translate(self, finder)
|
301
301
|
return parser_error("Invalid class 'for' parameter: #{finder.klass}") unless finder.klass <= Node
|
302
302
|
|
303
303
|
set_dom_prefix
|
@@ -315,7 +315,7 @@ module Zena
|
|
315
315
|
return
|
316
316
|
end
|
317
317
|
|
318
|
-
finder = RubyLess.translate(
|
318
|
+
finder = RubyLess.translate(self, finder)
|
319
319
|
unless finder.klass <= Node
|
320
320
|
out parser_error("Invalid class 'for' parameter: #{finder.klass}")
|
321
321
|
return
|
data/lib/zena/use/authlogic.rb
CHANGED
@@ -20,6 +20,13 @@ module Zena
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def save_after_login_url
|
23
|
+
# prevent redirect to favicon or css
|
24
|
+
return unless request.format == Mime::HTML
|
25
|
+
path = params[:path]
|
26
|
+
if path && path.last =~ /\.(.+)\Z/
|
27
|
+
return if $1 != 'html'
|
28
|
+
end
|
29
|
+
|
23
30
|
session[:after_login_url] = request.parameters
|
24
31
|
end
|
25
32
|
|
@@ -92,7 +99,7 @@ module Zena
|
|
92
99
|
# Allow xml without :prefix in NodesController because it is rendered with zafu.
|
93
100
|
|
94
101
|
# Authentication token required for xml.
|
95
|
-
render :xml => 'Authentication token needed.', :status => 401
|
102
|
+
render :xml => [{:message => 'Authentication token needed.'}].to_xml(:root => 'errors'), :status => 401
|
96
103
|
end
|
97
104
|
end
|
98
105
|
end
|
data/lib/zena/use/context.rb
CHANGED
@@ -12,6 +12,7 @@ module Zena
|
|
12
12
|
|
13
13
|
# Group an array of records by key.
|
14
14
|
def group_array(list)
|
15
|
+
return nil if list.empty?
|
15
16
|
groups = []
|
16
17
|
h = {}
|
17
18
|
list.each do |e|
|
@@ -148,38 +149,38 @@ module Zena
|
|
148
149
|
# end
|
149
150
|
|
150
151
|
if %w{parent project section}.include?(key)
|
151
|
-
key = "e.#{key}"
|
152
|
+
key = "e.#{key}_id"
|
152
153
|
else
|
153
|
-
|
154
|
+
receiver = RubyLess::TypedString.new('e', :class => node.klass.first, :query => node.opts[:query])
|
155
|
+
key = RubyLess.translate(receiver, key)
|
154
156
|
end
|
155
157
|
|
156
158
|
#if sort_block
|
157
159
|
# out "<% grp_#{list_var} = sort_array(#{group_array}) #{sort_block} -%>"
|
158
160
|
#else
|
159
|
-
out "<% #{var} = group_array(#{node}) {|e| #{key}} -%>"
|
160
161
|
#end
|
162
|
+
method = "group_array(#{node}) {|e| #{key}}"
|
163
|
+
out "<% if #{var} = #{method} -%>"
|
164
|
+
open_node_context({:method => method}, :node => node.move_to(var, [node.klass], :query => node.opts[:query])) do
|
165
|
+
if child['each_group']
|
166
|
+
out expand_with
|
167
|
+
else
|
168
|
+
@var = nil
|
169
|
+
r_each
|
170
|
+
end
|
171
|
+
end
|
172
|
+
out "<% end -%>"
|
161
173
|
|
162
|
-
if descendant('each_group')
|
163
|
-
|
164
|
-
else
|
165
|
-
|
166
|
-
|
167
|
-
end
|
174
|
+
#if descendant('each_group')
|
175
|
+
# out expand_with(:group => var)
|
176
|
+
#else
|
177
|
+
# @context[:group] = var
|
178
|
+
# r_each_group
|
179
|
+
#end
|
168
180
|
end
|
169
181
|
|
170
|
-
|
171
182
|
def r_each_group
|
172
|
-
|
173
|
-
if join = @params[:join]
|
174
|
-
join = join.gsub(/<([^%])/, '<\1').gsub(/([^%])>/, '\1>')
|
175
|
-
out "<% #{group}.each_with_index do |#{var}, #{var}_i| -%>"
|
176
|
-
out "<%= #{var}_i > 0 ? #{join.inspect} : '' %>"
|
177
|
-
else
|
178
|
-
out "<% #{group}.each do |#{var}| -%>"
|
179
|
-
end
|
180
|
-
|
181
|
-
out wrap(expand_with(:group => nil, :node => node.move_to(var, node.klass)))
|
182
|
-
out "<% end -%>"
|
183
|
+
r_each
|
183
184
|
end
|
184
185
|
end # ZafuMethods
|
185
186
|
end # Context
|
data/lib/zena/use/dates.rb
CHANGED
@@ -279,9 +279,32 @@ EOL
|
|
279
279
|
end
|
280
280
|
|
281
281
|
# Select a date for the current context
|
282
|
-
|
283
|
-
|
284
|
-
|
282
|
+
def r_date
|
283
|
+
return nil unless code = get_attribute_or_eval
|
284
|
+
|
285
|
+
if format = @params[:format]
|
286
|
+
format = RubyLess.translate_string(self, format)
|
287
|
+
else
|
288
|
+
format = "'%Y-%m-%d %H:%M:%S'"
|
289
|
+
end
|
290
|
+
|
291
|
+
if code.klass <= String
|
292
|
+
if code.could_be_nil?
|
293
|
+
code = "(#{code} || '').to_utc(#{format})"
|
294
|
+
else
|
295
|
+
code = "#{code}.to_utc(#{format})"
|
296
|
+
end
|
297
|
+
could_be_nil = true
|
298
|
+
elsif code.klass <= Time
|
299
|
+
could_be_nil = code.could_be_nil?
|
300
|
+
else
|
301
|
+
return parser_error("should evaluate to a String or Time (found #{code.klass})")
|
302
|
+
end
|
303
|
+
v = get_var_name('set_var', 'date')
|
304
|
+
out "<% #{v} = #{code} -%>"
|
305
|
+
set_context_var('set_var', 'date', RubyLess::TypedString.new(v, :class => Time, :nil => could_be_nil))
|
306
|
+
out expand_with
|
307
|
+
end
|
285
308
|
|
286
309
|
end
|
287
310
|
end # Dates
|
data/lib/zena/use/display.rb
CHANGED
@@ -387,11 +387,32 @@ module Zena
|
|
387
387
|
end # ViewMethods
|
388
388
|
|
389
389
|
module ZafuMethods
|
390
|
+
SHOW_KEYS = [:tz, :tformat, :format, :lang, :zero]
|
391
|
+
|
390
392
|
include Common
|
391
393
|
include RubyLess
|
392
394
|
|
393
395
|
safe_method [:zazen, String] => :r_zazen
|
394
396
|
|
397
|
+
# As a last resort, if the method cannot be compilated, use <r:show eval='...'/>
|
398
|
+
def self.included(base)
|
399
|
+
base.process_unknown :show_eval
|
400
|
+
end
|
401
|
+
|
402
|
+
# Transform <p do='created_at' format='%d'/> into
|
403
|
+
# <p do='show' eval='created_at' format='%d'/>
|
404
|
+
def show_eval
|
405
|
+
if !@params.empty? && !(@method =~ /. ./) && (@params.keys - SHOW_KEYS == [])
|
406
|
+
# try to use r_show without using params as arguments
|
407
|
+
code = RubyLess.translate(self, @method)
|
408
|
+
r_show(code)
|
409
|
+
else
|
410
|
+
nil
|
411
|
+
end
|
412
|
+
rescue RubyLess::Error
|
413
|
+
nil
|
414
|
+
end
|
415
|
+
|
395
416
|
# Parse text with zazen helper
|
396
417
|
def r_zazen(signature = nil)
|
397
418
|
@markup.prepend_param(:class, 'zazen')
|
@@ -421,15 +442,15 @@ module Zena
|
|
421
442
|
end
|
422
443
|
|
423
444
|
# Display an attribute or RubyLess code
|
424
|
-
def r_show
|
445
|
+
def r_show(code = nil)
|
425
446
|
if node.list_context?
|
426
|
-
@context[:node] = node.move_to("#{node}.first", node.klass.first)
|
447
|
+
@context[:node] = node.move_to("#{node}.first", node.klass.first, :query => node.opts[:query])
|
427
448
|
return r_show
|
428
449
|
elsif node.will_be?(String)
|
429
450
|
return "<%= #{node} %>"
|
430
451
|
end
|
431
452
|
|
432
|
-
return nil unless method = get_attribute_or_eval
|
453
|
+
return nil unless method = code || get_attribute_or_eval
|
433
454
|
|
434
455
|
klass = method.klass
|
435
456
|
|
@@ -505,7 +526,7 @@ module Zena
|
|
505
526
|
return unless node.will_be?(Node)
|
506
527
|
|
507
528
|
if src = @params[:src]
|
508
|
-
finder = ::RubyLess.translate(@params[:src]
|
529
|
+
finder = ::RubyLess.translate(self, @params[:src]) #build_finder(:first, @params[:src])
|
509
530
|
return parser_error("invalid class (#{finder.klass})") unless finder.klass <= Node
|
510
531
|
|
511
532
|
img = finder
|
@@ -522,7 +543,7 @@ module Zena
|
|
522
543
|
res += ", :host => #{@context["exp_host"]}" if @context["exp_host"]
|
523
544
|
res += ")"
|
524
545
|
if finder = @params[:link]
|
525
|
-
finder = ::RubyLess.translate(
|
546
|
+
finder = ::RubyLess.translate(self, finder)
|
526
547
|
|
527
548
|
return parser_error("Invalid class (#{finder.klass})") unless finder.klass <= Node
|
528
549
|
|
@@ -586,8 +607,15 @@ module Zena
|
|
586
607
|
end
|
587
608
|
|
588
609
|
def show_time(method)
|
610
|
+
if tformat = @params.delete(:tformat)
|
611
|
+
tformat = RubyLess.translate(self, "t(%Q{#{tformat}})")
|
612
|
+
method = "#{method}, :format => #{tformat}"
|
613
|
+
end
|
614
|
+
|
589
615
|
if hash_arguments = extract_from_params(:tz, :lang, :format)
|
590
616
|
"<%= format_date(#{method}, #{hash_arguments.join(', ')}) %>"
|
617
|
+
elsif tformat
|
618
|
+
"<%= format_date(#{method}) %>"
|
591
619
|
else
|
592
620
|
"<%= #{method} %>"
|
593
621
|
end
|
data/lib/zena/use/forms.rb
CHANGED
@@ -2,6 +2,13 @@ module Zena
|
|
2
2
|
module Use
|
3
3
|
module Forms
|
4
4
|
module ViewMethods
|
5
|
+
|
6
|
+
# Create a new instance of the given class name
|
7
|
+
def new_instance(class_name, params = {})
|
8
|
+
return nil unless klass = Node.get_class(class_name, :create => true)
|
9
|
+
klass.new_instance(Node.transform_attributes(params))
|
10
|
+
end
|
11
|
+
|
5
12
|
def make_checkbox(node, values, relation_name, attribute)
|
6
13
|
relation_proxy = node.relation_proxy(relation_name)
|
7
14
|
return nil unless values && relation_proxy
|
@@ -39,6 +46,43 @@ module Zena
|
|
39
46
|
end # ViewMethods
|
40
47
|
|
41
48
|
module ZafuMethods
|
49
|
+
|
50
|
+
# Enter the context of a newly created object
|
51
|
+
def r_new
|
52
|
+
return parser_error("missing 'klass' parameter") unless class_name = @params[:klass]
|
53
|
+
return parser_error("invalid 'klass' parameter (not a Node)") unless klass = get_class(class_name)
|
54
|
+
|
55
|
+
res = []
|
56
|
+
keys = {:klass => 'klass'}
|
57
|
+
@params.each do |key, value|
|
58
|
+
next if key == :klass
|
59
|
+
# TODO: maybe it would be safer to check with [:"key="] and change safe_property to
|
60
|
+
# authorize both ?
|
61
|
+
next unless type = klass.safe_method_type([key.to_s])
|
62
|
+
# Store how to access current value to show hidden field in form.
|
63
|
+
keys[key] = type[:method]
|
64
|
+
res << ":#{key} => #{RubyLess.translate_string(self, value)}"
|
65
|
+
end
|
66
|
+
|
67
|
+
if res == []
|
68
|
+
method = "new_instance(#{class_name.inspect})"
|
69
|
+
else
|
70
|
+
method = "new_instance(#{class_name.inspect}, #{res.join(', ')})"
|
71
|
+
end
|
72
|
+
|
73
|
+
expand_with_finder(
|
74
|
+
:method => method,
|
75
|
+
:class => klass,
|
76
|
+
:nil => true,
|
77
|
+
:new_keys => keys
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def r_errors
|
82
|
+
# Very basic for the moment
|
83
|
+
"<%= error_messages_for(#{node.form_name}, :object => #{node}) %>"
|
84
|
+
end
|
85
|
+
|
42
86
|
def make_input(form_helper, name, type, textarea = false)
|
43
87
|
if type == Time
|
44
88
|
"<%= date_box(#{node}, :#{name}) %>"
|
@@ -112,19 +156,31 @@ module Zena
|
|
112
156
|
# Saved form
|
113
157
|
opts[:id] = "<%= ndom_id(#{node}) %>"
|
114
158
|
|
115
|
-
opts[:form_tag] =
|
116
|
-
<% remote_form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path : #{node.form_name}_path(#{node}), :method => #{node}.new_record? ? :post : :put, :
|
117
|
-
|
159
|
+
opts[:form_tag] = %Q{
|
160
|
+
<% remote_form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path : #{node.form_name}_path(#{node}.zip), :html => {:method => #{node}.new_record? ? :post : :put, :id => \"\#{ndom_id(#{node})}_form_t\"}) do |f| %>
|
161
|
+
}
|
118
162
|
|
119
|
-
opts[:form_cancel] =
|
163
|
+
opts[:form_cancel] = %Q{
|
120
164
|
<% if #{node}.new_record? -%>
|
121
165
|
<p class='btn_x'><a href='#' onclick='[\"<%= params[:dom_id] %>_add\", \"<%= params[:dom_id] %>_form\"].each(Element.toggle);return false;'>#{_('btn_x')}</a></p>
|
122
166
|
<% else -%>
|
123
|
-
<p class='btn_x'><%= link_to_remote(#{_('btn_x').inspect}, :url => #{node.form_name}_path(#{node}.
|
167
|
+
<p class='btn_x'><%= link_to_remote(#{_('btn_x').inspect}, :url => #{node.form_name}_path(#{node}.zip) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=\#{params[:dom_id]}#{@context[:has_link_id] ? "&link_id=\#{#{node}.link_id}" : ''}\", :method => :get) %></p>
|
124
168
|
<% end -%>
|
125
|
-
|
169
|
+
}
|
126
170
|
end
|
171
|
+
else
|
172
|
+
# no ajax
|
173
|
+
if descendants('errors')
|
174
|
+
error_messages = ''
|
175
|
+
else
|
176
|
+
error_messages = r_errors + "\n"
|
177
|
+
end
|
178
|
+
|
179
|
+
opts[:form_tag] = %Q{
|
180
|
+
<% form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path : #{node.form_name}_path(#{node}.zip), :html => {:method => #{node}.new_record? ? :post : :put, :id => \"\#{ndom_id(#{node})}_form_t\"}) do |f| %>
|
181
|
+
#{error_messages}}
|
127
182
|
end
|
183
|
+
|
128
184
|
opts
|
129
185
|
end
|
130
186
|
|
@@ -234,8 +290,27 @@ END_TXT
|
|
234
290
|
|
235
291
|
hidden_fields['node[v_status]'] = Zena::Status[:pub].to_s if add_params[:publish] || auto_publish_param
|
236
292
|
|
293
|
+
# All default values set in the <r:new> field should at least appear as hidden fields
|
294
|
+
if new_keys = node.opts[:new_keys]
|
295
|
+
input_keys = (
|
296
|
+
(descendants('input') || []).map {|e| e.params[:name]} +
|
297
|
+
hidden_fields.keys.map do |e|
|
298
|
+
if e =~ /.*\[(.*)\]/
|
299
|
+
$1.to_sym
|
300
|
+
else
|
301
|
+
nil
|
302
|
+
end
|
303
|
+
end
|
304
|
+
).compact.uniq
|
305
|
+
|
306
|
+
new_keys.each do |key, value|
|
307
|
+
next if input_keys.include?(key)
|
308
|
+
hidden_fields["node[#{key}]"] = "<%= #{node}.#{value} %>"
|
309
|
+
end
|
310
|
+
end
|
237
311
|
# ===
|
238
312
|
# TODO: reject set_fields from hidden_fields
|
313
|
+
# ? what is this ?
|
239
314
|
# ===
|
240
315
|
|
241
316
|
hidden_fields.reject! do |k,v|
|
@@ -257,7 +332,7 @@ END_TXT
|
|
257
332
|
return parser_error("missing name") unless attribute
|
258
333
|
|
259
334
|
if value = @params[:selected]
|
260
|
-
selected = ::RubyLess.translate_string(
|
335
|
+
selected = ::RubyLess.translate_string(self, value)
|
261
336
|
elsif @context[:in_filter]
|
262
337
|
selected = "params[#{attribute.to_sym.inspect}].to_s"
|
263
338
|
elsif %w{parent_id}.include?(attribute)
|
@@ -396,13 +471,13 @@ END_TXT
|
|
396
471
|
|
397
472
|
if sub_attr
|
398
473
|
type = node.klass.safe_method_type([attribute])
|
399
|
-
if sub_attr_ruby = RubyLess.translate(%Q{this.#{attribute}[#{sub_attr.inspect}]}
|
474
|
+
if sub_attr_ruby = RubyLess.translate(self, %Q{this.#{attribute}[#{sub_attr.inspect}]})
|
400
475
|
res[:value] = "<%= fquote #{sub_attr_ruby} %>"
|
401
476
|
end
|
402
477
|
else
|
403
478
|
if value = params[:value]
|
404
479
|
# On refactor, use append_markup_attr(markup, key, value)
|
405
|
-
value = RubyLess.translate_string(
|
480
|
+
value = RubyLess.translate_string(self, value)
|
406
481
|
|
407
482
|
if value.literal
|
408
483
|
res[:value] = value.literal.to_s.gsub("'",''')
|
@@ -432,6 +507,9 @@ END_TXT
|
|
432
507
|
# res[:value] = ["''"]
|
433
508
|
# end
|
434
509
|
#end
|
510
|
+
elsif node.will_be?(Column)
|
511
|
+
res[:name] = "node[<%= #{node}.name %>]"
|
512
|
+
res[:value] = "<%= fquote #{node(Node)}.prop[#{node}.name] %>"
|
435
513
|
end
|
436
514
|
|
437
515
|
if node.dom_prefix
|
@@ -474,7 +552,7 @@ END_TXT
|
|
474
552
|
|
475
553
|
# Get current attribute in forms
|
476
554
|
def node_attribute(attribute)
|
477
|
-
node_attribute = ::RubyLess.translate(
|
555
|
+
node_attribute = ::RubyLess.translate(node.klass, attribute)
|
478
556
|
"#{node}.#{node_attribute}"
|
479
557
|
rescue ::RubyLess::NoMethodError
|
480
558
|
if node.will_be?(Node)
|
@@ -517,8 +595,8 @@ END_TXT
|
|
517
595
|
nodes = finder[:method]
|
518
596
|
end
|
519
597
|
|
520
|
-
set_attr = ::RubyLess.translate(@params[:attr] || 'id'
|
521
|
-
show_attr = ::RubyLess.translate(@params[:show] || 'title'
|
598
|
+
set_attr = ::RubyLess.translate(klass, @params[:attr] || 'id')
|
599
|
+
show_attr = ::RubyLess.translate(klass, @params[:show] || 'title')
|
522
600
|
|
523
601
|
options_list = "[['','']] + (#{nodes} || []).map{|r| [r.#{show_attr}, r.#{set_attr}.to_s]}"
|
524
602
|
elsif values = @params[:values]
|