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.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/asset/css/materialize.min.css +13 -0
- data/asset/css/style.css +3 -0
- data/asset/html/index.html +1 -0
- data/{app_template/asset/image/favicon.ico → asset/image/c_e.ico} +0 -0
- data/asset/js/ezframe.js +387 -0
- data/exe/check_column_yml +64 -0
- data/exe/console +2 -2
- data/exe/{create_table.rb → create_table} +7 -4
- data/exe/dbmigrate +174 -0
- data/exe/html2ruby +61 -0
- data/ezframe.gemspec +10 -8
- data/lib/ezframe.rb +9 -3
- data/lib/ezframe/auth.rb +50 -31
- data/lib/ezframe/column_set.rb +314 -103
- data/lib/ezframe/column_type.rb +456 -99
- data/lib/ezframe/config.rb +27 -6
- data/lib/ezframe/controller.rb +41 -38
- data/lib/ezframe/database.rb +171 -52
- data/lib/ezframe/editor_common.rb +74 -0
- data/lib/ezframe/email.rb +34 -0
- data/lib/ezframe/ezlog.rb +40 -0
- data/lib/ezframe/ht.rb +42 -17
- data/lib/ezframe/html.rb +47 -31
- data/lib/ezframe/japanese_utils.rb +15 -0
- data/lib/ezframe/jquery-ui.rb +29 -0
- data/lib/ezframe/loader.rb +4 -4
- data/lib/ezframe/main_editor.rb +19 -0
- data/lib/ezframe/main_page_kit.rb +226 -0
- data/lib/ezframe/materialize.rb +10 -14
- data/lib/ezframe/message.rb +46 -0
- data/lib/ezframe/page_base.rb +59 -71
- data/lib/ezframe/route.rb +126 -0
- data/lib/ezframe/server.rb +16 -5
- data/lib/ezframe/single_page_editor.rb +22 -0
- data/lib/ezframe/single_page_kit.rb +199 -0
- data/lib/ezframe/sub_editor.rb +25 -0
- data/lib/ezframe/sub_page_kit.rb +213 -0
- data/lib/ezframe/template.rb +5 -4
- data/lib/ezframe/util.rb +45 -23
- data/lib/ezframe/version.rb +1 -1
- metadata +74 -34
- data/.rubocop.yml +0 -44
- data/app_template/asset/js/ezframe.js +0 -288
- data/app_template/config.ru +0 -10
- data/app_template/config/generic.yml +0 -3
- data/app_template/config/materialize.yml +0 -5
- data/app_template/pages/basic.rb +0 -5
- data/exe/setup.rb +0 -15
- data/lib/ezframe/editor.rb +0 -188
- data/lib/ezframe/model.rb +0 -52
- data/lib/ezframe/page_kit.rb +0 -63
data/lib/ezframe/materialize.rb
CHANGED
@@ -4,17 +4,16 @@ module Ezframe
|
|
4
4
|
class Materialize
|
5
5
|
class << self
|
6
6
|
def into_html_header
|
7
|
-
|
8
|
-
|
9
|
-
js_a = Config[:extra_js_list].map {|file| "<script src=\"#{file}\"></script>\n" }
|
7
|
+
css_a = Config[:extra_css_list]&.map {|file| "<link href=\"#{file}\" rel=\"stylesheet\">\n" }
|
8
|
+
js_a = Config[:extra_js_list]&.map {|file| "<script src=\"#{file}\"></script>\n" }
|
10
9
|
|
11
10
|
css_files = Dir["./asset/css/*.css"]||[]
|
12
|
-
css_a += css_files.map do |file|
|
11
|
+
css_a += css_files.sort.map do |file|
|
13
12
|
file.gsub!("./asset", "")
|
14
13
|
"<link href=\"#{file}\" rel=\"stylesheet\">\n"
|
15
14
|
end
|
16
15
|
js_files = Dir["./asset/js/*.js"]||[]
|
17
|
-
js_a += js_files.map do |file|
|
16
|
+
js_a += js_files.sort.map do |file|
|
18
17
|
file.gsub!("./asset", "")
|
19
18
|
"<script src=\"#{file}\"></script>\n"
|
20
19
|
end
|
@@ -27,19 +26,16 @@ module Ezframe
|
|
27
26
|
|
28
27
|
def convert(ht_h)
|
29
28
|
return nil unless ht_h
|
30
|
-
return ht_h if (ht_h.
|
29
|
+
return ht_h if (ht_h.is_a?(Hash) && ht_h[:final])
|
31
30
|
new_h = ht_h.clone
|
32
|
-
if ht_h.
|
31
|
+
if ht_h.is_a?(Array)
|
33
32
|
new_h = ht_h.map { |v| convert(v) }
|
34
|
-
elsif ht_h.
|
33
|
+
elsif ht_h.is_a?(Hash)
|
35
34
|
unless ht_h[:tag]
|
36
|
-
|
35
|
+
EzLog.info("convert: no tag: #{ht_h.inspect}")
|
37
36
|
return nil
|
38
37
|
end
|
39
38
|
case ht_h[:tag].to_sym
|
40
|
-
# when :input, :select
|
41
|
-
# new_h = input(ht_h) if "hidden" != ht_h[:type]
|
42
|
-
# return new_h
|
43
39
|
when :checkbox
|
44
40
|
return checkbox(ht_h)
|
45
41
|
when :radio
|
@@ -58,8 +54,8 @@ module Ezframe
|
|
58
54
|
|
59
55
|
def icon(ht_h)
|
60
56
|
new_h = ht_h.clone
|
61
|
-
|
62
|
-
new_h.add_class(
|
57
|
+
EzLog.info "[warn] no name attribute for icon ht_h: #{ht_h.inspect}" unless new_h[:name]
|
58
|
+
new_h.add_class(%w[material-icons align-icon])
|
63
59
|
new_h.update({ tag: "i", child: ht_h[:name] })
|
64
60
|
new_h.delete(:name)
|
65
61
|
return new_h
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Ezframe
|
2
|
+
class Message
|
3
|
+
class << self
|
4
|
+
def init
|
5
|
+
load_yaml_files
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_yaml_files(dir = "./message")
|
9
|
+
unless @catalog
|
10
|
+
@catalog = {}
|
11
|
+
Dir["#{dir}/*.yml"].each do |file|
|
12
|
+
load_one_file(file)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_one_file(file)
|
18
|
+
begin
|
19
|
+
yaml = YAML.load(File.open(file), symbolize_names: true)
|
20
|
+
rescue
|
21
|
+
EzLog.info("YAML load error: #{file}")
|
22
|
+
return
|
23
|
+
end
|
24
|
+
if /([a-z]{2})\.yml$/ =~ file
|
25
|
+
lang = $1
|
26
|
+
@catalog[lang.to_sym] = yaml # .recursively_symbolize_keys
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def languages
|
31
|
+
return @catalog.keys
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(key, lang = nil)
|
35
|
+
lang = languages[0] unless lang
|
36
|
+
messages = @catalog[lang]
|
37
|
+
return messages[key.to_sym] if messages
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](key)
|
42
|
+
return get(key)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/ezframe/page_base.rb
CHANGED
@@ -2,106 +2,94 @@
|
|
2
2
|
|
3
3
|
require "json"
|
4
4
|
require "uri"
|
5
|
-
|
6
5
|
require_relative "util"
|
7
6
|
|
8
7
|
module Ezframe
|
9
8
|
class PageBase
|
10
|
-
|
11
|
-
def decide_route(path_info)
|
12
|
-
default_class = Config[:default_page_class]||"App"
|
13
|
-
default_method = Config[:default_page_method]||"default"
|
14
|
-
path_parts = path_info.split('/').drop(1)
|
15
|
-
case path_parts.length
|
16
|
-
when 0
|
17
|
-
[get_class(default_class), default_method]
|
18
|
-
when 1
|
19
|
-
filename = path_parts[0]
|
20
|
-
if filename.index(".")
|
21
|
-
return nil
|
22
|
-
end
|
23
|
-
klass = get_class(path_parts)
|
24
|
-
if klass
|
25
|
-
return [klass, default_method]
|
26
|
-
else
|
27
|
-
return [get_class(default_class), path_parts[0]]
|
28
|
-
end
|
29
|
-
else
|
30
|
-
klass = get_class(path_parts)
|
31
|
-
if klass
|
32
|
-
[klass, default_method]
|
33
|
-
else
|
34
|
-
method = path_parts.pop
|
35
|
-
klass = get_class(path_parts)
|
36
|
-
[klass, method]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
9
|
+
attr_accessor :request
|
40
10
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
return Object.const_get(klass)
|
47
|
-
end
|
48
|
-
return nil
|
49
|
-
end
|
11
|
+
def initialize(request = nil)
|
12
|
+
@class_snake = class_to_snake(self.class)
|
13
|
+
# puts "class_snake = #{@class_snake}"
|
14
|
+
set_request(request) if request
|
15
|
+
init_vars
|
50
16
|
end
|
51
17
|
|
52
|
-
|
18
|
+
def init_vars
|
19
|
+
end
|
20
|
+
|
21
|
+
# Rackのrequestを代入し、関連するインスタンス変数を定義
|
22
|
+
def set_request(request)
|
23
|
+
@request = request
|
24
|
+
@column_set = ColumnSets.get(@class_snake)
|
25
|
+
@dataset = DB.dataset(@class_snake)
|
26
|
+
EzLog.debug "column_set is not defined: #{@class_snake}" unless @column_set
|
27
|
+
@params = parse_query_string(request.env["QUERY_STRING"])
|
28
|
+
@params.update(request.params)
|
29
|
+
# EzLog.info "set_request: params=#{@params.inspect}" if @params.length > 0
|
30
|
+
# @id, @key = @params[:id], @params[:key]
|
31
|
+
@env = @request.env
|
32
|
+
@session = @env["rack.session"]
|
53
33
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
mylog "params=#{@params.inspect}" if @params.length > 0
|
61
|
-
@id, @key = @params[:id], @params[:key]
|
62
|
-
@env = @request.env
|
63
|
-
@session = @env["rack.session"]
|
64
|
-
mylog "session = #{@session.inspect}"
|
65
|
-
if request.post?
|
66
|
-
parse_json_body
|
67
|
-
mylog "json=#{@json.inspect}"
|
34
|
+
if %w[POST PUT].include?(request.request_method)
|
35
|
+
body = @request.body.read
|
36
|
+
if request.content_type.index("json")
|
37
|
+
@parsed_body = parse_json_body(body)
|
38
|
+
else
|
39
|
+
@parsed_body = parse_query_string(body)
|
68
40
|
end
|
41
|
+
# EzLog.info "parsed_body=#{@parsed_body.inspect}"
|
42
|
+
@event = @parsed_body[:ezevent] || {}
|
43
|
+
@form = @event[:form]
|
69
44
|
end
|
70
|
-
@auth = nil
|
71
45
|
end
|
72
46
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
47
|
+
# routeから基本URLを生成
|
48
|
+
def make_base_url(id = nil)
|
49
|
+
path = Route::get_path(@class_snake)
|
50
|
+
params = @request.env["url_params"] || {}
|
51
|
+
# EzLog.info "make_base_url: params=#{params}"
|
52
|
+
# params[@class_snake.to_sym] = id
|
53
|
+
path_s = path.map do |pa|
|
54
|
+
if pa == @class_snake.to_sym && id
|
55
|
+
"#{pa}/#{id}"
|
56
|
+
elsif params[pa.to_sym]
|
57
|
+
"#{pa}/#{params[pa.to_sym]}"
|
58
|
+
else
|
59
|
+
pa
|
60
|
+
end
|
61
|
+
end.join("/")
|
62
|
+
# EzLog.info "path_s=#{path_s}"
|
63
|
+
return "/#{path_s}"
|
78
64
|
end
|
79
65
|
|
80
|
-
def
|
66
|
+
def show_base_template(opts = {})
|
81
67
|
args = {
|
82
68
|
title: opts[:title],
|
83
69
|
body: opts[:body],
|
84
70
|
into_html_header: Materialize.into_html_header,
|
85
71
|
into_bottom_of_body: Materialize.into_bottom_of_body,
|
86
72
|
}
|
87
|
-
Template.
|
73
|
+
Template.fill_from_file("template/base.html", args)
|
88
74
|
end
|
89
75
|
|
90
|
-
def parse_json_body
|
91
|
-
body = @request.body.read
|
76
|
+
def parse_json_body(body)
|
92
77
|
return {} if !body || body.length==0
|
93
78
|
begin
|
94
|
-
|
79
|
+
json = JSON.parse(body, symbolize_names: true)
|
95
80
|
rescue => e
|
96
|
-
|
81
|
+
EzLog.info "ERROR: #{e.class}:#{e.message}\n#{e.backtrace}"
|
97
82
|
return nil
|
98
83
|
end
|
99
|
-
|
100
|
-
|
84
|
+
return json
|
85
|
+
end
|
86
|
+
|
87
|
+
def session
|
88
|
+
return @request.env['rack.session']
|
101
89
|
end
|
102
90
|
|
103
91
|
def warden
|
104
|
-
@request.env["warden"]
|
92
|
+
return @request.env["warden"]
|
105
93
|
end
|
106
94
|
|
107
95
|
def login?
|
@@ -109,7 +97,7 @@ module Ezframe
|
|
109
97
|
end
|
110
98
|
|
111
99
|
def user
|
112
|
-
warden.user
|
100
|
+
return warden.user
|
113
101
|
end
|
114
102
|
end
|
115
103
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Ezframe
|
2
|
+
class Route
|
3
|
+
class << self
|
4
|
+
def choose(request, route_h = nil)
|
5
|
+
path_parts = request.path_info.split("/").drop(1)
|
6
|
+
route_h ||= Config[:route].deep_dup
|
7
|
+
unless route_h
|
8
|
+
raise "Config[:route] is not defined. It should be defined in config/route.yml"
|
9
|
+
end
|
10
|
+
# puts "config=#{Config[:route]}, route_h=#{route_h}"
|
11
|
+
args = {}
|
12
|
+
opts = {}
|
13
|
+
class_a = []
|
14
|
+
# p path_parts
|
15
|
+
if path_parts.empty?
|
16
|
+
root_conf = route_h[:/]
|
17
|
+
# p root_conf
|
18
|
+
if root_conf
|
19
|
+
klass = get_class(root_conf[:class])
|
20
|
+
return [ klass.new, make_method_name("default", request.request_method) ]
|
21
|
+
end
|
22
|
+
return [ 404 ]
|
23
|
+
end
|
24
|
+
# URLを解析して、クラスの決定とIDの取得を行う
|
25
|
+
while path_parts.length > 0
|
26
|
+
part = path_parts.shift
|
27
|
+
# break if part.empty?
|
28
|
+
# EzLog.info "part=#{part}, route_h=#{route_h.inspect}"
|
29
|
+
if route_h.has_key?(part.to_sym)
|
30
|
+
# EzLog.info "has_route: #{part}"
|
31
|
+
class_a.push(part)
|
32
|
+
if path_parts[0].to_i > 0
|
33
|
+
args[part.to_sym] = val = path_parts.shift
|
34
|
+
# EzLog.info "value: part=#{part}, val=#{val}"
|
35
|
+
end
|
36
|
+
route_h = route_h[part.to_sym]
|
37
|
+
break if route_h.nil?
|
38
|
+
opts = {}
|
39
|
+
route_h.keys.compact.each do |rkey|
|
40
|
+
if rkey =~ /option_(\w+)/
|
41
|
+
opt_key = $1
|
42
|
+
opts[opt_key.to_sym] = route_h[rkey]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
# routeに無ければ、メソッドを探す
|
47
|
+
# EzLog.info "no_route: #{part}"
|
48
|
+
klass = get_class(class_a[-1])
|
49
|
+
return [ 404 ] unless klass
|
50
|
+
instance = klass.new
|
51
|
+
method_name = make_method_name(part, request.request_method)
|
52
|
+
if instance.respond_to?(method_name)
|
53
|
+
return [instance, method_name, args, opts]
|
54
|
+
else
|
55
|
+
EzLog.info "undefined method: #{klass}.#{method_name}: full path=#{request.path_info}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# 最後にメソッド名が無い場合はpublic_default_#{method}を実行。
|
60
|
+
#puts "class_a=#{class_a}"
|
61
|
+
klass = get_class(class_a[-1])
|
62
|
+
return [404] unless klass
|
63
|
+
if path_parts.length > 0
|
64
|
+
part = path_parts.shift
|
65
|
+
else
|
66
|
+
part = "default"
|
67
|
+
end
|
68
|
+
method_name = make_method_name(part, request.request_method)
|
69
|
+
#EzLog.info "method_name=#{method_name}"
|
70
|
+
instance = klass.new
|
71
|
+
if instance.respond_to?(method_name)
|
72
|
+
return [instance, method_name, args, opts]
|
73
|
+
end
|
74
|
+
return [ 404 ]
|
75
|
+
end
|
76
|
+
|
77
|
+
# ページクラスの階層を辿る
|
78
|
+
def get_path(class_snake, route_h = nil)
|
79
|
+
route_h = Config[:route] unless route_h
|
80
|
+
# EzLog.info "get_path: route_h=#{route_h}"
|
81
|
+
@get_path_found_it = nil
|
82
|
+
route =_scan_route(class_snake, route_h.deep_dup)
|
83
|
+
return route.reverse if route
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
|
87
|
+
# targetに対応する名称のクラスまでの経路を返す
|
88
|
+
def _scan_route(target, route_h)
|
89
|
+
if route_h.keys.include?(target.to_sym)
|
90
|
+
@get_path_found_it = true
|
91
|
+
return [ target ]
|
92
|
+
else
|
93
|
+
route_h.each do |k, v|
|
94
|
+
next if k.to_s =~ /^option_/
|
95
|
+
if v.is_a?(Hash)
|
96
|
+
a = _scan_route(target, v)
|
97
|
+
if @get_path_found_it
|
98
|
+
a.push(k)
|
99
|
+
return a
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
return nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def make_method_name(base_name, method = "get")
|
108
|
+
return ["public", base_name, method.downcase].join("_")
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_class(keys)
|
112
|
+
# EzLog.info "get_class: #{keys.inspect}"
|
113
|
+
return nil unless keys
|
114
|
+
keys = [ keys ] if keys.is_a?(String)
|
115
|
+
klass = (%w[Ezframe] + keys.map { |k| k.to_s.to_camel }).join("::")
|
116
|
+
# EzLog.info "get_class: #{klass}"
|
117
|
+
if Object.const_defined?(klass)
|
118
|
+
return Object.const_get(klass)
|
119
|
+
else
|
120
|
+
raise "get_class: undefined class: #{klass}"
|
121
|
+
end
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/ezframe/server.rb
CHANGED
@@ -2,14 +2,25 @@
|
|
2
2
|
|
3
3
|
module Ezframe
|
4
4
|
class Server
|
5
|
-
def
|
5
|
+
def initialize
|
6
|
+
Controller.init
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
6
10
|
req = Rack::Request.new(env)
|
7
11
|
res = Rack::Response.new
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
begin
|
13
|
+
Controller.exec(req, res)
|
14
|
+
rescue => e
|
15
|
+
EzLog.error("Controller.exec: exception: #{e.message}:\n#{e.backtrace}")
|
16
|
+
res.status = 500
|
17
|
+
res.headers["Content-Type"] = "text/plain"
|
18
|
+
res.body = [ "Internal server error" ]
|
11
19
|
end
|
12
|
-
res.
|
20
|
+
# if res.body.empty?
|
21
|
+
# raise "no body in response"
|
22
|
+
# end
|
23
|
+
return res.finish
|
13
24
|
end
|
14
25
|
end
|
15
26
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "editor_common"
|
2
|
+
require_relative "single_page_kit"
|
3
|
+
|
4
|
+
module Ezframe
|
5
|
+
# ページ遷移無しでデータを編集する仕組み
|
6
|
+
class SinglePageEditor < PageBase
|
7
|
+
include EditorCommon
|
8
|
+
include PageKit::Default
|
9
|
+
include PageKit::Index
|
10
|
+
include PageKit::Edit
|
11
|
+
include PageKit::Detail
|
12
|
+
include PageKit::Delete
|
13
|
+
|
14
|
+
def init_vars
|
15
|
+
super
|
16
|
+
@sort_key = :id
|
17
|
+
@event = @parsed_body[:ezevent] if @parsed_body
|
18
|
+
@dom_id = { create: "create-area", edit: "edit-area", index: "index-area", detail: "detail-area"}
|
19
|
+
# @show_delete_button = nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|