ezframe 0.0.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +1 -1
  4. data/asset/css/materialize.min.css +13 -0
  5. data/asset/css/style.css +3 -0
  6. data/asset/html/index.html +1 -0
  7. data/{app_template/asset/image/favicon.ico → asset/image/c_e.ico} +0 -0
  8. data/asset/js/ezframe.js +387 -0
  9. data/exe/check_column_yml +64 -0
  10. data/exe/console +2 -2
  11. data/exe/{create_table.rb → create_table} +7 -4
  12. data/exe/dbmigrate +174 -0
  13. data/exe/html2ruby +61 -0
  14. data/ezframe.gemspec +10 -8
  15. data/lib/ezframe.rb +9 -3
  16. data/lib/ezframe/auth.rb +50 -31
  17. data/lib/ezframe/column_set.rb +314 -103
  18. data/lib/ezframe/column_type.rb +456 -99
  19. data/lib/ezframe/config.rb +27 -6
  20. data/lib/ezframe/controller.rb +41 -38
  21. data/lib/ezframe/database.rb +171 -52
  22. data/lib/ezframe/editor_common.rb +74 -0
  23. data/lib/ezframe/email.rb +34 -0
  24. data/lib/ezframe/ezlog.rb +40 -0
  25. data/lib/ezframe/ht.rb +42 -17
  26. data/lib/ezframe/html.rb +47 -31
  27. data/lib/ezframe/japanese_utils.rb +15 -0
  28. data/lib/ezframe/jquery-ui.rb +29 -0
  29. data/lib/ezframe/loader.rb +4 -4
  30. data/lib/ezframe/main_editor.rb +19 -0
  31. data/lib/ezframe/main_page_kit.rb +226 -0
  32. data/lib/ezframe/materialize.rb +10 -14
  33. data/lib/ezframe/message.rb +46 -0
  34. data/lib/ezframe/page_base.rb +59 -71
  35. data/lib/ezframe/route.rb +126 -0
  36. data/lib/ezframe/server.rb +16 -5
  37. data/lib/ezframe/single_page_editor.rb +22 -0
  38. data/lib/ezframe/single_page_kit.rb +199 -0
  39. data/lib/ezframe/sub_editor.rb +25 -0
  40. data/lib/ezframe/sub_page_kit.rb +213 -0
  41. data/lib/ezframe/template.rb +5 -4
  42. data/lib/ezframe/util.rb +45 -23
  43. data/lib/ezframe/version.rb +1 -1
  44. metadata +74 -34
  45. data/.rubocop.yml +0 -44
  46. data/app_template/asset/js/ezframe.js +0 -288
  47. data/app_template/config.ru +0 -10
  48. data/app_template/config/generic.yml +0 -3
  49. data/app_template/config/materialize.yml +0 -5
  50. data/app_template/pages/basic.rb +0 -5
  51. data/exe/setup.rb +0 -15
  52. data/lib/ezframe/editor.rb +0 -188
  53. data/lib/ezframe/model.rb +0 -52
  54. data/lib/ezframe/page_kit.rb +0 -63
@@ -0,0 +1,34 @@
1
+ require "mail"
2
+
3
+ module Ezframe
4
+ class Email
5
+ class << self
6
+ def receive
7
+
8
+ end
9
+
10
+ # options =
11
+ # :address => "smtp.server.host",
12
+ # :port => 1025,
13
+ # :user_name => login user,
14
+ # :password => login password,
15
+ # :authentication => 'plain',
16
+ # :ssl => true,
17
+ def setup_smtp(options)
18
+ Mail.defaults do
19
+ delivery_method :smtp, options
20
+ end
21
+ end
22
+
23
+ def send(data)
24
+ mail = Mail.new do
25
+ from data[:mail_from]
26
+ to data[:mail_to]
27
+ subject data[:subject]
28
+ body data[:body]
29
+ end
30
+ mail.deliver!
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ module Ezframe
2
+ class EzLog
3
+ class << self
4
+ @instance = nil
5
+
6
+ def writer(level="", msg)
7
+ # unless @instance
8
+ # @instance = File.open("log/#{ENV['RACK_ENV']||'development'}.log", "a+")
9
+ # @instance.sync = true
10
+ # end
11
+ # @instance.puts "#{Time.now.to_s}:#{level.upcase}:#{msg}"
12
+ File.open("log/#{ENV['RACK_ENV']||'development'}.log", "a+") {|f| f.puts "#{Time.now.to_s}:#{level.upcase}:#{msg}"}
13
+ end
14
+
15
+ def level=(lv)
16
+ @level = lv
17
+ end
18
+
19
+ def info(msg)
20
+ writer("info", msg)
21
+ end
22
+
23
+ def debug(msg)
24
+ writer("debug", msg)
25
+ end
26
+
27
+ def warn(msg)
28
+ writer("warn", msg)
29
+ end
30
+
31
+ def error(msg)
32
+ writer("debug", msg)
33
+ end
34
+
35
+ def <<(msg)
36
+ writer("", msg)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -3,24 +3,33 @@ module Ezframe
3
3
  module Ht
