intranet-pictures 1.1.0 → 2.0.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/lib/intranet/pictures/json_db_provider.rb +41 -71
- data/lib/intranet/pictures/responder.rb +100 -71
- data/lib/intranet/pictures/version.rb +1 -1
- data/lib/intranet/resources/haml/pictures_browse.haml +8 -7
- data/lib/intranet/resources/haml/pictures_home.haml +18 -16
- data/spec/intranet/pictures/json_db_provider_spec.rb +52 -147
- data/spec/intranet/pictures/responder_spec.rb +102 -137
- data/spec/intranet/pictures/sample-db.json +28 -38
- data/spec/spec_helper.rb +6 -8
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f83afa6acab98f33abb964031b20ee5e3e13a9225ff3ec4525be209c87c66f51
|
|
4
|
+
data.tar.gz: 1c43a4f8cc550fe3900684a81e93ed0e50276ed59154f166132b1395d0748911
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9746b40dee3c630e69510789eed1d3f937f88441b7a484c0a139d90b7eacfdff63394875bc8122e9efea0583c6955fbc3da77852bb4816a1615952b3658de099
|
|
7
|
+
data.tar.gz: 9e8d8f8903b495bb1dbbacf010cea817f11440a0475b2eb6b98dc7b6e0576ea1dd6d1583cff63f27a9f607f384d108e1a6fa8dc969d009ba43d57b3e544cccb9
|
|
@@ -5,7 +5,7 @@ require 'mimemagic'
|
|
|
5
5
|
|
|
6
6
|
module Intranet
|
|
7
7
|
module Pictures
|
|
8
|
-
# Provides pictures data and pictures
|
|
8
|
+
# Provides pictures data and pictures listings from a database file in JSON format.
|
|
9
9
|
#
|
|
10
10
|
# === Structure of the JSON database
|
|
11
11
|
# See the example below.
|
|
@@ -14,37 +14,34 @@ module Intranet
|
|
|
14
14
|
#
|
|
15
15
|
# Pictures are described individually as a hash in the +pictures+ array. The mandatory keys in
|
|
16
16
|
# this hash are:
|
|
17
|
-
# * +id+ : unique identifier of the picture
|
|
18
17
|
# * +uri+ : location of the picture, relative to the JSON file
|
|
19
18
|
# * +title+ : description of the picture
|
|
20
19
|
# * +datetime+ : date and time of the picture, as a string in ISO8601 format
|
|
21
20
|
# * +height+ and +width+ : size in pixels of the picture
|
|
22
21
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
22
|
+
# Additional keys may be added (for instance: event, city, region/country, ...); they will be
|
|
23
|
+
# used to group pictures sharing the same value of a given key.
|
|
24
|
+
# Some groups may be defined in the +groups+ hash to add a thumbnail picture and a brief text
|
|
25
|
+
# description for them. The possible keys in this hash are:
|
|
26
26
|
# * +id+ : unique identifier of the group, mandatory
|
|
27
|
-
# * +title+ : human-readable group name, mandatory
|
|
28
27
|
# * +brief+ : optional short text associated to the group name
|
|
29
28
|
# * +uri+ : optional group thumbnail, relative to the JSON file
|
|
30
29
|
#
|
|
31
|
-
# Each image is associated to at most one group in each group type by by a a "foreign key"
|
|
32
|
-
# constraint of the type *picture*.+group_type+ = *group*.+id+.
|
|
33
30
|
# @example Structure of the JSON database (not all mandatory are present for readability)
|
|
34
31
|
# {
|
|
35
32
|
# "title": "gallery title",
|
|
36
33
|
# "groups": {
|
|
37
34
|
# "event": [
|
|
38
|
-
# { "id": "
|
|
35
|
+
# { "id": "Party", "brief": "...", "uri": "party.jpg", ... },
|
|
39
36
|
# { ... }
|
|
40
37
|
# ],
|
|
41
38
|
# "city": [
|
|
42
|
-
# { "id": "
|
|
39
|
+
# { "id": "Houston", "uri": "houston.png", ... },
|
|
43
40
|
# { ... }
|
|
44
41
|
# ]
|
|
45
42
|
# },
|
|
46
43
|
# "pictures": [
|
|
47
|
-
# { "uri": "dir/pic0.jpg", "datetime": "...", "event": "
|
|
44
|
+
# { "uri": "dir/pic0.jpg", "datetime": "...", "event": "Party", "city": "Houston", ... },
|
|
48
45
|
# { ... }
|
|
49
46
|
# ]
|
|
50
47
|
# }
|
|
@@ -66,47 +63,16 @@ module Intranet
|
|
|
66
63
|
@json.fetch('title').to_s
|
|
67
64
|
end
|
|
68
65
|
|
|
69
|
-
# Returns the list of available group types.
|
|
70
|
-
# @return [Array<String>] The available group types.
|
|
71
|
-
# @raise KeyError If no group type is defined in JSON file.
|
|
72
|
-
def group_types
|
|
73
|
-
load_json
|
|
74
|
-
@json.fetch('groups').keys
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Returns the list of the groups satisfying the following conditions:
|
|
78
|
-
# * the group is of the given +type+, and
|
|
79
|
-
# * at least one picture belonging to that group matches the +selector+.
|
|
80
|
-
# Results are returned ordered by *group*.+sort_by+ in ascending order if +asc+, and in
|
|
81
|
-
# descending order otherwise.
|
|
82
|
-
# @param type [String] The group type.
|
|
83
|
-
# @param selector [Hash<String,String>] The pictures selector, interpreted as a logical AND
|
|
84
|
-
# combination of all key/value pairs provided.
|
|
85
|
-
# @param sort_by [String] The group field to sort the results by, or nil if results should be
|
|
86
|
-
# returned without particular sorting.
|
|
87
|
-
# @param asc [Boolean] True to sort returned groups in ascending order, False to sort in
|
|
88
|
-
# descending order.
|
|
89
|
-
# @return [Array<Hash{'id'=>String, 'title'=>String, ...}>] The selected groups.
|
|
90
|
-
# @raise KeyError If JSON file is malformed, if +type+ does not match an existing group type,
|
|
91
|
-
# or if +sort_by+ is not an existing group field.
|
|
92
|
-
def list_groups(type, selector = {}, sort_by = nil, asc = true)
|
|
93
|
-
load_json
|
|
94
|
-
groups = select_groups(type, selector).map { |g| g.except('uri') }
|
|
95
|
-
groups.sort_by! { |g| g.fetch(sort_by) } unless sort_by.nil?
|
|
96
|
-
groups.reverse! unless asc
|
|
97
|
-
groups
|
|
98
|
-
end
|
|
99
|
-
|
|
100
66
|
# Returns the list of the pictures matching +selector+.
|
|
101
|
-
# Results are returned ordered by
|
|
102
|
-
#
|
|
67
|
+
# Results are returned ordered by +sort_by+ in ascending order if +asc+, and in descending
|
|
68
|
+
# order otherwise.
|
|
103
69
|
# @param selector [Hash<String,String>] The pictures selector, interpreted as a logical AND
|
|
104
70
|
# combination of all key/value pairs provided.
|
|
105
71
|
# @param sort_by [String] The picture field to sort the results by, or nil if results should
|
|
106
72
|
# be returned without particular sorting.
|
|
107
|
-
# @param asc [Boolean] True to sort returned pictures in ascending order, False to sort
|
|
108
|
-
# descending order.
|
|
109
|
-
# @return [Array<Hash{'
|
|
73
|
+
# @param asc [Boolean] True to sort returned pictures in ascending order, False to sort them
|
|
74
|
+
# in descending order.
|
|
75
|
+
# @return [Array<Hash{'title'=>String, 'datetime'=>String, 'height'=>Integer,
|
|
110
76
|
# 'width'=>Integer, ...}>] The selected pictures.
|
|
111
77
|
# @raise KeyError If JSON file is malformed, or if +sort_by+ is not an existing picture field.
|
|
112
78
|
def list_pictures(selector = {}, sort_by = nil, asc = true)
|
|
@@ -122,35 +88,46 @@ module Intranet
|
|
|
122
88
|
# picture.
|
|
123
89
|
# @return [String, Blob] The MIME type of the picture, and the picture file content.
|
|
124
90
|
# @raise KeyError If JSON file is malformed, if selector does not match exactly one picture,
|
|
125
|
-
# or if the
|
|
91
|
+
# or if the picture +uri+ does not refer to an existing image file.
|
|
126
92
|
def picture(selector = {})
|
|
127
93
|
load_json
|
|
128
94
|
pic = select_pictures(selector)
|
|
129
95
|
raise KeyError unless pic.size == 1
|
|
130
96
|
|
|
131
97
|
path = File.join(@json_dir, pic.first.fetch('uri'))
|
|
132
|
-
|
|
98
|
+
read_image_file(path)
|
|
133
99
|
end
|
|
134
100
|
|
|
135
|
-
# Returns the thumbnail picture of the group
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
# @param type [String] The group type.
|
|
139
|
-
# @param selector [Hash<String,String>] The pictures selector, interpreted as a logical AND
|
|
140
|
-
# combination of all key/value pairs provided. The
|
|
141
|
-
# selector should return exactly one group.
|
|
101
|
+
# Returns the thumbnail picture of the group whose type is +key+ and named +value+.
|
|
102
|
+
# @param key [String] The group type.
|
|
103
|
+
# @param value [String] The group name.
|
|
142
104
|
# @return [String, Blob] The MIME type of the picture, and the picture file content. Nil may
|
|
143
105
|
# be returned if no thumbnail is available for that group.
|
|
144
|
-
# @raise KeyError If JSON file is malformed, if
|
|
145
|
-
# or if the
|
|
146
|
-
def group_thumbnail(
|
|
106
|
+
# @raise KeyError If JSON file is malformed, if key/value do not designate exactly one group,
|
|
107
|
+
# or if the group +uri+ does not refer to an existing image file.
|
|
108
|
+
def group_thumbnail(key, value)
|
|
147
109
|
load_json
|
|
148
|
-
group =
|
|
110
|
+
group = select_group(key, value)
|
|
149
111
|
raise KeyError unless group.size == 1
|
|
150
112
|
return nil if group.first['uri'].nil?
|
|
151
113
|
|
|
152
114
|
path = File.join(@json_dir, group.first.fetch('uri'))
|
|
153
|
-
|
|
115
|
+
read_image_file(path)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Returns the brief text of the group whose type is +key+ and named +value+.
|
|
119
|
+
# @param key [String] The group type.
|
|
120
|
+
# @param value [String] The group name.
|
|
121
|
+
# @return [String] The brief text of the group, or an empty string if no brief is available.
|
|
122
|
+
# @raise KeyError If JSON file is malformed or if key/value do not designate exactly one
|
|
123
|
+
# group.
|
|
124
|
+
def group_brief(key, value)
|
|
125
|
+
load_json
|
|
126
|
+
group = select_group(key, value)
|
|
127
|
+
raise KeyError unless group.size == 1
|
|
128
|
+
return '' if group.first['brief'].nil?
|
|
129
|
+
|
|
130
|
+
group.first.fetch('brief')
|
|
154
131
|
end
|
|
155
132
|
|
|
156
133
|
private
|
|
@@ -164,7 +141,7 @@ module Intranet
|
|
|
164
141
|
@json_time = mtime
|
|
165
142
|
end
|
|
166
143
|
|
|
167
|
-
def
|
|
144
|
+
def read_image_file(path)
|
|
168
145
|
mime_type = MimeMagic.by_path(path).type
|
|
169
146
|
raise KeyError unless mime_type.start_with?('image/')
|
|
170
147
|
|
|
@@ -179,19 +156,12 @@ module Intranet
|
|
|
179
156
|
false
|
|
180
157
|
end
|
|
181
158
|
|
|
182
|
-
def select_groups(type, selector)
|
|
183
|
-
return @json.fetch('groups').fetch(type) if selector.empty? # optimization
|
|
184
|
-
|
|
185
|
-
groups_id = select_pictures_having(type, selector).map { |p| p.fetch(type) }.uniq.compact
|
|
186
|
-
@json.fetch('groups').fetch(type).select { |g| groups_id.include?(g.fetch('id')) }
|
|
187
|
-
end
|
|
188
|
-
|
|
189
159
|
def select_pictures(selector)
|
|
190
160
|
@json.fetch('pictures').select { |p| picture_match?(p, selector) }
|
|
191
161
|
end
|
|
192
162
|
|
|
193
|
-
def
|
|
194
|
-
@json.fetch('
|
|
163
|
+
def select_group(type, id)
|
|
164
|
+
@json.fetch('groups').fetch(type).select { |g| g.fetch('id') == id }
|
|
195
165
|
end
|
|
196
166
|
end
|
|
197
167
|
end
|
|
@@ -9,7 +9,7 @@ require_relative 'version'
|
|
|
9
9
|
module Intranet
|
|
10
10
|
module Pictures
|
|
11
11
|
# The responder for the Pictures monitor module of the Intranet.
|
|
12
|
-
class Responder < AbstractResponder
|
|
12
|
+
class Responder < AbstractResponder # rubocop:disable Metrics/ClassLength
|
|
13
13
|
include Core::HamlWrapper # 'inherits' from methods of HamlWrapper
|
|
14
14
|
|
|
15
15
|
# Returns the name of the module.
|
|
@@ -18,30 +18,37 @@ module Intranet
|
|
|
18
18
|
NAME
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Returns the version of the module, according to semantic versionning.
|
|
22
22
|
# @return [String] The version of the module.
|
|
23
23
|
def self.module_version
|
|
24
24
|
VERSION
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# Returns the homepage URL of the module.
|
|
28
28
|
# @return [String] The homepage URL of the module.
|
|
29
29
|
def self.module_homepage
|
|
30
30
|
HOMEPAGE_URL
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Initializes a new Pictures responder instance.
|
|
34
|
-
# @param provider [#title,#
|
|
34
|
+
# @param provider [#title,#list_pictures,#group_thumbnail,#group_brief,#picture]
|
|
35
35
|
# The pictures provider.
|
|
36
36
|
# @see Intranet::Pictures::JsonDbProvider The specification of the provider, and in particular
|
|
37
37
|
# the minimal mandatory elements that must be returned by the operations.
|
|
38
|
-
# @param recents [Array<Hash{
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
38
|
+
# @param recents [Array<Hash{group_by:String, sort_by:String, sort_order:String,
|
|
39
|
+
# limit:Integer}>]
|
|
40
|
+
# The description of the recent pictures to be displayed on the module home page. Pictures
|
|
41
|
+
# will first be sorted according to +sort_by+ and +sort_order+, then grouped by +group_by+,
|
|
42
|
+
# keeping only the first +limit+ elements, or all if +limit+ is zero. All keys except
|
|
43
|
+
# +group_by+ may be omitted.
|
|
44
|
+
# @param home_groups [Array<Hash{group_by:String, sort_by:String, sort_order:String,
|
|
45
|
+
# browse_group_by:String, browse_sort_by:String, browse_sort_order:String}>]
|
|
46
|
+
# The description of the pictures groups to be displayed on the module home page, after the
|
|
47
|
+
# +recents+. Pictures will first be sorted according to +sort_by+ and +sort_order+, then
|
|
48
|
+
# grouped by +group_by+. The obtained groups will be displayed with their thumbnail,
|
|
49
|
+
# (optional) brief text and a link to display images of that group sorted according to
|
|
50
|
+
# +browse_sort_by+ and +browse_sort_order+ and grouped by +browse_group_by+. All keys except
|
|
51
|
+
# +group_by+ and +browse_group_by+ may be omitted.
|
|
45
52
|
# @param in_menu [Boolean] Whether the module instance should be displayed in the main
|
|
46
53
|
# navigation menu or not.
|
|
47
54
|
def initialize(provider, recents = [], home_groups = [], in_menu = true)
|
|
@@ -65,34 +72,42 @@ module Intranet
|
|
|
65
72
|
end
|
|
66
73
|
|
|
67
74
|
# Generates the HTML content associated to the given +path+ and +query+.
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
75
|
+
# @param path [String] The requested URI, relative to that module root URI.
|
|
76
|
+
# @param query [Hash<String,String>] The URI variable/value pairs, if any.
|
|
77
|
+
# @return [Integer, String, String] The HTTP return code, the MIME type and the answer body.
|
|
78
|
+
#
|
|
79
|
+
# Relevant queries are as follows:
|
|
80
|
+
#
|
|
81
|
+
# * If +path+ is +/browse.html+, key/value pairs may be used to restrict the displayed images
|
|
82
|
+
# to those satisfying all the pairs. Moreover, +sort_by+ (followed by a key), +sort_order+
|
|
83
|
+
# (followed by either +asc+ or +desc+) and +group_by+ may be used to alter the way images
|
|
84
|
+
# are displayed.
|
|
85
|
+
# * If +path+ is +/api/group_thumbnail+ or +/api/group_brief+, query must contain only a
|
|
86
|
+
# single key/value pair designating the pictures group.
|
|
87
|
+
# * If +path+ is +/api/pictures+, key/value pairs may be used to restrict the displayed images
|
|
88
|
+
# to those satisfying all the pairs. Moreover, +sort_by+ (followed by a key), and
|
|
89
|
+
# +sort_order+ (followed by either +asc+ or +desc+) may be used to alter the order in which
|
|
90
|
+
# images are returned.
|
|
91
|
+
# * If +path+ is +api/picture+, key/value pairs must be used to select a single image from the
|
|
92
|
+
# gallery.
|
|
93
|
+
#
|
|
94
|
+
# When +path+ is +/api/pictures+, the selected pictures are returned in JSON format (REST API)
|
|
95
|
+
# with the following structure:
|
|
71
96
|
# [
|
|
72
97
|
# { "id": "...", "height": 480, "width": 640, "title": "...", "datetime": "...", ... },
|
|
73
98
|
# { ... }
|
|
74
99
|
# ]
|
|
75
|
-
# * Read-only access to groups listings under */api/groups/*+group_type+ using +GET+ method,
|
|
76
|
-
# response is in JSON format with the following structure:
|
|
77
|
-
# [
|
|
78
|
-
# { "id": "...", "title": "...", ... },
|
|
79
|
-
# { ... }
|
|
80
|
-
# ]
|
|
81
|
-
# @param path [String] The requested URI, relative to that module root URI.
|
|
82
|
-
# @param query [Hash<String,String>] The URI variable/value pairs, if any.
|
|
83
|
-
# @return [Integer, String, String] The HTTP return code, the MIME type and the answer body.
|
|
84
100
|
def generate_page(path, query)
|
|
85
101
|
case path
|
|
86
|
-
when %r{^/index\.html$}
|
|
87
|
-
when %r{^/
|
|
88
|
-
serve_groups(path.gsub(%r{^/browse_(\w+)\.html$}, '\\1'), query)
|
|
102
|
+
when %r{^/index\.html$} then serve_home
|
|
103
|
+
when %r{^/browse\.html$} then serve_browse(query)
|
|
89
104
|
when %r{^/api/} then serve_api(path.gsub(%r{^/api}, ''), query)
|
|
90
105
|
when %r{^/i18n\.js$} then serve_i18n_js
|
|
91
106
|
else super(path, query)
|
|
92
107
|
end
|
|
93
108
|
end
|
|
94
109
|
|
|
95
|
-
#
|
|
110
|
+
# Returns the title of the Pictures module, as displayed on the web page.
|
|
96
111
|
# @return [String] The title of the Pictures module web page.
|
|
97
112
|
def title
|
|
98
113
|
@provider.title
|
|
@@ -101,23 +116,30 @@ module Intranet
|
|
|
101
116
|
private
|
|
102
117
|
|
|
103
118
|
# Extract a selector from the given +query+.
|
|
104
|
-
# @return [Hash<String,String>] The picture
|
|
119
|
+
# @return [Hash<String,String>] The picture selector.
|
|
105
120
|
def selector(query)
|
|
106
|
-
query.except('sort_by', 'sort_order')
|
|
121
|
+
query.except('group_by', 'sort_by', 'sort_order')
|
|
107
122
|
end
|
|
108
123
|
|
|
109
|
-
# Extract the
|
|
110
|
-
#
|
|
111
|
-
#
|
|
124
|
+
# Extract the grouping criteria from the given +query+, ie. the key that will be used to group
|
|
125
|
+
# the selected pictures.
|
|
126
|
+
# @return [String] The key to use to group pictures.
|
|
127
|
+
# @raise KeyError If no grouping criteria is specified.
|
|
128
|
+
def group_by(query)
|
|
129
|
+
query.fetch('group_by')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Extract the sorting criteria from the given +query+, ie. the key that will be used to sort
|
|
133
|
+
# the selected pictures.
|
|
134
|
+
# @return [String] The key to use to sort pictures, or nil if no sorting is specified.
|
|
112
135
|
def sort_by(query)
|
|
113
136
|
query.fetch('sort_by')
|
|
114
137
|
rescue KeyError
|
|
115
138
|
nil
|
|
116
139
|
end
|
|
117
140
|
|
|
118
|
-
# Extract the
|
|
119
|
-
# @return [Boolean]
|
|
120
|
-
# True otherwise.
|
|
141
|
+
# Extract the sorting order from the given +query+.
|
|
142
|
+
# @return [Boolean] True if the pictures should be sorted in ascending order, False otherwise.
|
|
121
143
|
# @raise KeyError If the query requests an invalid sort order.
|
|
122
144
|
def sort_order(query)
|
|
123
145
|
return false if query['sort_order'] == 'desc'
|
|
@@ -143,52 +165,55 @@ module Intranet
|
|
|
143
165
|
### Servicing of the HTML "display-able" content ###
|
|
144
166
|
##########################################################################
|
|
145
167
|
|
|
146
|
-
def
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
168
|
+
def collect_groups(selector, group_by, sort_by, sort_order)
|
|
169
|
+
# Select all pictures, sort them & eventually keep only group names (first occurrence only)
|
|
170
|
+
@provider.list_pictures(selector, sort_by, sort_order).map do |picture|
|
|
171
|
+
picture.fetch(group_by)
|
|
172
|
+
end.uniq
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def hash_to_query(hash)
|
|
176
|
+
hash.map { |k, v| [k, v].join('=') }.join('&')
|
|
152
177
|
end
|
|
153
178
|
|
|
154
179
|
def recent_groups
|
|
155
180
|
@recents.map do |recent|
|
|
156
|
-
groups =
|
|
181
|
+
groups = collect_groups({}, group_by(recent), sort_by(recent), sort_order(recent))
|
|
157
182
|
see_more_url = ''
|
|
158
|
-
if recent[
|
|
159
|
-
groups = groups.first(recent[
|
|
160
|
-
see_more_url = "
|
|
161
|
-
see_more_url += '&sort_order=desc' unless recent[:asc]
|
|
183
|
+
if recent['limit'].to_i.positive?
|
|
184
|
+
groups = groups.first(recent['limit'].to_i)
|
|
185
|
+
see_more_url = "browse.html?#{hash_to_query(recent.except('limit'))}"
|
|
162
186
|
end
|
|
163
|
-
{
|
|
187
|
+
{ group_key: group_by(recent), groups: groups, see_more_url: see_more_url }
|
|
164
188
|
end
|
|
165
189
|
end
|
|
166
190
|
|
|
167
191
|
def all_groups
|
|
168
|
-
@home_groups.map do |
|
|
169
|
-
groups =
|
|
170
|
-
url_prefix = "
|
|
171
|
-
url_prefix +=
|
|
172
|
-
|
|
192
|
+
@home_groups.map do |sec|
|
|
193
|
+
groups = collect_groups({}, group_by(sec), sort_by(sec), sort_order(sec))
|
|
194
|
+
url_prefix = "browse.html?group_by=#{sec['browse_group_by']}"
|
|
195
|
+
url_prefix += "&sort_by=#{sec['browse_sort_by']}" if sec['browse_sort_by']
|
|
196
|
+
url_prefix += "&sort_order=#{sec['browse_sort_order']}" if sec['browse_sort_order']
|
|
197
|
+
{ group_key: group_by(sec), groups: groups, url_prefix: url_prefix }
|
|
173
198
|
end
|
|
174
199
|
end
|
|
175
200
|
|
|
176
|
-
def make_nav(
|
|
201
|
+
def make_nav(query = {})
|
|
177
202
|
h = { I18n.t('nav.home') => '/index.html', I18n.t('pictures.menu') => nil, title => nil }
|
|
178
|
-
unless
|
|
203
|
+
unless query['group_by'].nil?
|
|
179
204
|
h[title] = 'index.html'
|
|
180
|
-
extra_key = I18n.t("pictures.nav.#{
|
|
181
|
-
filters =
|
|
205
|
+
extra_key = I18n.t("pictures.nav.#{group_by(query)}")
|
|
206
|
+
filters = selector(query).values
|
|
182
207
|
extra_key += " (#{filters.join(', ')})" unless filters.empty?
|
|
183
208
|
h.store(extra_key, nil)
|
|
184
209
|
end
|
|
185
210
|
h
|
|
186
211
|
end
|
|
187
212
|
|
|
188
|
-
def gallery_url(
|
|
189
|
-
filters.store(
|
|
213
|
+
def gallery_url(key, value, filters = {})
|
|
214
|
+
filters.store(key, value)
|
|
190
215
|
filters.store('sort_by', 'datetime')
|
|
191
|
-
filters
|
|
216
|
+
hash_to_query(filters)
|
|
192
217
|
end
|
|
193
218
|
|
|
194
219
|
def serve_home
|
|
@@ -199,9 +224,9 @@ module Intranet
|
|
|
199
224
|
[404, '', '']
|
|
200
225
|
end
|
|
201
226
|
|
|
202
|
-
def
|
|
203
|
-
groups =
|
|
204
|
-
content = to_markup('pictures_browse', nav: make_nav(
|
|
227
|
+
def serve_browse(query)
|
|
228
|
+
groups = collect_groups(selector(query), group_by(query), sort_by(query), sort_order(query))
|
|
229
|
+
content = to_markup('pictures_browse', nav: make_nav(query), group_key: group_by(query),
|
|
205
230
|
filters: selector(query), groups: groups)
|
|
206
231
|
[206, 'text/html',
|
|
207
232
|
{ content: content, title: title, stylesheets: stylesheets, scripts: scripts }]
|
|
@@ -222,28 +247,32 @@ module Intranet
|
|
|
222
247
|
### Servicing of the REST API (raw JSON data & pictures) ###
|
|
223
248
|
##########################################################################
|
|
224
249
|
|
|
225
|
-
def
|
|
226
|
-
|
|
227
|
-
@provider.list_groups(group_type, selector(query), sort_by(query), sort_order(query))
|
|
228
|
-
end
|
|
250
|
+
def api_group_thumbnail(query)
|
|
251
|
+
raise KeyError unless query.size == 1
|
|
229
252
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
pic = @provider.group_thumbnail(group_type, selector(query))
|
|
253
|
+
key, value = query.first
|
|
254
|
+
pic = @provider.group_thumbnail(key, value)
|
|
233
255
|
if pic.nil?
|
|
234
256
|
pic = ['image/svg+xml', File.read(File.join(resources_dir, 'www', 'group_thumbnail.svg'))]
|
|
235
257
|
end
|
|
236
258
|
pic
|
|
237
259
|
end
|
|
238
260
|
|
|
261
|
+
def api_group_brief(query)
|
|
262
|
+
raise KeyError unless query.size == 1
|
|
263
|
+
|
|
264
|
+
key, value = query.first
|
|
265
|
+
@provider.group_brief(key, value)
|
|
266
|
+
end
|
|
267
|
+
|
|
239
268
|
def api_list_pictures(query)
|
|
240
269
|
@provider.list_pictures(selector(query), sort_by(query), sort_order(query))
|
|
241
270
|
end
|
|
242
271
|
|
|
243
272
|
def serve_api(path, query)
|
|
244
273
|
case path
|
|
245
|
-
when %r{^/
|
|
246
|
-
when %r{^/
|
|
274
|
+
when %r{^/group_thumbnail$} then [200, api_group_thumbnail(query)].flatten
|
|
275
|
+
when %r{^/group_brief$} then [200, 'application/json', api_group_brief(query).to_json]
|
|
247
276
|
when %r{^/pictures$} then [200, 'application/json', api_list_pictures(query).to_json]
|
|
248
277
|
when %r{^/picture$} then [200, @provider.picture(query)].flatten
|
|
249
278
|
else [404, '', '']
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
%section
|
|
2
2
|
= to_markup 'title_and_breadcrumb', {title: title, nav: nav}
|
|
3
3
|
%ul.groups
|
|
4
|
-
- groups.each do |
|
|
5
|
-
%li{ title:
|
|
6
|
-
%a{ onclick: 'openImagesGallery("' + gallery_url(
|
|
4
|
+
- groups.each do |group_name|
|
|
5
|
+
%li{ title: group_name }
|
|
6
|
+
%a{ onclick: 'openImagesGallery("' + gallery_url(group_key, group_name, filters) + '");' }
|
|
7
7
|
%figure
|
|
8
|
-
%div{ style: 'background-image: url("api/
|
|
8
|
+
%div{ style: 'background-image: url("api/group_thumbnail?' + group_key + '=' + group_name + '")' }
|
|
9
9
|
%figcaption
|
|
10
|
-
=
|
|
11
|
-
-
|
|
10
|
+
= group_name
|
|
11
|
+
- group_brief = api_group_brief({ group_key => group_name })
|
|
12
|
+
- unless group_brief.empty?
|
|
12
13
|
%br
|
|
13
|
-
%em=
|
|
14
|
+
%em= group_brief
|
|
@@ -2,32 +2,34 @@
|
|
|
2
2
|
= to_markup 'title_and_breadcrumb', {title: title, nav: nav}
|
|
3
3
|
|
|
4
4
|
- recent_groups.each do |recent|
|
|
5
|
-
%h3= I18n.t('pictures.recents.' + recent[:
|
|
5
|
+
%h3= I18n.t('pictures.recents.' + recent[:group_key])
|
|
6
6
|
%ul.groups
|
|
7
|
-
- recent[:groups].each do |
|
|
8
|
-
%li{ title:
|
|
9
|
-
%a{ onclick: 'openImagesGallery("' + gallery_url(recent[:
|
|
7
|
+
- recent[:groups].each do |group_name|
|
|
8
|
+
%li{ title: group_name }
|
|
9
|
+
%a{ onclick: 'openImagesGallery("' + gallery_url(recent[:group_key], group_name) + '");' }
|
|
10
10
|
%figure
|
|
11
|
-
%div{ style: 'background-image: url("api/
|
|
11
|
+
%div{ style: 'background-image: url("api/group_thumbnail?' + recent[:group_key] + '=' + group_name + '")' }
|
|
12
12
|
%figcaption
|
|
13
|
-
=
|
|
14
|
-
-
|
|
13
|
+
= group_name
|
|
14
|
+
- group_brief = api_group_brief({ recent[:group_key] => group_name })
|
|
15
|
+
- unless group_brief.empty?
|
|
15
16
|
%br
|
|
16
|
-
%em=
|
|
17
|
+
%em= group_brief
|
|
17
18
|
- unless recent[:see_more_url].empty?
|
|
18
19
|
%p.see_more
|
|
19
20
|
%a{ href: recent[:see_more_url] }= I18n.t('pictures.see_more')
|
|
20
21
|
|
|
21
22
|
- all_groups.each do |section|
|
|
22
|
-
%h3= I18n.t('pictures.browse_by.' + section[:
|
|
23
|
+
%h3= I18n.t('pictures.browse_by.' + section[:group_key])
|
|
23
24
|
%ul.groups.wide
|
|
24
|
-
- section[:groups].each do |
|
|
25
|
-
%li{ title:
|
|
26
|
-
%a{ href: section[:url_prefix] + '&' + section[:
|
|
25
|
+
- section[:groups].each do |group_name|
|
|
26
|
+
%li{ title: group_name }
|
|
27
|
+
%a{ href: section[:url_prefix] + '&' + section[:group_key] + '=' + group_name }
|
|
27
28
|
%figure
|
|
28
|
-
%div{ style: 'background-image: url("api/
|
|
29
|
+
%div{ style: 'background-image: url("api/group_thumbnail?' + section[:group_key] + '=' + group_name + '")' }
|
|
29
30
|
%figcaption
|
|
30
|
-
=
|
|
31
|
-
-
|
|
31
|
+
= group_name
|
|
32
|
+
- group_brief = api_group_brief({ section[:group_key] => group_name })
|
|
33
|
+
- unless group_brief.empty?
|
|
32
34
|
%br
|
|
33
|
-
%em=
|
|
35
|
+
%em= group_brief
|