fiveapples 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/config5.ru +8 -5
- data/lib/fa_utils.rb +18 -0
- data/lib/fiveapples.db3 +0 -0
- data/lib/fiveapples.rb +53 -19
- data/lib/model.rb +17 -2
- data/lib/options.rb +5 -2
- data/lib/ui5/Component.js.erb +4 -3
- data/lib/ui5/controller/Base64.js +87 -0
- data/lib/ui5/controller/Breeder.js +74 -0
- data/lib/ui5/controller/BreederList.controller.js +5 -5
- data/lib/ui5/controller/Breeder_Create.controller.js +20 -49
- data/lib/ui5/controller/Breeder_Detail.controller.js +62 -91
- data/lib/ui5/controller/Create.js +41 -0
- data/lib/ui5/controller/CultivarList.controller.js +5 -4
- data/lib/ui5/controller/Cultivar_Create.controller.js +25 -80
- data/lib/ui5/controller/Cultivar_Detail.controller.js +126 -159
- data/lib/ui5/controller/Detail.js +96 -0
- data/lib/ui5/controller/FileUpload.js +40 -0
- data/lib/ui5/controller/Parentage_Create.controller.js +0 -3
- data/lib/ui5/controller/Parentage_Detail.controller.js +10 -37
- data/lib/ui5/view/BreederList.view.xml +8 -1
- data/lib/ui5/view/Breeder_Create.view.xml +6 -3
- data/lib/ui5/view/Breeder_Detail.view.xml +46 -9
- data/lib/ui5/view/CultivarList.view.xml +2 -1
- data/lib/ui5/view/Cultivar_Create.view.xml +6 -3
- data/lib/ui5/view/Cultivar_Detail.view.xml +47 -43
- data/lib/version.rb +1 -1
- metadata +13 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 819272c422885597ec73f8dd633cad031e882f03e9c5ee3d009a48792d1ae6eb
|
4
|
+
data.tar.gz: 96e67d9c2cbe9538ca91f30565f8c15553357a7d9c4880c6eccb45454de45917
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf920145c28718564c5c207cb98eb4800d651e691340f1e670b3e8f794ae062c66bba5db6027c28aa09292effbe949b0fcb2db9f0aca1b9b0476b2c4ef13f62d
|
7
|
+
data.tar.gz: b8db84aa3f9f1c83ab63d524be0ee57b10804d39d573a23c59e9efacdfd6e4c6b8444108bb69c056d7399117aa8ea118451331877cb349c1a47175d14f4fa590
|
data/lib/config5.ru
CHANGED
@@ -33,8 +33,8 @@ end
|
|
33
33
|
|
34
34
|
fiveapples = Rack::OData::Builder.new do
|
35
35
|
|
36
|
-
use Rack::ODataCommonLogger
|
37
|
-
|
36
|
+
use Rack::ODataCommonLogger if FiveA.log
|
37
|
+
|
38
38
|
use Rack::Cors do
|
39
39
|
allow do
|
40
40
|
origins 'localhost:9494', '127.0.0.1:9494'
|
@@ -54,9 +54,12 @@ fiveapples = Rack::OData::Builder.new do
|
|
54
54
|
'/ui5' => idxh,
|
55
55
|
'/ui5/' => idxh}
|
56
56
|
redirects["/#{ui5d}"] = idxh if FiveA.one_way
|
57
|
-
redirects["/#{ui5d}/"] = idxh if FiveA.one_way
|
58
|
-
|
59
|
-
|
57
|
+
redirects["/#{ui5d}/"] = idxh if FiveA.one_way
|
58
|
+
if FiveA.one_way
|
59
|
+
redirects["/ui5/index.html"] = idxh
|
60
|
+
else
|
61
|
+
redirects["/ui5_1way/index.html"] = idxh
|
62
|
+
end
|
60
63
|
# some user friendly redirects
|
61
64
|
# Note: We need this because serving / with /ui5/index.html content does not work
|
62
65
|
# as is produces follow-up javascript resource requests like "/Component.js"
|
data/lib/fa_utils.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
# Ruby 2.5 ships String#delete_prefix but lets try to support 2.4
|
5
|
+
class String
|
6
|
+
def del_prefix(prf)
|
7
|
+
if self[0] == prf
|
8
|
+
self[1..-1]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module FiveApples
|
14
|
+
def self.test_host_ip
|
15
|
+
net = Socket.ip_address_list.detect(&:ipv4_private?)
|
16
|
+
net.nil? ? 'localhost' : net.ip_address
|
17
|
+
end
|
18
|
+
end
|
data/lib/fiveapples.db3
CHANGED
Binary file
|
data/lib/fiveapples.rb
CHANGED
@@ -1,28 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rack'
|
4
|
-
|
5
4
|
require 'sequel'
|
6
5
|
require 'fileutils'
|
7
|
-
require 'socket'
|
8
6
|
require 'erb'
|
9
7
|
require_relative 'version'
|
8
|
+
require_relative 'fa_utils'
|
9
|
+
|
10
10
|
require 'safrano.rb'
|
11
11
|
|
12
|
-
# Ruby 2.5 ships String#delete_prefix but lets try to support 2.4
|
13
|
-
class String
|
14
|
-
def del_prefix(prf)
|
15
|
-
if self[0] == prf
|
16
|
-
self[1..-1]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
12
|
|
21
13
|
module FiveApples
|
22
14
|
class Server
|
23
15
|
CONFIGDIRNAME = 'fiveapples'.freeze
|
24
16
|
DBFILENAME = 'fiveapples.db3'.freeze
|
25
17
|
CONFIGRU = 'config5.ru'.freeze
|
18
|
+
MEDIADIR = 'media'.freeze
|
26
19
|
|
27
20
|
attr_reader :db
|
28
21
|
attr_reader :one_way
|
@@ -31,13 +24,17 @@ module FiveApples
|
|
31
24
|
attr_reader :role
|
32
25
|
attr_reader :host
|
33
26
|
attr_reader :port
|
34
|
-
|
27
|
+
attr_reader :media_root
|
28
|
+
attr_accessor :log
|
29
|
+
|
35
30
|
def initialize(options={})
|
36
31
|
options ||= {}
|
37
32
|
@role = options[:role]
|
33
|
+
# from libdir we readonly. --> can be a system (install) dir
|
38
34
|
@libdir = __dir__.dup
|
39
35
|
|
40
|
-
|
36
|
+
# apphome needs to be user-writeable !
|
37
|
+
@apphome = if ( @role == :test )
|
41
38
|
File.expand_path('testdb', @libdir)
|
42
39
|
else
|
43
40
|
gconfigdir = File.expand_path('.config', Dir.home)
|
@@ -48,18 +45,22 @@ module FiveApples
|
|
48
45
|
|
49
46
|
@systemdbname = File.join(@libdir, DBFILENAME)
|
50
47
|
@homedbname = File.expand_path(DBFILENAME, @apphome)
|
48
|
+
@media_root = File.expand_path(MEDIADIR, @apphome)
|
51
49
|
@configru = File.expand_path(CONFIGRU, @libdir)
|
52
|
-
|
53
50
|
@one_way = options[:one_way]
|
54
51
|
@use_cdn = options[:use_cdn]
|
55
|
-
|
52
|
+
|
53
|
+
# in testmode we dont log per default,
|
54
|
+
# in non testmode we log per default,
|
55
|
+
# but this can be overriden with option
|
56
|
+
@log = ( options[:log] || ( @role != :test ) )
|
57
|
+
|
56
58
|
@resources = @use_cdn ? "https://openui5.hana.ondemand.com/#{OpenUI5::VERSION}/resources/sap-ui-core.js" : '../resources/sap-ui-core.js'
|
57
59
|
|
58
60
|
@ui5d = @one_way ? 'ui5_1way' : 'ui5'
|
59
61
|
@port = 9494
|
60
62
|
@host = if ( ( @role == :test ) && ENV['selenium_remote_url'] )
|
61
|
-
|
62
|
-
net.nil? ? 'localhost' : net.ip_address
|
63
|
+
FiveApples.test_host_ip()
|
63
64
|
else
|
64
65
|
'localhost'
|
65
66
|
end
|
@@ -70,16 +71,46 @@ module FiveApples
|
|
70
71
|
if ( @role == :test )
|
71
72
|
# in test-mode always start with a fresh DB copy
|
72
73
|
FileUtils.cp(@systemdbname, @homedbname)
|
74
|
+
|
75
|
+
# and reset the media directory
|
76
|
+
media_photo_dir = File.absolute_path('Photo', @media_root)
|
77
|
+
FileUtils.remove_entry_secure(media_photo_dir) if File.exists?(media_photo_dir)
|
73
78
|
else
|
74
79
|
FileUtils.cp(@systemdbname, @homedbname) unless File.exist?(@homedbname)
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
83
|
+
def db_create_photo_table
|
84
|
+
@db.create_table :photo do
|
85
|
+
primary_key :id
|
86
|
+
column :name, :text
|
87
|
+
Integer :cultivar_id
|
88
|
+
column :content_type, :text
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def db_breeder_table_photo_id
|
93
|
+
return if @db.schema(:breeder).find{|col| col[0] == :photo_id }
|
94
|
+
|
95
|
+
@db.alter_table :breeder do
|
96
|
+
add_column :photo_id, Integer
|
97
|
+
add_foreign_key [:photo_id], :photo, key: :id,
|
98
|
+
name: :breeder_photo_id_fkey
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
78
103
|
def startdb
|
79
104
|
setup_db_in_homedir
|
80
105
|
|
81
106
|
@db = Sequel::Model.db = Sequel.sqlite(@homedbname)
|
82
|
-
|
107
|
+
# data model for media entities table and relations
|
108
|
+
unless @db.table_exists? :photo
|
109
|
+
db_create_photo_table
|
110
|
+
end
|
111
|
+
|
112
|
+
db_breeder_table_photo_id
|
113
|
+
|
83
114
|
Kernel.at_exit { Sequel::Model.db.disconnect if Sequel::Model.db }
|
84
115
|
|
85
116
|
end
|
@@ -92,8 +123,11 @@ module FiveApples
|
|
92
123
|
def serve
|
93
124
|
|
94
125
|
puts "Fiveapples version #{FiveApples::VERSION} on #{@host} config #{@configru}"
|
95
|
-
|
96
|
-
#
|
126
|
+
begin
|
127
|
+
# this requires safrano ~> 0.3.5
|
128
|
+
puts "Safrano version #{Safrano::VERSION}"
|
129
|
+
rescue
|
130
|
+
end
|
97
131
|
|
98
132
|
Dir.chdir @libdir do
|
99
133
|
|
data/lib/model.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
|
3
4
|
class Cultivar < Sequel::Model(:cultivar)
|
4
5
|
|
5
6
|
# Navigation attributes
|
6
7
|
one_to_many :parent, :class => :Parentage, :key => :cultivar_id
|
7
8
|
one_to_many :child, :class => :Parentage, :key => :parent_id
|
8
|
-
|
9
|
+
one_to_many :photo, :class => :Photo, :key => :cultivar_id
|
9
10
|
many_to_one :breeder, :key => :breeder_id
|
10
11
|
|
11
12
|
end
|
@@ -15,6 +16,7 @@ end
|
|
15
16
|
|
16
17
|
class Breeder < Sequel::Model(:breeder)
|
17
18
|
one_to_many :cultivar, :key => :breeder_id
|
19
|
+
many_to_one :avatar, :class => :Photo, :key => :photo_id
|
18
20
|
end
|
19
21
|
|
20
22
|
class Parentage < Sequel::Model(:parentage)
|
@@ -27,6 +29,9 @@ class Parentage < Sequel::Model(:parentage)
|
|
27
29
|
|
28
30
|
end
|
29
31
|
|
32
|
+
class Photo < Sequel::Model(:photo)
|
33
|
+
end
|
34
|
+
|
30
35
|
### SERVER Part #############################
|
31
36
|
|
32
37
|
class ODataFiveApples < OData::ServerApp
|
@@ -37,12 +42,21 @@ class ODataFiveApples < OData::ServerApp
|
|
37
42
|
namespace 'ODataFiveApples'
|
38
43
|
path_prefix '/odata'
|
39
44
|
enable_batch
|
45
|
+
publish_media_model Photo do
|
46
|
+
slug :name
|
47
|
+
use OData::Media::Static, :root => FiveA.media_root
|
48
|
+
end
|
49
|
+
|
40
50
|
publish_model Cultivar, :cultivar do
|
41
51
|
add_nav_prop_single :breeder
|
42
52
|
add_nav_prop_collection :parent
|
43
53
|
add_nav_prop_collection :child
|
54
|
+
add_nav_prop_collection :photo
|
55
|
+
end
|
56
|
+
publish_model Breeder, :breeder do
|
57
|
+
add_nav_prop_collection :cultivar
|
58
|
+
add_nav_prop_single :avatar
|
44
59
|
end
|
45
|
-
publish_model Breeder, :breeder do add_nav_prop_collection :cultivar end
|
46
60
|
publish_model ParentageType, :par_type
|
47
61
|
publish_model Parentage, :parentage do
|
48
62
|
add_nav_prop_single :parent
|
@@ -50,5 +64,6 @@ class ODataFiveApples < OData::ServerApp
|
|
50
64
|
add_nav_prop_single :par_type
|
51
65
|
end
|
52
66
|
end
|
67
|
+
|
53
68
|
end
|
54
69
|
|
data/lib/options.rb
CHANGED
@@ -4,7 +4,8 @@ OPTS = GetoptLong.new(
|
|
4
4
|
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
5
5
|
[ '--one_way', '-o', GetoptLong::NO_ARGUMENT ],
|
6
6
|
[ '--use_cdn', '-c', GetoptLong::NO_ARGUMENT ],
|
7
|
-
[ '--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT ]
|
7
|
+
[ '--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT ],
|
8
|
+
[ '--test', '-t', GetoptLong::NO_ARGUMENT ]
|
8
9
|
)
|
9
10
|
|
10
11
|
def read_opts
|
@@ -12,7 +13,7 @@ OPTS = GetoptLong.new(
|
|
12
13
|
options[:one_way] = false
|
13
14
|
options[:libdir_add] = nil
|
14
15
|
options[:use_cdn] = false
|
15
|
-
|
16
|
+
|
16
17
|
OPTS.each do |opt, arg|
|
17
18
|
case opt
|
18
19
|
when '--help'
|
@@ -29,6 +30,8 @@ Usage: fiveapples [OPTIONS]
|
|
29
30
|
options[:one_way] = true
|
30
31
|
when '--use_cdn'
|
31
32
|
options[:use_cdn] = true
|
33
|
+
when '--test'
|
34
|
+
options[:role] = :test
|
32
35
|
when '--libdir'
|
33
36
|
options[:libdir_add] = arg
|
34
37
|
if arg
|
data/lib/ui5/Component.js.erb
CHANGED
@@ -2,9 +2,10 @@ sap.ui.define(
|
|
2
2
|
[
|
3
3
|
"sap/ui/core/UIComponent",
|
4
4
|
"sap/ui/model/odata/ODataModel",
|
5
|
-
"sap/ui/model/resource/ResourceModel"
|
5
|
+
"sap/ui/model/resource/ResourceModel",
|
6
|
+
"sap/m/MessageToast"
|
6
7
|
],
|
7
|
-
function(UIComponent, ODataModel, ResourceModel) {
|
8
|
+
function(UIComponent, ODataModel, ResourceModel, MessageToast) {
|
8
9
|
"use strict";
|
9
10
|
return UIComponent.extend("fivea.Component", {
|
10
11
|
metadata: { manifest: "json" },
|
@@ -27,7 +28,7 @@ sap.ui.define(
|
|
27
28
|
mParameters.serviceUrl = "http://<%= @host %>:9494/odata";
|
28
29
|
var oModel = new sap.ui.model.odata.v2.ODataModel(mParameters);
|
29
30
|
oModel.setTokenHandlingEnabled(true);
|
30
|
-
|
31
|
+
|
31
32
|
this.setModel(oModel);
|
32
33
|
|
33
34
|
// set i18n model
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* Base64 encode / decode
|
4
|
+
* http://www.webtoolkit.info/
|
5
|
+
* https://stackoverflow.com/questions/246801/how-can-you-encode-a-string-to-base64-in-javascript
|
6
|
+
**/
|
7
|
+
|
8
|
+
|
9
|
+
/**
|
10
|
+
* https://stackoverflow.com/questions/37376838/how-to-call-utility-functions-in-sapui5-controller
|
11
|
+
*
|
12
|
+
* **/
|
13
|
+
|
14
|
+
sap.ui.define([], function() {
|
15
|
+
|
16
|
+
"use strict";
|
17
|
+
|
18
|
+
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
19
|
+
|
20
|
+
var _utf8_encode = function (string) {
|
21
|
+
|
22
|
+
var utftext = "", c, n;
|
23
|
+
|
24
|
+
string = string.replace(/\r\n/g,"\n");
|
25
|
+
|
26
|
+
for (n = 0; n < string.length; n++) {
|
27
|
+
|
28
|
+
c = string.charCodeAt(n);
|
29
|
+
|
30
|
+
if (c < 128) {
|
31
|
+
|
32
|
+
utftext += String.fromCharCode(c);
|
33
|
+
|
34
|
+
} else if((c > 127) && (c < 2048)) {
|
35
|
+
|
36
|
+
utftext += String.fromCharCode((c >> 6) | 192);
|
37
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
38
|
+
|
39
|
+
} else {
|
40
|
+
|
41
|
+
utftext += String.fromCharCode((c >> 12) | 224);
|
42
|
+
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
43
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
44
|
+
|
45
|
+
}
|
46
|
+
|
47
|
+
}
|
48
|
+
|
49
|
+
return utftext;
|
50
|
+
};
|
51
|
+
|
52
|
+
return {
|
53
|
+
encode: function (input) {
|
54
|
+
var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;
|
55
|
+
|
56
|
+
input = _utf8_encode(input);
|
57
|
+
|
58
|
+
while (i < input.length) {
|
59
|
+
|
60
|
+
chr1 = input.charCodeAt(i++);
|
61
|
+
chr2 = input.charCodeAt(i++);
|
62
|
+
chr3 = input.charCodeAt(i++);
|
63
|
+
|
64
|
+
enc1 = chr1 >> 2;
|
65
|
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
66
|
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
67
|
+
enc4 = chr3 & 63;
|
68
|
+
|
69
|
+
if (isNaN(chr2)) {
|
70
|
+
enc3 = enc4 = 64;
|
71
|
+
} else if (isNaN(chr3)) {
|
72
|
+
enc4 = 64;
|
73
|
+
}
|
74
|
+
|
75
|
+
output += _keyStr.charAt(enc1);
|
76
|
+
output += _keyStr.charAt(enc2);
|
77
|
+
output += _keyStr.charAt(enc3);
|
78
|
+
output += _keyStr.charAt(enc4);
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
return output;
|
83
|
+
}
|
84
|
+
|
85
|
+
};
|
86
|
+
}
|
87
|
+
);
|
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Common helper/callbacks for Breeder related functions, eg
|
4
|
+
* reusable search helps
|
5
|
+
*
|
6
|
+
* **/
|
7
|
+
|
8
|
+
sap.ui.define(["sap/m/MessageToast",
|
9
|
+
"sap/ui/commons/Dialog",
|
10
|
+
"sap/ui/core/routing/History"],
|
11
|
+
function(MessageToast, Dialog, History) {
|
12
|
+
|
13
|
+
"use strict";
|
14
|
+
|
15
|
+
return {
|
16
|
+
|
17
|
+
|
18
|
+
onIdValueHelp: function(that, oEvent) {
|
19
|
+
|
20
|
+
that.inputId = oEvent.getSource().getId();
|
21
|
+
that.inputDescrId = that.inputId + "_descr";
|
22
|
+
|
23
|
+
// create value help dialog
|
24
|
+
if (!that._valueHelpDialog) {
|
25
|
+
that._valueHelpDialog = sap.ui.xmlfragment(
|
26
|
+
"fivea.view.BreederOptio", that );
|
27
|
+
that.getView().addDependent(that._valueHelpDialog);
|
28
|
+
}
|
29
|
+
|
30
|
+
that._valueHelpDialog.open("");
|
31
|
+
},
|
32
|
+
_handleValueHelpSearch: function(evt) {
|
33
|
+
var sValue = evt.getParameter("value");
|
34
|
+
var oFilter = new Filter(
|
35
|
+
"name",
|
36
|
+
sap.ui.model.FilterOperator.Contains,
|
37
|
+
sValue
|
38
|
+
);
|
39
|
+
evt.getSource()
|
40
|
+
.getBinding("items")
|
41
|
+
.filter([oFilter]);
|
42
|
+
},
|
43
|
+
|
44
|
+
_handleValueHelpClose: function(that, evt) {
|
45
|
+
var oSelectedItem = evt.getParameter("selectedItem");
|
46
|
+
if (oSelectedItem) {
|
47
|
+
// oSelectedItem.getBindingContextPath();
|
48
|
+
// "/breeder(8)"
|
49
|
+
var oModel = oSelectedItem.getModel();
|
50
|
+
var oPath = oSelectedItem.getBindingContextPath();
|
51
|
+
|
52
|
+
|
53
|
+
function _loadavsuccs(oData, response){
|
54
|
+
that.loadavsuccs(oData, response);
|
55
|
+
};
|
56
|
+
function _loadaverr(oErr){};
|
57
|
+
oModel.read(oPath,
|
58
|
+
{ urlParameters:{$expand: "avatar"},
|
59
|
+
success: _loadavsuccs,
|
60
|
+
error: _loadaverr } );
|
61
|
+
|
62
|
+
var IDInput = that.getView().byId(that.inputId);
|
63
|
+
IDInput.setValue(oSelectedItem.getDescription());
|
64
|
+
|
65
|
+
var oText = that.getView().byId(that.inputDescrId);
|
66
|
+
oText.setText(oSelectedItem.getTitle());
|
67
|
+
}
|
68
|
+
evt.getSource()
|
69
|
+
.getBinding("items")
|
70
|
+
.filter([]);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
}
|
74
|
+
);
|