4
4
  class << self
5
5
  # メソッド名の名前のタグのhthashを生成
6
- def wrap_tag(opts = {})
7
- if opts.is_a?(String) || opts.is_a?(Array)
8
- h = { child: opts }
9
- elsif opts.is_a?(Hash)
10
- if opts[:tag] && !__callee__.to_s.index("wrap_tag")
11
- h = { child: opts }
6
+ def wrap_tag(ht_h = {})
7
+ return nil unless ht_h
8
+ if ht_h.is_a?(String) || ht_h.is_a?(Array)
9
+ h = { child: ht_h }
10
+ elsif ht_h.is_a?(Hash)
11
+ if ht_h[:tag] && !__callee__.to_s.index("wrap_tag")
12
+ h = { child: ht_h }
12
13
  else
13
- h = opts.dup
14
+ h = ht_h.dup
14
15
  end
15
16
  else
16
- mylog("wrap_tag: unknown type: #{opts.inspect}")
17
+ EzLog.info("[WARN] wrap_tag: unknown type: #{ht_h.inspect}")
17
18
  return nil
18
19
  end
19
20
  h[:tag] ||= __callee__.to_s
21
+ h[:wrap] = true
20
22
  raise "no tag" if h[:tag] == "wrap_tag"
21
23
  return h
22
24
  end
23
25
 
26
+ def single_tag(ht_h = {})
27
+ ht_h[:tag] ||= __callee__.to_s
28
+ raise "no tag" if ht_h[:tag] == "wrap_tag"
29
+ raise "has child: #{ht_h.inspect}" if ht_h[:child]
30
+ return ht_h
31
+ end
32
+
24
33
  alias_method :script, :wrap_tag
25
34
 
26
35
  alias_method :h1, :wrap_tag
@@ -30,8 +39,8 @@ module Ezframe
30
39
  alias_method :h5, :wrap_tag
31
40
  alias_method :h6, :wrap_tag
32
41
  alias_method :p, :wrap_tag
33
- alias_method :br, :wrap_tag
34
- alias_method :hr, :wrap_tag
42
+ alias_method :br, :single_tag
43
+ alias_method :hr, :single_tag
35
44
  alias_method :div, :wrap_tag
36
45
  alias_method :span, :wrap_tag
37
46
  alias_method :i, :wrap_tag
@@ -45,11 +54,12 @@ module Ezframe
45
54
  alias_method :tr, :wrap_tag
46
55
  alias_method :th, :wrap_tag
47
56
  alias_method :td, :wrap_tag
48
- alias_method :img, :wrap_tag
57
+ alias_method :img, :single_tag
49
58
  alias_method :a, :wrap_tag
50
59
  alias_method :form, :wrap_tag
51
- alias_method :input, :wrap_tag
60
+ alias_method :input, :single_tag
52
61
  alias_method :select, :wrap_tag
62
+ alias_method :option, :wrap_tag
53
63
  alias_method :textarea, :wrap_tag
54
64
  alias_method :label, :wrap_tag
55
65
  alias_method :fieldset, :wrap_tag
@@ -57,6 +67,8 @@ module Ezframe
57
67
  alias_method :footer, :wrap_tag
58
68
 
59
69
  alias_method :small, :wrap_tag
