ezframe 0.0.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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