drg_cms 0.5.7 → 0.5.8
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/README.md +7 -3
- data/app/assets/javascripts/drg_cms/drg_cms.js +21 -4
- data/app/assets/stylesheets/drg_cms/drg_cms.css +92 -47
- data/app/controllers/cmsedit_controller.rb +22 -20
- data/app/controllers/drgcms_controls/browse_models_control.rb +107 -0
- data/app/controllers/drgcms_controls/{dc_page_controls.rb → dc_page_control.rb} +1 -1
- data/app/forms/all_options.yml +7 -0
- data/app/forms/cms_menu.yml +7 -0
- data/app/forms/dc_browse_fields.yml +32 -0
- data/app/forms/dc_browse_models.yml +26 -0
- data/app/forms/dc_site.yml +2 -2
- data/app/helpers/cmsedit_helper.rb +84 -59
- data/app/helpers/dc_application_helper.rb +1 -1
- data/app/helpers/dc_poll_renderer.rb +3 -2
- data/app/helpers/dc_simple_menu_renderer.rb +1 -1
- data/app/views/cmsedit/_result.html.erb +6 -8
- data/app/views/layouts/models.html.erb +14 -0
- data/app/views/models/dump_models.html.erb +47 -0
- data/config/locales/drgcms_en.yml +2 -0
- data/config/locales/drgcms_sl.yml +2 -0
- data/config/locales/models_en.yml +9 -0
- data/config/locales/models_sl.yml +11 -0
- data/lib/drg_cms/version.rb +1 -1
- data/lib/tasks/browse_models.rake +128 -0
- data/lib/tasks/database.rake +1 -1
- metadata +9 -5
- data/app/views/dc_mail/subscribe.html.erb +0 -7
- data/app/views/dc_mail/unsubscribe.html.erb +0 -19
@@ -0,0 +1,107 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2014+ Damjan Rems
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
######################################################################
|
26
|
+
#
|
27
|
+
######################################################################
|
28
|
+
module DrgcmsControls::BrowseModelsControl
|
29
|
+
include DcApplicationHelper
|
30
|
+
|
31
|
+
#########################################################################
|
32
|
+
# Determine model class from filename.
|
33
|
+
#########################################################################
|
34
|
+
def determine_model(path)
|
35
|
+
path =~ /(.*)\/(.*).rb/
|
36
|
+
begin
|
37
|
+
$2.camelize.constantize
|
38
|
+
$2
|
39
|
+
rescue Exception # it happends
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#########################################################################
|
45
|
+
# Return array of all models found in application.
|
46
|
+
#########################################################################
|
47
|
+
def all_collections()
|
48
|
+
collections = []
|
49
|
+
DrgCms.paths(:forms).each do |path|
|
50
|
+
models_dir = File.expand_path("../models", path)
|
51
|
+
Dir["#{models_dir}/*.rb"].each do |model_file|
|
52
|
+
collection_name = determine_model(model_file)
|
53
|
+
collections << collection_name if collection_name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
collections.sort
|
57
|
+
end
|
58
|
+
|
59
|
+
######################################################################
|
60
|
+
# List all collections
|
61
|
+
######################################################################
|
62
|
+
def collections()
|
63
|
+
@records = []
|
64
|
+
all_collections.each do |collection|
|
65
|
+
@records << {'id' => collection, 'description' => t("helpers.label.#{collection}.tabletitle") }
|
66
|
+
end
|
67
|
+
@records
|
68
|
+
end
|
69
|
+
|
70
|
+
######################################################################
|
71
|
+
# List field definition for single model
|
72
|
+
######################################################################
|
73
|
+
def fields()
|
74
|
+
@records = []
|
75
|
+
model = params[:id].classify.constantize
|
76
|
+
document = model.new
|
77
|
+
document.attribute_names.each do |attribute_name|
|
78
|
+
options = model.fields[attribute_name].options
|
79
|
+
description = I18n.t("helpers.help.#{params[:id]}.#{attribute_name}")
|
80
|
+
description = I18n.t("helpers.label.#{params[:id]}.#{attribute_name}") if description.match('missing:')
|
81
|
+
description = attribute_name if description.match('missing:')
|
82
|
+
|
83
|
+
@records << {'collection' => params[:id],
|
84
|
+
'field' => attribute_name,
|
85
|
+
'type' => options[:type],
|
86
|
+
'description' => description,
|
87
|
+
'_default' => options[:default]
|
88
|
+
}
|
89
|
+
end
|
90
|
+
# embedded documents
|
91
|
+
document.embedded_relations.each do |a_embedded|
|
92
|
+
embedded = a_embedded.last
|
93
|
+
description = I18n.t("helpers.help.#{params[:id]}.#{embedded.key}")
|
94
|
+
description = I18n.t("helpers.label.#{params[:id]}.#{embedded.key}") if description.match('missing:')
|
95
|
+
description = embedded.key if description.match('missing:')
|
96
|
+
|
97
|
+
@records << {'collection' => params[:id],
|
98
|
+
'field' => embedded.key,
|
99
|
+
'type' => 'Embedded:' + embedded.class_name,
|
100
|
+
'description' => description
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
@records
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -25,7 +25,7 @@
|
|
25
25
|
######################################################################
|
26
26
|
# DrgcmsControls for DcPage model.
|
27
27
|
######################################################################
|
28
|
-
module DrgcmsControls::
|
28
|
+
module DrgcmsControls::DcPageControl
|
29
29
|
|
30
30
|
######################################################################
|
31
31
|
# Called when new empty record is created
|
data/app/forms/all_options.yml
CHANGED
@@ -43,6 +43,10 @@ result_set:
|
|
43
43
|
filter: filter_vpis
|
44
44
|
actions_width: 100
|
45
45
|
per_page: 10
|
46
|
+
table_style: 'color: green;'
|
47
|
+
table_class: 'color: green;'
|
48
|
+
tr_style: 'color: green;'
|
49
|
+
tr_class: 'color: green;'
|
46
50
|
|
47
51
|
actions: standard
|
48
52
|
|
@@ -51,6 +55,9 @@ result_set:
|
|
51
55
|
2:
|
52
56
|
type: duplicate
|
53
57
|
dup_fields: name,another_field
|
58
|
+
td_class: class-name
|
59
|
+
td_style:
|
60
|
+
eval: "document['field'] == document['description'] ? 'color: gold;' : 'color: #000;'"
|
54
61
|
|
55
62
|
3:
|
56
63
|
type: delete
|
data/app/forms/cms_menu.yml
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
## Registration form. Not yet implemented.
|
2
|
+
---
|
3
|
+
table: dc_dummy
|
4
|
+
title: Browse field definitions
|
5
|
+
controls: browse_models
|
6
|
+
permissions:
|
7
|
+
can_view: admin
|
8
|
+
|
9
|
+
result_set:
|
10
|
+
filter: fields
|
11
|
+
tr_style:
|
12
|
+
eval: "document['field'] == document['description'] ? 'color: #669;' : 'color: #000;'"
|
13
|
+
|
14
|
+
columns:
|
15
|
+
10:
|
16
|
+
name: collection
|
17
|
+
caption: Collection
|
18
|
+
td_style: 'width: 150px;'
|
19
|
+
20:
|
20
|
+
name: field
|
21
|
+
caption: Field name
|
22
|
+
td_style: 'width: 150px;'
|
23
|
+
30:
|
24
|
+
name: type
|
25
|
+
caption: Field type
|
26
|
+
40:
|
27
|
+
name: description
|
28
|
+
caption: description
|
29
|
+
50:
|
30
|
+
name: _default
|
31
|
+
caption: Default
|
32
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
## Registration form. Not yet implemented.
|
2
|
+
---
|
3
|
+
table: dc_dummy
|
4
|
+
title: Browse collection models
|
5
|
+
controls: browse_models
|
6
|
+
permissions:
|
7
|
+
can_view: admin
|
8
|
+
|
9
|
+
result_set:
|
10
|
+
filter: collections
|
11
|
+
|
12
|
+
dblclick:
|
13
|
+
type: link
|
14
|
+
table: dc_dummy
|
15
|
+
formname: dc_browse_fields
|
16
|
+
action: index
|
17
|
+
|
18
|
+
columns:
|
19
|
+
10:
|
20
|
+
name: id
|
21
|
+
caption: Collection
|
22
|
+
td_style: 'font-weight: bold;width: 150px;'
|
23
|
+
|
24
|
+
20:
|
25
|
+
name: description
|
26
|
+
caption: Decription
|
data/app/forms/dc_site.yml
CHANGED
@@ -113,7 +113,7 @@ form:
|
|
113
113
|
60:
|
114
114
|
name: menu_name
|
115
115
|
type: text_with_select
|
116
|
-
eval: dc_choices4(
|
116
|
+
eval: dc_choices4(@record.menu_class,'description','name')
|
117
117
|
html:
|
118
118
|
size: 30
|
119
119
|
90:
|
@@ -146,7 +146,7 @@ form:
|
|
146
146
|
name: design
|
147
147
|
type: text_area
|
148
148
|
html:
|
149
|
-
size:
|
149
|
+
size: 130x40
|
150
150
|
|
151
151
|
5permissions:
|
152
152
|
|
@@ -230,56 +230,18 @@ def dc_link_or_ajax(yaml, parms) #:nodoc:
|
|
230
230
|
rest['class'] = rest['class'].to_s + ' dc-animate'
|
231
231
|
rest['title'] = yaml['title']
|
232
232
|
|
233
|
-
# method = yaml['method'] || yaml['request'] || 'get'
|
234
|
-
# caption = yaml['caption'] || yaml['text']
|
235
233
|
dc_deprecate "Form: result_set:action:text directive will be deprecated. Use caption instead of text." if yaml['text']
|
236
|
-
#
|
237
|
-
=begin
|
238
|
-
if yaml['type'] == 'link'
|
239
|
-
if yaml['icon'] # icon
|
240
|
-
link_to( image_tag(yaml['icon'], class: 'dc-link-img dc-link-ajax dc-animate'), parms, method: method, title: t(yaml['title'],yaml['title']) )
|
241
|
-
else # caption
|
242
|
-
'<span class="dc-link-ajax dc-animate">' + link_to(" #{t(caption, caption)} ", parms, method: method, title: t(yaml['title'],yaml['title']) ) + '</span>'
|
243
|
-
end
|
244
|
-
else # ajax
|
245
|
-
url = url_for(parms)
|
246
|
-
if yaml['icon'] # icon
|
247
|
-
image_tag(yaml['icon'], class: 'dc-link-img dc-link-ajax dc-animate', 'data-url' => url, 'data-request' => method)
|
248
|
-
else # caption
|
249
|
-
%Q[<span class="dc-link-ajax dc-animate" data-url="#{url}" data-request="#{method}">#{caption}</span>]
|
250
|
-
end
|
251
|
-
end
|
252
|
-
#####
|
253
|
-
caption = ''
|
254
|
-
if yaml['type'] == 'link'
|
255
|
-
if yaml['icon'] # icon
|
256
|
-
caption = if yaml['icon'].match('.')
|
257
|
-
image_tag(yaml['icon'], class: 'dc-link-img dc-link-ajax dc-animate')
|
258
|
-
else
|
259
|
-
fa_icon("#{yaml['icon']} 2x" , class: 'dc-link-ajax dc-animate')
|
260
|
-
end
|
261
|
-
end
|
262
|
-
if yaml['caption']
|
263
|
-
caption << ' ' if caption.size > 0
|
264
|
-
caption << t(yaml['caption'],yaml['caption'])
|
265
|
-
end
|
266
|
-
link_to(caption, parms, method: method, title: t(yaml['title'],yaml['title']) )
|
267
|
-
else
|
268
|
-
''
|
269
|
-
end
|
270
|
-
=end
|
271
234
|
if yaml['type'] == 'link'
|
272
235
|
dc_link_to(yaml['caption'], yaml['icon'], parms, rest )
|
273
236
|
else
|
274
237
|
''
|
275
238
|
end
|
276
|
-
|
277
239
|
end
|
278
240
|
|
279
241
|
############################################################################
|
280
242
|
# Creates actions that could be performed on single row of result set.
|
281
243
|
############################################################################
|
282
|
-
def dc_actions_for_result(
|
244
|
+
def dc_actions_for_result(document)
|
283
245
|
actions = @form['result_set']['actions']
|
284
246
|
return '' if actions.nil? or @form['readonly']
|
285
247
|
# standard actions
|
@@ -287,7 +249,7 @@ def dc_actions_for_result(record)
|
|
287
249
|
std_actions = {' 2' => 'edit', ' 3' => 'delete'}
|
288
250
|
actions.merge!(std_actions) if actions['standard']
|
289
251
|
#
|
290
|
-
width = @form['result_set']['actions_width'] ||
|
252
|
+
width = @form['result_set']['actions_width'] || 20*actions.size
|
291
253
|
html = "<td style=\"width: #{width}px;\">"
|
292
254
|
actions.each do |k,v|
|
293
255
|
session[:form_processing] = "result_set:actions: #{k}=#{v}"
|
@@ -297,31 +259,31 @@ def dc_actions_for_result(record)
|
|
297
259
|
html << case
|
298
260
|
when yaml['type'] == 'edit' then
|
299
261
|
parms['action'] = 'edit'
|
300
|
-
parms['id'] =
|
262
|
+
parms['id'] = document.id
|
301
263
|
dc_link_to( nil, 'pencil lg', parms )
|
302
264
|
when yaml['type'] == 'duplicate' then
|
303
|
-
parms['id'] =
|
265
|
+
parms['id'] = document.id
|
304
266
|
# duplicate string will be added to these fields.
|
305
267
|
parms['dup_fields'] = yaml['dup_fields']
|
306
268
|
parms['action'] = 'create'
|
307
269
|
dc_link_to( nil, 'copy lg', parms, data: { confirm: t('drgcms.confirm_dup') }, method: :post )
|
308
270
|
when yaml['type'] == 'delete' then
|
309
271
|
parms['action'] = 'destroy'
|
310
|
-
parms['id'] =
|
272
|
+
parms['id'] = document.id
|
311
273
|
dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
|
312
274
|
# undocumented so far
|
313
275
|
when yaml['type'] == 'edit_embedded'
|
314
276
|
parms['controller'] = 'cmsedit'
|
315
277
|
parms['table'] += ";#{yaml['table']}"
|
316
278
|
parms['ids'] ||= ''
|
317
|
-
parms['ids'] += "#{
|
279
|
+
parms['ids'] += "#{document.id};"
|
318
280
|
dc_link_to( nil, 'table lg', parms, method: :get )
|
319
281
|
when yaml['type'] == 'link' || yaml['type'] == 'ajax' then
|
320
282
|
if yaml['url']
|
321
283
|
parms['controller'] = yaml['url']
|
322
|
-
parms['idr'] =
|
284
|
+
parms['idr'] = document.id
|
323
285
|
else
|
324
|
-
parms['id'] =
|
286
|
+
parms['id'] = document.id
|
325
287
|
end
|
326
288
|
parms['controller'] = yaml['controller'] if yaml['controller']
|
327
289
|
parms['action'] = yaml['action'] if yaml['action']
|
@@ -343,19 +305,26 @@ end
|
|
343
305
|
def dc_header_for_result()
|
344
306
|
c = ''
|
345
307
|
actions = @form['result_set']['actions']
|
346
|
-
c = '<th
|
347
|
-
|
308
|
+
c = '<th> </th>' unless actions.nil? or @form['readonly']
|
309
|
+
# preparation for sort icon
|
310
|
+
sort_field, sort_direction = nil, nil
|
311
|
+
if session[@form['table']]
|
312
|
+
sort_field, sort_direction = session[@form['table']][:sort].to_s.split(' ')
|
313
|
+
end
|
314
|
+
#
|
348
315
|
if (columns = @form['result_set']['columns'])
|
349
316
|
columns.each do |k,v|
|
350
317
|
session[:form_processing] = "result_set:columns: #{k}=#{v}"
|
351
318
|
th = '<th '
|
352
|
-
v = {'name' => v} if v.class == String
|
319
|
+
v = {'name' => v} if v.class == String
|
353
320
|
caption = v['caption'] || t("helpers.label.#{@form['table']}.#{v['name']}")
|
354
|
-
th << "style=\"#{v['style']}\" " if v['style']
|
355
|
-
th << "class=\"#{v['class']}\" " if v['class']
|
356
321
|
# no sorting when embedded field or custom filter is active
|
357
322
|
if @tables.size == 1 and @form['result_set']['filter'].nil?
|
358
|
-
|
323
|
+
icon = 'sort lg'
|
324
|
+
if v['name'] == sort_field
|
325
|
+
icon = sort_direction == '1' ? 'sort-alpha-asc lg' : 'sort-alpha-desc lg'
|
326
|
+
end
|
327
|
+
th << ">#{dc_link_to(caption, icon, sort: v['name'], table: @tables[0][1], action: :index )}</th>"
|
359
328
|
else
|
360
329
|
th << ">#{caption}</th>"
|
361
330
|
end
|
@@ -365,6 +334,30 @@ def dc_header_for_result()
|
|
365
334
|
c.html_safe
|
366
335
|
end
|
367
336
|
|
337
|
+
############################################################################
|
338
|
+
# Creates div with documents of current result set.
|
339
|
+
############################################################################
|
340
|
+
def dc_clicks_for_result(document)
|
341
|
+
html = ''
|
342
|
+
if @form['result_set']['dblclick']
|
343
|
+
yaml = @form['result_set']['dblclick']
|
344
|
+
opts = {}
|
345
|
+
opts[:controller] = yaml['controller'] || 'cmsedit'
|
346
|
+
opts[:action] = yaml['action']
|
347
|
+
opts[:table] = yaml['table']
|
348
|
+
opts[:formname] = yaml['formname']
|
349
|
+
opts[:method] = yaml['method'] || 'get'
|
350
|
+
opts[:id] = document['id']
|
351
|
+
html << ' data-dblclick=' + url_for(opts)
|
352
|
+
else
|
353
|
+
html << (' data-dblclick=' +
|
354
|
+
url_for(action: 'show', controller: 'cmsedit', id: document,
|
355
|
+
readonly: (params[:readonly] ? 2 : 1), table: params[:table],
|
356
|
+
formname: params[:formname], ids: params[:ids]) ) if @form['form']
|
357
|
+
end
|
358
|
+
html
|
359
|
+
end
|
360
|
+
|
368
361
|
############################################################################
|
369
362
|
# Formats value according to format supplied or data type. There is lots of things missing here.
|
370
363
|
############################################################################
|
@@ -384,7 +377,31 @@ def dc_format_value(value, format=nil)
|
|
384
377
|
end
|
385
378
|
|
386
379
|
############################################################################
|
387
|
-
#
|
380
|
+
# Defines style or class for row (tr) or column (td)
|
381
|
+
############################################################################
|
382
|
+
def dc_style_or_class(selector, yaml, value, document)
|
383
|
+
return '' if yaml.nil?
|
384
|
+
html = selector ? "#{selector}=\"" : ''
|
385
|
+
html << if yaml.class == String
|
386
|
+
yaml
|
387
|
+
else
|
388
|
+
(yaml['eval'] ? eval(yaml['eval']) : '') rescue 'background-color:red;'
|
389
|
+
end
|
390
|
+
html << '"' if selector
|
391
|
+
html
|
392
|
+
end
|
393
|
+
|
394
|
+
############################################################################
|
395
|
+
# Creates tr code for each row of result set.
|
396
|
+
############################################################################
|
397
|
+
def dc_row_for_result(document)
|
398
|
+
clas = "dc-#{cycle('odd','even')} " + dc_style_or_class(nil,@form['result_set']['tr_class'],nil,document)
|
399
|
+
style = dc_style_or_class('style',@form['result_set']['tr_style'],nil,document)
|
400
|
+
"<tr class=\"#{clas}\" #{dc_clicks_for_result(document)} #{style}>".html_safe
|
401
|
+
end
|
402
|
+
|
403
|
+
############################################################################
|
404
|
+
# Creates column for each field of result set document.
|
388
405
|
############################################################################
|
389
406
|
def dc_columns_for_result(document)
|
390
407
|
html = ''
|
@@ -393,9 +410,6 @@ def dc_columns_for_result(document)
|
|
393
410
|
session[:form_processing] = "result_set:columns: #{k}=#{v}"
|
394
411
|
# convert shortcut to hash
|
395
412
|
v = {'name' => v} if v.class == String
|
396
|
-
td = '<td '
|
397
|
-
td << "style=\"#{v['style']}\" " if v['style']
|
398
|
-
td << "class=\"#{v['class']}\" " if v['class']
|
399
413
|
# eval
|
400
414
|
value = if v['eval']
|
401
415
|
if v['eval'].match('dc_name4_id')
|
@@ -424,10 +438,21 @@ def dc_columns_for_result(document)
|
|
424
438
|
eval( "#{v['eval']} '#{document[ v['name'] ]}'")
|
425
439
|
end
|
426
440
|
end
|
427
|
-
|
428
|
-
|
441
|
+
# as field
|
442
|
+
elsif document.respond_to?(v['name'])
|
443
|
+
dc_format_value(document.send( v['name'] ), v['format'])
|
444
|
+
# as hash (dc_dummy)
|
445
|
+
elsif document.class == Hash
|
446
|
+
document[ v['name'] ]
|
447
|
+
# error
|
448
|
+
else
|
449
|
+
"!!! #{v['name']}"
|
429
450
|
end
|
430
|
-
|
451
|
+
#
|
452
|
+
td = '<td '
|
453
|
+
td << dc_style_or_class('class',v['td_class'],value,document)
|
454
|
+
td << dc_style_or_class('style',v['td_style'],value,document)
|
455
|
+
html << "#{td}>#{value}</td>"
|
431
456
|
end
|
432
457
|
end
|
433
458
|
html.html_safe
|