70
+ alias_method :pre, :wrap_tag
71
+ alias_method :iframe, :wrap_tag
60
72
 
61
73
  alias_method :checkbox, :wrap_tag
62
74
  alias_method :radio, :wrap_tag
@@ -69,7 +81,7 @@ module Ezframe
69
81
  h[:tag] = "icon"
70
82
  return wrap_tag(h)
71
83
  elsif arg.is_a?(String)
72
- return { tag: "icon", name: arg }
84
+ return { tag: "icon", wrap: true, name: arg }
73
85
  end
74
86
  end
75
87
 
@@ -88,6 +100,21 @@ module Ezframe
88
100
  end
89
101
  return child
90
102
  end
103
+
104
+ def search(ht_h, opts)
105
+ @found ||= []
106
+ if ht_h.is_a?(Hash)
107
+ if opts[:tag] && ht_h[:tag] && ht_h[:tag] == opts[:tag]
108
+ @found.push(ht_h)
109
+ end
110
+ if ht_h[:child]
111
+ search(ht_h[:child], opts)
112
+ end
113
+ elsif ht_h.is_a?(Array)
114
+ ht_h.map { |h| search(h, opts) }
115
+ end
116
+ return @found
117
+ end
91
118
  end
92
119
 
93
120
  # 配列を<UL><OL>要素に変換するためのクラス
@@ -95,10 +122,8 @@ module Ezframe
95
122
  attr_accessor :tag
96
123
  def to_h(opts = {})
97
124
  return nil if self.empty?
98
- child = self.map do |elem|
99
- { tag: "li", child: elem }
100
- end
101
- h = { tag: @tag, child: child }
125
+ child = self.map { |elem| Ht.li(elem) }
126
+ h = { tag: @tag, wrap: true, child: child }
102
127
  h.update(opts)
103
128
  return h
104
129
  end
@@ -4,6 +4,7 @@ module Ezframe
4
4
  class Html
5
5
  class << self
6
6
  def convert(ht_h = {})
7
+ ht_h = hook_for_convert(ht_h)
7
8
  return "" if ht_h.nil? || ht_h.to_s.empty?
8
9
  return ht_h.to_html if ht_h.respond_to?(:to_html)
9
10
  return ht_h.to_s if ht_h.is_a?(String) || ht_h.is_a?(Symbol) || ht_h.is_a?(Integer) || ht_h.is_a?(Time)
@@ -11,24 +12,38 @@ module Ezframe
11
12
 
12
13
  tag = ht_h[:tag]
13
14
  case tag
14
- when "input"
15
- input(ht_h)
15
+ when "textarea"
16
+ textarea(ht_h)
16
17
  when "select"
17
- return select(ht_h) if ht_h[:items]
18
+ return select(ht_h) if ht_h[:item]
18
19
  when "icon"
19
20
  tag = "i"
20
21
  end
21
- opt_s, child_s = join_attributes(ht_h)
22
- if child_s.length >= 0
23
- return "<#{ht_h[:tag]} #{opt_s}>\n#{child_s}\n</#{ht_h[:tag]}>\n"
22
+ tag = ht_h[:tag]
23
+ join_info = join_attribute(ht_h)
24
+ start_tag = [ht_h[:tag], join_info[:attr]].compact.join(" ").strip
25
+ if ht_h[:wrap] # !child_s.strip.empty? ||
26
+ return "#{join_info[:before]}<#{start_tag}>#{join_info[:child]}</#{ht_h[:tag]}>#{join_info[:after]}"
24
27
  end
25
- "<#{ht_h[:tag]} #{opt_s}/>"
28
+ # tag_content = [ ht_h[:tag], join_info[:attr] ].compact.join(" ")
29
+ return "#{join_info[:before]}<#{start_tag}/>#{join_info[:after]}"
26
30
  end
27
31
 
28
- def join_attributes(attrs)
32
+ # attributeの連結文字列化
33
+ def join_attribute(attrs)
29
34
  child_s = ""
35
+ before = ""
36
+ after = ""
30
37
  opt_a = attrs.map do |k, v|
31
38
  case k
39
+ when :before
40
+ before = convert(v)
41
+ next
42
+ when :after
43
+ after = convert(v)
44
+ next
45
+ when :wrap
46
+ nil
32
47
  when :child
