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,199 @@
1
+ module Ezframe
2
+ module PageKit
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
+
11
+ def public_default_post
12
+ return { inject: "##{@dom_id[:index]}", body: Html.convert(make_index_table), set_url: make_base_url }
13
+ end
14
+ end
15
+
16
+ module Index
17
+ def make_index_top
18
+ make_create_button("on=click:url=#{make_base_url}/create")
19
+ end
20
+
21
+ # 一覧表の生成
22
+ def make_index_table
23
+ list = list_for_index
24
+ target_keys = @index_keys
25
+ unless target_keys
26
+ target_keys = @column_set.keys.select { |k| !@column_set[k].no_view? }
27
+ end
28
+ labels = @table_labels
29
+ unless labels
30
+ labels = target_keys.map { |k| @column_set[k].label(force: true) || " " }
31
+ end
32
+ # 項目名欄の生成
33
+ thead = Ht.thead(Ht.tr(labels.map { |label| Ht.th(label || " ") }))
34
+
35
+ tr_a = list.map do |data|
36
+ view_a = make_index_line(target_keys, data)
37
+ td_a = view_a.map { |view| Ht.td(view) }
38
+ Ht.tr(id: "tr-#{@class_snake}-#{data[:id]}", child: td_a, ezevent: "on=click:url=#{make_base_url(data[:id])}/detail")
39
+ end
40
+ tbody = Ht.tbody(tr_a)
41
+ return [
42
+ Ht.table(id: "enable_datatable_#{@class_snake}", child: [thead, tbody], ezload: "command=enable_datatable:target=#enable_datatable_#{@class_snake}"),
43
+ Ht.div(id: @dom_id[:detail], child: ""),
44
+ ]
45
+ end
46
+
47
+ # 一覧表示の1行を生成
48
+ def make_index_line(target_keys, data)
49
+ @column_set.clear
50
+ @column_set.values = data
51
+ return target_keys.map { |key| make_index_column(key) }
52
+ end
53
+
54
+ # 一覧表示の1カラムを生成
55
+ def make_index_column(key)
56
+ column = @column_set[key.to_sym]
57
+ return column.view(force: true)
58
+ end
59
+
60
+ # 一覧ページ用のデータリスト生成
61
+ def list_for_index
62
+ return @column_set.dataset.where(deleted_at: nil).order(@sort_key).all
63
+ end
64
+
65
+ # 一覧ページ用ボタン
66
+ def button_for_index_line(data)
67
+ return Ht.button(class: %w[btn right], ezevent: "on=click:url=#{make_base_url(data[:id])}/edit", child: [Ht.icon("edit"), Message[:edit_button_label]])
68
+ end
69
+ end
70
+
71
+ module Edit
72
+ # 新規データ登録
73
+ def public_create_post
74
+ @form = @event[:form]
75
+ EzLog.debug("public_create_post: event=#{@event}")
76
+ if @event[:cancel]
77
+ return { inject: "##{@dom_id[:create]}", body: Html.convert(make_index_top) }
78
+ elsif !@form
79
+ return { inject: "##{@dom_id[:create]}", body: Html.convert(make_edit_form(:create)) }
80
+ else
81
+ # 値の保存
82
+ @column_set.clear
83
+ form_values = @form
84
+ form_values.update(@env["url_params"])
85
+ # @column_set.values = form_values
86
+ @column_set[:id].value = @id = @column_set.create(form_values)
87
+ return { redirect: make_base_url(@id) }
88
+ # return public_default_post
89
+ end
90
+ end
91
+
92
+ # データ編集受信
93
+ def public_edit_post
94
+ @id = get_id
95
+ validation = @column_set.validate(@form)
96
+ if @event[:branch] == "single_validate"
97
+ EzLog.debug("public_edit_post: single validate:event=#{@event}, form=#{@form}")
98
+ return single_validation(validation, @event[:target_key])
99
+ end
100
+ unless @event[:form]
101
+ data = @column_set.set_from_db(@id)
102
+ return show_message_page("no data", "data is not defined: #{@id}") unless data
103
+ # フォームの表示
104
+ form = make_edit_form
105
+ found_a = Ht.search(form, tag: "input")
106
+ found_a.each { |h| h.add_class("#{@class_snake}-edit-box") if h[:size] }
107
+ return { inject: "##{@dom_id[:detail]}", body: Html.convert(form) }
108
+ else
109
+ if @event[:cancel]
110
+ data = @column_set.set_from_db(@id)
111
+ return act_after_cancel
112
+ else
113
+ # 値を保存
114
+ @column_set.update(@id, @event[:form])
115
+ end
116
+ return act_after_edit
117
+ end
118
+ end
119
+
120
+ # 編集フォームの生成
121
+ def make_edit_form(command = :edit)
122
+ @id ||= get_id
123
+ target_keys = @edit_keys || @column_set.keys
124
+ list = target_keys.map do |colkey|
125
+ column = @column_set[colkey.to_sym]
126
+ unless column
127
+ EzLog.error("undefined column entry: #{colkey}")
128
+ next
129
+ end
130
+ form = column.form
131
+ Ht.p(class: %w[form-line], child: [Ht.small(column.label), form]) if form
132
+ end
133
+ send_button = Ht.button(id: "#{@class_snake}-#{command}-finish-button", class: %w[btn], child: [Ht.icon("check"), Message[:edit_finish_button_label]], ezevent: "on=click:url=#{make_base_url(@id)}/#{command}:with=form")
134
+ cancel_button = make_cancel_button("on=click:url=#{make_base_url(@id)}/#{command}:cancel=true:with=form")
135
+ list.push(Ht.p(class: %w[edit-finish-buttons], child: [send_button, cancel_button]))
136
+ return make_form("#{make_base_url}/edit", list)
137
+ end
138
+
139
+ # 編集完了後の表示
140
+ def act_after_edit
141
+ return [public_default_post, public_detail_post]
142
+ end
143
+
144
+ # キャンセル時の表示
145
+ def act_after_cancel
146
+ return public_detail_post
147
+ end
148
+ end
149
+
150
+ # 詳細表示ページ生成キット
151
+ module Detail
152
+ # データ詳細表示
153
+ def public_detail_post
154
+ @id ||= get_id
155
+ data = @column_set.set_from_db(@id)
156
+ target_keys = @detail_keys || @column_set.keys.select { |key| !@column_set[key].attribute[:no_view] }
157
+ line_a = []
158
+ target_keys.each do |key|
159
+ column = @column_set[key]
160
+ v = make_detail_line(column)
161
+ line_a.push(v) if v
162
+ end
163
+ table = Ht.div(line_a)
164
+ collection = Materialize::Collection.new
165
+ # 詳細表示用のblockを追加
166
+ collection.push(Ht.div(id: @dom_id[:detail], child: [button_for_detail_box(data), table]))
167
+ return { inject: "##{@dom_id[:detail]}", body: Html.convert(collection.to_h) }
168
+ end
169
+
170
+ # 詳細ページ用ボタン
171
+ # 詳細表示欄の一行を生成
172
+ def make_detail_line(column)
173
+ view = column.view
174
+ if view
175
+ view = Ht.pre(view) if view.strip.index("\n")
176
+ return Ht.p([Ht.small(column.label), view])
177
+ end
178
+ return nil
179
+ end
180
+
181
+ def button_for_detail_box(data)
182
+ buttons = [Ht.button(class: %w[btn right], ezevent: "on=click:url=#{make_base_url(data[:id])}/edit", child: [Ht.icon("edit"), Message[:edit_button_label]])]
183
+ if @show_delete_button
184
+ buttons.push(make_delete_button)
185
+ end
186
+ return Ht.div(class: %w[button-box], child: buttons)
187
+ end
188
+ end
189
+
190
+ module Delete
191
+ def public_delete_post
192
+ @id = get_id
193
+ dataset = DB.dataset(@column_set.name)
194
+ DB.delete(dataset, @id)
195
+ return public_default_post
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "sub_page_kit"
2
+
3
+ module Ezframe
4
+ # 各顧客に関連づいた情報の編集を一般化したクラス
5
+ class SubEditor < PageBase
6
+ include EditorCommon
7
+
8
+ def init_vars
9
+ super
10
+ @sort_key = :id
11
+ # @parent_key = :customer
12
+ @event = @parsed_body[:ezevent] if @parsed_body
13
+ # @use_detail_box = true
14
+ end
15
+
16
+ def get_parent_id
17
+ params = @request.env["url_params"]
18
+ unless params
19
+ EzLog.info "[WARN] no url_params"
20
+ return nil
21
+ end
22
+ return params[@parent_key.to_sym]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,213 @@
1
+ module Ezframe
2
+ module SubPageKit
3
+ module Default
4
+ def public_default_post
5
+ return { inject: "##{@class_snake}_tab", body: Html.convert(make_index_page) }
6
+ end
7
+ end
8
+
9
+ module Index
10
+ # 一覧表の生成
11
+ def make_index_page
12
+ list = list_for_index
13
+ target_keys = @index_keys
14
+ unless target_keys
15
+ target_keys = @column_set.keys.select { |k| !@column_set[k].no_view? }
16
+ end
17
+ # 項目名欄の生成
18
+ if @table_labels
19
+ thead = Ht.thead(Ht.tr(@table_labels.map { |label| Ht.th(label) }))
20
+ else
21
+ thead = Ht.thead(Ht.tr(target_keys.map { |key|
22
+ if @column_set[key].respond_to?(:label)
23
+ Ht.th(@column_set[key].label(force: true))
24
+ else
25
+ nil
26
+ end
27
+ })).compact
28
+ end
29
+
30
+ tr_a = list.map do |data|
31
+ view_a = make_index_line(target_keys, data)
32
+ td_a = view_a.map { |view| Ht.td(view) }
33
+ Ht.tr(id: "tr-#{@class_snake}-#{data[:id]}", child: td_a, ezevent: "on=click:url=#{make_base_url(data[:id])}/detail")
34
+ end
35
+ tbody = Ht.tbody(tr_a)
36
+ return [
37
+ area_for_create,
38
+ Ht.table(id: "enable_datatable_#{@class_snake}", child: [thead, tbody], ezload: "command=enable_datatable:target=#enable_datatable_#{@class_snake}"),
39
+ Ht.div(id: edit_inject_element),
40
+ ]
41
+ end
42
+
43
+ # 一覧表示の1行を生成
44
+ def make_index_line(target_keys, data)
45
+ @column_set.clear
46
+ @column_set.set_values(data, from_db: true)
47
+ return target_keys.map { |key| make_index_column(key) }
48
+ end
49
+
50
+ # 一覧表示の1カラムを生成
51
+ def make_index_column(key)
52
+ column = @column_set[key.to_sym]
53
+ return column.view(force: true)
54
+ end
55
+
56
+ # 一覧ページ用のデータリスト生成
57
+ def list_for_index
58
+ return @column_set.dataset.where(@parent_key.to_sym => get_parent_id, deleted_at: nil).order(@sort_key).all
59
+ end
60
+
61
+ # 一覧ページ用ボタン
62
+ def button_for_index_line(data)
63
+ Ht.button(class: %w[btn right], ezevent: "on=click:url=#{make_base_url(data[:id])}/edit", child: [Ht.icon("edit"), Message[:edit_button_label]])
64
+ end
65
+ end
66
+
67
+ module Edit
68
+ # 新規データ登録
69
+ def public_create_post
70
+ @form = @event[:form]
71
+ # EzLog.debug("public_create_post: form=#{@form}")
72
+ unless @form
73
+ { inject: "##{@class_snake}-create-area", body: Html.convert(make_edit_form(:create)) }
74
+ else
75
+ # 値の保存
76
+ @column_set.clear
77
+ form_values = @form
78
+ form_values.update(@env["url_params"])
79
+ # @column_set.values = form_values
80
+ @column_set[:id].value = @id = @column_set.create(form_values)
81
+ # return { redirect: "#{make_base_url}/#{@id}" }
82
+ return public_default_post
83
+ end
84
+ end
85
+
86
+ # データ編集受信
87
+ def public_edit_post
88
+ @id ||= get_id
89
+ unless @event[:form]
90
+ data = @column_set.set_from_db(@id)
91
+ # データが空ならエラーページ
92
+ return { inject: "##{edit_inject_element}", body: "データがありません: #{@id}" } unless data
93
+ # フォームの表示
94
+ form = make_edit_form
95
+ found_a = Ht.search(form, tag: "input")
96
+ found_a.each { |h| h.add_class("#{@class_snake}-edit-box") if h[:size] }
97
+ return { inject: "##{edit_inject_element}", body: Html.convert(form) }
98
+ else
99
+ if @event[:cancel]
100
+ # キャンセルの場合
101
+ data = @column_set.set_from_db(@id)
102
+ return act_after_cancel
103
+ else
104
+ # 値を保存
105
+ @column_set.update(@id, @event[:form])
106
+ end
107
+ return act_after_edit
108
+ end
109
+ end
110
+
111
+ #--------------------------------------------------------------------------------------------------------
112
+ # 新規データ追加欄
113
+ def area_for_create(extra_buttons = nil)
114
+ create_button = make_create_button
115
+ create_button[:ezevent] = "on=click:url=#{make_base_url}/create"
116
+ return Ht.div(id: "#{@class_snake}-create-area", child: [create_button, extra_buttons].compact)
117
+ end
118
+
119
+ # 編集フォームの生成
120
+ def make_edit_form(command = :edit)
121
+ @id ||= get_id
122
+ if command == :edit && !@id
123
+ EzLog.error "make_edit_form: @id is not defined"
124
+ end
125
+ target_keys = @edit_keys || @column_set.keys
126
+ list = target_keys.map do |colkey|
127
+ column = @column_set[colkey.to_sym]
128
+ unless column
129
+ EzLog.error("undefined column entry: #{colkey}")
130
+ next
131
+ end
132
+ make_edit_line(column)
133
+ end.compact
134
+ event = "on=click:url=#{make_base_url(@id)}/#{command}:with=form"
135
+ send_button = Ht.button(id: "#{@class_snake}-#{command}-finish-button", class: %w[btn], child: [Ht.icon("check"), Message[:edit_finish_button_label]], ezevent: event)
136
+ cancel_button = make_cancel_button("on=click:url=#{make_base_url(@id)}/#{command}:cancel=true:with=form")
137
+ list.push(Ht.p(class: %w[edit-finish-buttons], child: [send_button, cancel_button]))
138
+ return make_form("#{make_base_url}/edit", list)
139
+ end
140
+
141
+ def make_edit_line(column)
142
+ form = column.form
143
+ if form
144
+ return Ht.p(class: %w[form-line], child: [Ht.small(column.label), form])
145
+ else
146
+ return nil
147
+ end
148
+ end
149
+
150
+ def edit_inject_element
151
+ return "#{@class_snake}_show"
152
+ end
153
+
154
+ def act_after_edit
155
+ return [public_default_post, public_detail_post]
156
+ # return { inject: edit_inject_element, body: Html.convert(make_index_line(@column_set.get_hash(:value))) }
157
+ end
158
+
159
+ def act_after_cancel
160
+ return public_detail_post
161
+ end
162
+ end
163
+
164
+ module Detail
165
+ # データ詳細表示
166
+ def public_detail_post
167
+ @id = get_id
168
+ data = @column_set.set_from_db(@id)
169
+ target_keys = @show_keys || @column_set.keys.select { |key| !@column_set[key].attribute[:no_view] }
170
+ line_a = []
171
+ target_keys.each do |key|
172
+ column = @column_set[key]
173
+ v = make_detail_line(column)
174
+ line_a.push(v) if v
175
+ end
176
+ table = Ht.div(line_a)
177
+ collection = Materialize::Collection.new
178
+ # 詳細表示用のblockを追加
179
+ collection.push(Ht.div(class: "detail-box", child: [button_for_detail_box(data), table]))
180
+ return { inject: "##{edit_inject_element}", body: Html.convert(collection.to_h) }
181
+ end
182
+
183
+ # 詳細表示欄の一行を生成
184
+ def make_detail_line(column)
185
+ view = column.view
186
+ if view
187
+ view = Ht.pre(view) if view.index("\n")
188
+ return Ht.p([Ht.small(column.label), view])
189
+ end
190
+ return nil
191
+ end
192
+
193
+ # 詳細ページ用ボタン
194
+ def button_for_detail_box(data)
195
+ buttons = [Ht.button(class: %w[btn right], ezevent: "on=click:url=#{make_base_url(data[:id])}/edit", child: [Ht.icon("edit"), Message[:edit_button_label]])]
196
+ if @show_delete_button
197
+ buttons.push(make_delete_button)
198
+ end
199
+ return Ht.div(class: %w[button-box], child: buttons)
200
+ end
201
+ end
202
+
203
+ module Delete
204
+ # 削除ボタン押下時の処理
205
+ def public_delete_post
206
+ @id = get_id
207
+ dataset = DB.dataset(@column_set.name)
208
+ DB.delete(dataset, @id)
209
+ return public_default_post
210
+ end
211
+ end
212
+ end
213
+ end
@@ -3,23 +3,24 @@
3
3
  module Ezframe
4
4
  class Template
5
5
  class << self
6
- def fill(filename, opts = {})
6
+ def fill_from_file(filename, opts = {})
7
7
  dir = File.dirname(filename)
8
8
  unless File.exist?(filename)
9
9
  raise "fill_template: file does not exist: #{filename}"
10
10
  end
11
-
12
11
  instr = File.open(filename, &:read)
13
12
  return fill_in_text(instr, opts)
14
13
  end
15
14
 
16
15
  def fill_in_text(text, opts = {})
17
- outstr = text.gsub(/\#\{(.*)\}/) do
16
+ outstr = text.gsub(/\#\{([^\}]+)\}/) do
18
17
  keyword = $1
19
18
  if opts[keyword.to_sym]
20
19
  opts[keyword.to_sym]
20
+ elsif ENV[keyword]
21
+ ENV[keyword]
21
22
  else
22
- mylog "[WARN] no value for keyword: #{keyword}"
23
+ EzLog.info "[WARN] no value for keyword: #{keyword}"
23
24
  nil
24
25
  end
25
26
  end