33
48
  child_s = convert(v)
34
49
  next
@@ -47,62 +62,63 @@ module Ezframe
47
62
  end
48
63
  end
49
64
  end
50
- [opt_a.compact.join(" "), child_s]
65
+ { attr: opt_a.compact.join(" "), before: before, after: after, child: child_s }
51
66
  end
52
67
 
53
- def input(ht_h)
54
- size = ht_h[:size]
55
- # puts "input: size=#{size.inspect}"
56
- if size && (size.index("x") || size.index("*"))
57
- if /(\d+)\s*[x\*]\s*(\d+)/ =~ size
58
- ht_h[:cols], ht_h[:rows] = $1, $2
59
- end
60
- ht_h[:tag] = "textarea"
61
- ht_h[:child] = ht_h[:value]
68
+ def textarea(ht_h)
69
+ value = ht_h[:value]
70
+ if value
71
+ ht_h[:child] = value
62
72
  ht_h.delete(:value)
63
- p ht_h
64
73
  end
65
74
  end
66
75
 
67
76
  def select(ht_h = {})
68
77
  attr = ht_h.clone
69
- items = attr[:items]
70
- # puts "Html.select: #{items}"
71
- if items.is_a?(Hash)
72
- option_a = ht_h[:items].map do |k, v|
73
- h = { tag: "option", value: k }
78
+ item = attr[:item]
79
+ # puts "Html.select: #{item}"
80
+ if item.is_a?(Hash)
81
+ option_a = ht_h[:item].map do |k, v|
82
+ h = Ht.option(value: k)
74
83
  if v.is_a?(Array)
75
84
  v, selected = v
76
85
  h[:selected] = "selected" if selected
77
86
  end
78
87
  h[:child] = v
79
- if ht_h[:default] && ht_h[:default] == v
88
+ # EzLog.info "select: hash: k=#{k}, v=#{v}, value=#{ht_h[:value]}"
89
+ if ht_h[:value] && ht_h[:value].to_s == k.to_s
80
90
  h[:selected] = "selected"
81
91
  end
82
92
  h
83
93
  end
84
- elsif items.is_a?(Array)
85
- option_a = items.map do |v|
86
- h = { tag: "option", value: v[0], child: v[1] }
94
+ elsif item.is_a?(Array)
95
+ option_a = item.map do |v|
96
+ h = Ht.option(value: v[0], child: v[1])
87
97
  if %w[selected default].include?(v[2])
88
98
  h[:selected] = "selected"
89
99
  end
90
- if ht_h[:default] && ht_h[:default] == v
100
+ # EzLog.info "select: array: v=#{v}, value=#{ht_h[:value]}"
101
+ if ht_h[:value] && ht_h[:value].to_s == v[0].to_s
91
102
  h[:selected] = "selected"
92
103
  end
93
104
  # puts h.inspect
94
105
  h
95
106
  end
96
107
  else
97
- warn "unknown items: #{ht_h.inspect}"
108
+ warn "unknown item: #{ht_h.inspect}"
98
109
  end
99
110
  attr[:tag] = "select"
100
111
  attr[:child] = option_a
101
112
  attr[:name] ||= attr[:key]
102
113
  attr[:final] = true
103
- attr.delete(:items)
114
+ attr[:wrap] = true
115
+ attr.delete(:item)
104
116
  Html.convert(attr)
105
117
  end
118
+
119
+ def hook_for_convert(ht_h)
120
+ return ht_h
121
+ end
106
122
  end
107
123
  end
108
124
  end
@@ -36,5 +36,20 @@ class Japanese
36
36
  return nil if !str
37
37
  return str.tr("ぁ-ん\-ー―−", "ァ-ン\-ー―−")
38
38
  end
39
+
40
+ def to_wday(wday)
41
+ return nil unless wday
42
+ return %w(日 月 火 水 木 金 土)[wday]
43
+ end
44
+
45
+ def to_datetime_str(tm)
46
+ return nil unless tm
47
+ return "%d年%2d月%2d日 %2d:%02d:%02d" %[ tm.year, tm.mon, tm.mday, tm.hour, tm.min, tm.sec ]
48
+ end
49
+
50
+ def to_date_str(tm)
51
+ return nil unless tm
52
+ return "%d年%2d月%2d日" %[ tm.year, tm.mon, tm.mday]
53
+ end
39
54
  end
40
55
  end
@@ -0,0 +1,29 @@
1
+ module Ezframe
2
+ class Jquery
3
+ class << self
4
+ def into_html_header
5
+ css_a = Config[:extra_css_list].map {|file| "<link href=\"#{file}\" rel=\"stylesheet\">\n" }
6
+ js_a = Config[:extra_js_list].map {|file| "<script src=\"#{file}\"></script>\n" }
7
+
8
+ css_files = Dir["./asset/css/*.css"]||[]
9
+ css_a += css_files.map do |file|
10
+ file.gsub!("./asset", "")
11
+ "<link href=\"#{file}\" rel=\"stylesheet\">\n"
12
+ end
13
+ js_files = Dir["./asset/js/*.js"]||[]
14
+ js_a += js_files.map do |file|
15
+ file.gsub!("./asset", "")
16
+ "<script src=\"#{file}\"></script>\n"
17
+ end
18
+ (css_a+js_a).join
19
+ end
20
+
21
+ def into_bottom_of_body
22
+ ""
23
+ end
24
+
25
+ def convert(ht_h)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if File.exist?("pages/common.rb")
4
- require "#{Dir.pwd}/pages/common.rb"
3
+ if File.exist?("page/common.rb")
4
+ require "#{Dir.pwd}/page/common.rb"
5
5
  end
6
- Dir["models/*.rb"].each do |file|
6
+ Dir["model/*.rb"].sort.each do |file|
7
7
  require "#{Dir.pwd}/#{file}"
8
8
  end
9
- Dir["pages/*.rb"].each do |file|
9
+ Dir["page/*.rb"].sort.each do |file|
10
10
  require "#{Dir.pwd}/#{file}"
11
11
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require_relative "main_page_kit"
3
+
4
+ module Ezframe
5
+ class MainEditor < PageBase
6
+ include EditorCommon
7
+ include MainPageKit::Default
8
+ include MainPageKit::Index
9
+ include MainPageKit::Edit
10
+ include MainPageKit::Detail
11
+
12
+ def init_vars
13
+ super
14
+ @sort_key = :id
15
+ @event = @parsed_body[:ezevent] if @parsed_body
16
+ @dom_id = { create: "create-area", edit: "edit-area", index: "index-area", detail: "detail-area"}
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,226 @@
1
+ module Ezframe
2
+ module MainPageKit
3
+ module Default
4
+ def public_default_get
5
+ @id = get_id
6
+ div = [Ht.div(id: @dom_id[:create], child: make_index_top), Ht.div(id: @dom_id[:index], child: "", ezload: "url=#{make_base_url}")]
7
+ layout = index_layout(center: make_form(make_base_url, div))
8
+ return show_base_template(title: Message[:index_page_title], body: Html.convert(layout))
9
+ end
10
+ end
11
+
12
+ # 一覧テーブルの生成
13
+ module Index
14
+ def public_default_post
15
+ return { inject: "#main-box", body: [ Ht.div(make_index_top), Ht.div(make_index_table)], set_url: make_base_url }
16
+ end
17
+
18
+ def make_index_table
19
+ data_a = list_for_index
20
+ EzLog.debug("make_index_table: #{data_a.length}")
21
+ target_keys = @index_keys
22
+ unless target_keys
23
+ target_keys = @column_set.keys.select { |k| !@column_set[k].no_view? }
24
+ end
25
+ tr_a = data_a.map do |data|
26
+ @column_set.clear
27
+ @column_set.set_values(data, from_db: true)
28
+ line = target_keys.map do |key|
29
+ view = @column_set[key].view
30
+ Ht.td(Ht.a(href: "#{make_base_url(data[:id])}", child: view))
31
+ end
32
+ Ht.tr(line)
33
+ end
34
+ th_a = target_keys.map { |key| Ht.th(@column_set[key.to_sym].label) }
35
+ thead = Ht.thead(Ht.tr(th_a))
36
+ tbody = Ht.tbody(tr_a)
37
+ table_id = "enable_datatable_#{@class_snake}"
38
+ return Ht.table(id: table_id, class: %w[enable_datatable], child: [thead, tbody], ezload: "command=enable_datatable:target=##{table_id}:size=10")
39
+ end
40
+
41
+ # 一覧ページの上部に表示するボタン等の生成
42
+ def make_index_top
43
+ make_create_button
44
+ end
45
+ end
46
+
47
+ module Edit
48
+ # 新規登録フォーム表示
49
+ def public_create_get
50
+ @column_set.clear
51
+ table = make_edit_form(:create)
52
+ layout = main_layout(center: make_form("#{make_base_url}/create", table), type: 2)
53
+ show_base_template(title: Message[:parent_create_page_title], body: Html.convert(layout))
54
+ end
55
+
56
+ # 新規登録受信
57
+ def public_create_post
58
+ validation = @column_set.validate(@form)
59
+ EzLog.debug("public_create_post: event=#{@event}, form=#{@form}")
60
+ if @event[:branch] == "single_validate"
61
+ EzLog.debug("public_create_post: single validate")
62
+ return single_validation(validation, @event[:target_key] || @form.keys[0])
63
+ end
64
+ unless @form
65
+ url = "#{make_base_url}/create"
66
+ return { inject: "#center-panel", body: Html.convert(make_form(url, make_edit_form(:create))), set_url: url }
67
+ else
68
+ if count_errors(validation) > 0
69
+ cmd_a = full_validation(validation)
70
+ EzLog.debug("public_create_post: cmd_a=#{cmd_a}")
71
+ return cmd_a if cmd_a.length > 0
72
+ end
73
+ # 値の保存
74
+ id = create_data(@form)
75
+ return { redirect: make_base_url(id) }
76
+ end
77
+ end
78
+
79
+ # データ編集受信
80
+ def public_edit_post
81
+ EzLog.debug("public_edit_post: #{@form}")
82
+ @id = get_id
83
+ validation = @column_set.validate(@form)
84
+ if @event[:branch] == "single_validate"
85
+ EzLog.debug("public_edit_post: single validate:event=#{@event}, form=#{@form}")
86
+ return single_validation(validation, @event[:target_key])
87
+ end
88
+ unless @form
89
+ data = @column_set.set_from_db(@id)
90
+ return show_message_page("no data", "data is not defined: #{@id}") unless data
91
+ return { inject: "#center-panel", body: Html.convert(make_form("#{make_base_url}/edit", make_edit_form)) }
92
+ else
93
+ if count_errors(validation) > 0
94
+ cmd_a = full_validation(validation)
95
+ return cmd_a
96
+ end
97
+ # 値を保存
98
+ update_data(@id, @form)
99
+ return { redirect: make_base_url(@id) }
100
+ end
101
+ end
102
+
103
+ # 自動入力を行う
104
+ def exec_completion
105
+ return nil
106
+ end
107
+
108
+ # 編集フォームの生成
109
+ def make_edit_form(command = :edit)
110
+ table = []
111
+ matrix = @column_set.map do |column|
112
+ next if column.no_edit?
113
+ form = column.form
114
+ table.push Ht.p([Ht.small(column.label), form]) if form
115
+ end
116
+ send_button = Ht.button(id: "edit-finish-button", child: Message[:edit_finish_button_label], class: %w[btn], ezevent: "on=click:url=#{make_base_url}/#{command}:with=form")
117
+ cancel_button = edit_cancel_button
118
+ cancel_button[:event] = "on=click:command=redirect:url=#{make_base_url}"
119
+ table.push(Ht.p([send_button, cancel_button]))
120
+ return table
121
+ end
122
+
123
+ # 1カラムに対してだけバリデーションを行う。
124
+ def single_validation(validate_h, target_key)
125
+ EzLog.debug("single_validation: validate_h=#{validate_h}, target_key=#{target_key}")
126
+ unless target_key
127
+ raise "target_key is empty: #{validate_h}"
128
+ return []
129
+ end
130
+ cmd_a = []
131
+ if validate_h[target_key.to_sym]
132
+ cmd_a = show_validate_result(validate_h)
133
+ end
134
+ if count_errors(validate_h) == 0
135
+ cmd_a.unshift({ reset_error: "#error-box-#{target_key}" })
136
+ end
137
+ comp_a = exec_completion(@form)
138
+ cmd_a += comp_a if comp_a
139
+ EzLog.debug("reset_error: #error-box-#{target_key}")
140
+ EzLog.debug("single_validation: target_key=#{target_key}, validate_h=#{validate_h}, count=#{count_errors(validate_h)}, cmd_a=#{cmd_a}")
141
+ return cmd_a
142
+ end
143
+
144
+ # 全てのカラムに対してバリデーションを行う
145
+ def full_validation(validate_h)
146
+ cmd_a = show_validate_result(validate_h)
147
+ cmd_a.unshift({ reset_error: ".error-box" })
148
+ EzLog.debug("full_validation: full, cmd_a=#{cmd_a}")
149
+ return cmd_a
150
+ end
151
+
152
+ # フォームの値の有効性チェックし、ajax用返信ハッシュを生成
153
+ def show_validate_result(validate_result)
154
+ cmd_a = []
155
+ validate_result.each do |key, status|
156
+ norm, err = status
157
+ EzLog.debug("norm=#{norm}, err=#{err}")
158
+ if norm
159
+ cmd_a.push({ set_value: "input[name=#{key}]", value: norm })
160
+ end
161
+ if err
162
+ msg = Message[err.to_sym] || err
163
+ cmd_a.push({ set_error: "#error-box-#{key}", value: msg })
164
+ end
165
+ end
166
+ return cmd_a
167
+ end
168
+
169
+ # validate_resultの中のエラーの数を数える
170
+ def count_errors(validate_result)
171
+ return validate_result.count { |k, a| a[1] }
172
+ end
173
+
174
+ def edit_cancel_button
175
+ Ht.span(class: %w[btn red small waves-effect waves-light switch-button], child: Ht.icon("clear"))
176
+ end
177
+
178
+ def make_create_button(event = nil)
179
+ event ||= "on=click:command=redirect:url=#{make_base_url}/create"
180
+ return Ht.button(class: %w[btn], child: [Ht.icon("add"), Message[:create_button_label]], ezevent: event)
181
+ end
182
+ end
183
+
184
+ # 詳細表示
185
+ module Detail
186
+ def make_detail_page
187
+ # EzLog.info "make_detail_page: #{@request.params.inspect}"
188
+ id = get_id(@class_snake)
189
+ unless @column_set.set_from_db(id)
190
+ return show_message_page("no data", "data is not defined: #{id}")
191
+ end
192
+ right = nil
193
+ right = right_tabs if @with_right_tabs
194
+ layout = main_layout(center: make_detail_table, right: right)
195
+ return show_base_template(title: Message[:customer_detail], body: Html.convert(layout))
196
+ end
197
+
198
+ # 詳細ページの表の生成
199
+ def make_detail_table
200
+ table = []
201
+ array = @column_set.map do |column|
202
+ next if column.no_view?
203
+ edit_btn = nil
204
+ if column.type.to_s == "textarea"
205
+ view = Ht.pre(id: "#{@class_snake}-#{column.key}-view", child: column.view)
206
+ else
207
+ view = Ht.span(id: "#{@class_snake}-#{column.key}-view", child: column.view)
208
+ end
209
+ table.push Ht.p(class: %w[hover-button-box], child: [Ht.small(column.label), view, edit_btn].compact)
210
+ end
211
+ edit_btn = Ht.button(id: "#{@class_snake}-detail-edit-button", class: %w[btn], child: [Ht.icon("edit"), Message[:edit_button_label]], ezevent: "on=click:url=#{make_base_url}/edit")
212
+ table.push edit_btn
213
+ return table
214
+ end
215
+
216
+ # 一覧ページ用のデータリスト生成
217
+ def list_for_index(where: nil)
218
+ where ||= {}
219
+ where[:deleted_at] = nil
220
+ sql = @column_set.dataset.where(where).order(@sort_key).sql
221
+ EzLog.debug("list_for_index: #{sql}")
222
+ return @column_set.dataset.where(where).order(@sort_key).all
223
+ end
224
+ end
225
+ end
226
+ end