drg_cms 0.6.1.0 → 0.6.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -10
- data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
- data/app/assets/javascripts/drg_cms/drg_cms.js +178 -55
- data/app/assets/stylesheets/drg_cms/drg_cms.css +218 -94
- data/app/assets/stylesheets/drg_cms/select-multiple.css +1 -1
- data/app/controllers/cmsedit_controller.rb +29 -24
- data/app/controllers/dc_application_controller.rb +78 -166
- data/app/controllers/dc_common_controller.rb +56 -47
- data/app/controls/dc_help_control.rb +12 -0
- data/app/controls/dc_report.rb +7 -9
- data/app/controls/design_element_settings_control.rb +1 -1
- data/app/forms/all_options.yml +25 -6
- data/app/forms/dc_big_table.yml +0 -2
- data/app/forms/dc_big_table_value.yml +0 -2
- data/app/forms/dc_design.yml +1 -2
- data/app/forms/dc_folder_permission.yml +0 -2
- data/app/forms/dc_help_1.yml +2 -1
- data/app/forms/dc_json_ld.yml +0 -3
- data/app/forms/dc_menu.yml +6 -12
- data/app/forms/dc_menu_item.yml +1 -3
- data/app/forms/dc_page.yml +5 -2
- data/app/forms/dc_policy.yml +2 -5
- data/app/forms/dc_poll.yml +10 -16
- data/app/forms/dc_seo.yml +1 -2
- data/app/forms/dc_simple_menu.yml +1 -2
- data/app/forms/dc_site.yml +5 -7
- data/app/helpers/cms_common_helper.rb +2 -3
- data/app/helpers/cms_edit_helper.rb +41 -31
- data/app/helpers/cms_helper.rb +6 -6
- data/app/helpers/cms_index_helper.rb +79 -34
- data/app/helpers/dc_application_helper.rb +99 -85
- data/app/models/concerns/dc_page_concern.rb +3 -2
- data/app/models/concerns/dc_piece_concern.rb +1 -1
- data/app/models/concerns/dc_site_concern.rb +10 -4
- data/app/models/concerns/dc_user_concern.rb +3 -3
- data/app/models/dc_big_table.rb +2 -2
- data/app/models/dc_filter.rb +28 -22
- data/app/models/dc_site.rb +0 -1
- data/app/models/dc_temp.rb +7 -0
- data/app/models/drgcms_form_fields/comment.rb +11 -2
- data/app/models/drgcms_form_fields/date_picker.rb +2 -0
- data/app/models/drgcms_form_fields/drgcms_field.rb +2 -1
- data/app/models/drgcms_form_fields/embedded.rb +4 -2
- data/app/models/drgcms_form_fields/number_field.rb +4 -3
- data/app/models/drgcms_form_fields/readonly.rb +13 -17
- data/app/models/drgcms_form_fields/select.rb +16 -18
- data/app/models/drgcms_form_fields/text_autocomplete.rb +39 -23
- data/app/renderers/dc_page_renderer.rb +7 -6
- data/app/renderers/dc_poll_renderer.rb +16 -20
- data/app/views/cmsedit/_edit_stuff.html.erb +5 -2
- data/app/views/cmsedit/_form.html.erb +3 -2
- data/app/views/cmsedit/_result.html.erb +21 -18
- data/app/views/cmsedit/edit.html.erb +2 -1
- data/app/views/cmsedit/index.html.erb +1 -1
- data/app/views/cmsedit/new.html.erb +3 -2
- data/app/views/dc_common/_help.html.erb +12 -3
- data/app/views/layouts/cms.html.erb +3 -5
- data/config/locales/drgcms_en.yml +5 -2
- data/config/locales/drgcms_sl.yml +5 -2
- data/config/locales/models_en.yml +2 -0
- data/config/locales/models_sl.yml +5 -3
- data/drg_cms.gemspec +16 -16
- data/lib/drg_cms/version.rb +1 -1
- data/lib/drg_cms.rb +46 -12
- metadata +35 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36ffde8dc003d78a30e69a2a1f45530841829c5b66d247e7bcece0d3c94a1a15
|
4
|
+
data.tar.gz: 3e1c6a0762f22cce3500de3c4ee0e2258c25f6f39a2aa3dc82f3febd15535449
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 562e2196260eefc0999249e1c0e871cda94b7fd2d303482d39314ec2eb6ae5ae4b32545b8a85c4434a28042d9c2c8b9f2c9dc0a1b1be3a0ec49d20cddece7aef
|
7
|
+
data.tar.gz: 03d0849a4040d4b99cf4b8c3b682e77b6c333ad562453700703b49a18d408d2e88555777051cf0b8f61d059ce4bf7e9f1670104f3e3ad786ea226c69c7217c08
|
data/README.md
CHANGED
@@ -1,12 +1,26 @@
|
|
1
1
|
# DrgCms
|
2
2
|
|
3
|
-
DRG CMS is advanced way of programming application for Ruby on Rails.
|
3
|
+
DRG CMS is advanced way of programming application for Ruby on Rails.
|
4
|
+
Instead of creating controllers and views for each collection (table),
|
5
|
+
DRG CMS introduces single Cmsedit controller. All CRUD database actions are
|
6
|
+
controlled by DRG Forms file, which can have hundreds of data entry fields
|
7
|
+
and still be easy to maintain and update.
|
4
8
|
|
5
|
-
DRG CMS uses
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
DRG CMS uses MongoDB, leading NO-SQL document database, as database back-end
|
10
|
+
with a help of mongoid gem. Mongoid's flexible document model defines all
|
11
|
+
document fields, indexes, dependencies, validations in single model source file with
|
12
|
+
no Rails migrations required. When collection model is defined, data entry DRG Form
|
13
|
+
can easily be generated with form generator.
|
14
|
+
|
15
|
+
DRG CMS can be used for rapid development of complex, data-entry intensive web
|
16
|
+
sites as well as building your private, in-house, Intranet applications. At
|
17
|
+
the same time it can be used as CMS system with support for running
|
18
|
+
multiple web sites on single Ruby on Rails instance.
|
19
|
+
|
20
|
+
DRG CMS has built-in user friendly role based database access system. Administrator
|
21
|
+
defines roles and roles rights (no access, can read, can edit) as web site policies.
|
22
|
+
Roles are then assigned to users and policies can be assigned to documents (web pages)
|
23
|
+
or even parts of a document.
|
10
24
|
|
11
25
|
Project Tracking
|
12
26
|
----------------
|
@@ -16,9 +30,10 @@ Project Tracking
|
|
16
30
|
Compatibility
|
17
31
|
-------------
|
18
32
|
|
19
|
-
DRG CMS is
|
20
|
-
|
21
|
-
|
33
|
+
DRG CMS is being actively developed since 2012 and has been live tested in production
|
34
|
+
since beginning. It runs against latest technology Ruby (3.0), Rails (6.1)
|
35
|
+
and MongoDB (4.4) and had so far little or no problems advancing to latest versions
|
36
|
+
of required programs.
|
22
37
|
|
23
38
|
Documentation
|
24
39
|
-------------
|
@@ -29,7 +44,7 @@ Please see the DRG CMS website for up-to-date documentation:
|
|
29
44
|
License (MIT LICENCE)
|
30
45
|
---------------------
|
31
46
|
|
32
|
-
Copyright (c) 2012-
|
47
|
+
Copyright (c) 2012-2021 Damjan Rems
|
33
48
|
|
34
49
|
Permission is hereby granted, free of charge, to any person obtaining
|
35
50
|
a copy of this software and associated documentation files (the
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -184,12 +184,12 @@ $(function() {
|
|
184
184
|
*******************************************************************/
|
185
185
|
|
186
186
|
process_json_result = function(json) {
|
187
|
-
|
187
|
+
let i, w, operation, selector, msg_div, field;
|
188
188
|
$.each(json, function(key, value) {
|
189
189
|
i = key.search('_');
|
190
190
|
if (i > 1) {
|
191
|
-
operation = key.substring(0,i);
|
192
|
-
selector = key.substring(i+1,100);
|
191
|
+
operation = key.substring(0, i);
|
192
|
+
selector = key.substring(i+1, 100);
|
193
193
|
} else {
|
194
194
|
operation = key;
|
195
195
|
selector = '';
|
@@ -207,7 +207,7 @@ process_json_result = function(json) {
|
|
207
207
|
// select field
|
208
208
|
} else if (field.is('select')) {
|
209
209
|
// options for select field
|
210
|
-
if (
|
210
|
+
if (Array.isArray(value)) {
|
211
211
|
field.empty();
|
212
212
|
$.each(value, function(index, v) {
|
213
213
|
field.append( new Option(v[0], v[1]) );
|
@@ -226,6 +226,11 @@ process_json_result = function(json) {
|
|
226
226
|
}
|
227
227
|
break;
|
228
228
|
|
229
|
+
/**** transfer focus to field ****/
|
230
|
+
case 'focus':
|
231
|
+
$('#' + value).focus();
|
232
|
+
break;
|
233
|
+
|
229
234
|
/**** display message ****/
|
230
235
|
case 'msg':
|
231
236
|
let msg_div = 'dc-form-' + selector;
|
@@ -240,9 +245,14 @@ process_json_result = function(json) {
|
|
240
245
|
|
241
246
|
/**** display popup message ****/
|
242
247
|
case 'popup':
|
243
|
-
|
244
|
-
|
245
|
-
|
248
|
+
if (selector == 'url') {
|
249
|
+
$('#popup').bPopup({ loadUrl: value });
|
250
|
+
}
|
251
|
+
else {
|
252
|
+
$('#popup').html(value);
|
253
|
+
$('#popup').bPopup({speed: 650, transition: 'slideUp', position: ['auto',1]});
|
254
|
+
}
|
255
|
+
break;
|
246
256
|
|
247
257
|
/**** update div ****/
|
248
258
|
case '#div+':
|
@@ -268,13 +278,16 @@ process_json_result = function(json) {
|
|
268
278
|
case 'url':
|
269
279
|
window.location.href = value;
|
270
280
|
break;
|
281
|
+
case 'parenturl':
|
282
|
+
parent.location.href = value;
|
283
|
+
break;
|
271
284
|
case 'alert':
|
272
285
|
alert(value);
|
273
286
|
break;
|
274
287
|
case 'window':
|
275
288
|
if (value == 'close') { window.close();
|
276
289
|
} else if (value == 'reload') {
|
277
|
-
location.
|
290
|
+
window.location.href = window.location.href;
|
278
291
|
} else {
|
279
292
|
w = window.open(value, selector);
|
280
293
|
w.focus();
|
@@ -294,10 +307,12 @@ process_json_result = function(json) {
|
|
294
307
|
case 'reload':
|
295
308
|
value = value.toString();
|
296
309
|
if (value == 'parent') {
|
297
|
-
parent.location.reload();
|
310
|
+
//parent.location.reload();
|
311
|
+
parent.location.href = parent.location.href;
|
312
|
+
|
298
313
|
/*** this would be current window (reload: true) ****/
|
299
314
|
} else if (value.length < 5) {
|
300
|
-
location.
|
315
|
+
window.location.href = window.location.href;
|
301
316
|
/*** reload iframe ****/
|
302
317
|
} else {
|
303
318
|
$( '#' + value ).attr('src', $( '#' + value ).attr('src'));
|
@@ -316,6 +331,17 @@ function dc_reload_window() {
|
|
316
331
|
location.reload();
|
317
332
|
}
|
318
333
|
|
334
|
+
/*******************************************************************
|
335
|
+
* Will open popup window
|
336
|
+
*******************************************************************/
|
337
|
+
function popup_window(url, title, parent_win, w, h) {
|
338
|
+
let y = parent_win.top.outerHeight / 2 + parent_win.top.screenY - (h / 2);
|
339
|
+
let x = parent_win.top.outerWidth / 2 + parent_win.top.screenX - (w / 2);
|
340
|
+
let win = parent_win.open(url, 'dc_popup', `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=${w}, height=${h}, top=${y}, left=${x}`);
|
341
|
+
win.document.title = title;
|
342
|
+
return win;
|
343
|
+
}
|
344
|
+
|
319
345
|
/*******************************************************************
|
320
346
|
* Will select first editable input field on form. Works only when tab
|
321
347
|
* is selected. Still have to find out, what to do on initial display.
|
@@ -377,6 +403,15 @@ dc_toggle_div = function(div) {
|
|
377
403
|
}
|
378
404
|
};
|
379
405
|
|
406
|
+
/*****************************************************************
|
407
|
+
* Return value of the input field on a form
|
408
|
+
******************************************************************/
|
409
|
+
function dc_get_field_value(field_name) {
|
410
|
+
field_name = field_name.replace('record_', '');
|
411
|
+
let field = $('[name="record[' + field_name + ']"]');
|
412
|
+
return field.val();
|
413
|
+
}
|
414
|
+
|
380
415
|
/*******************************************************************
|
381
416
|
*
|
382
417
|
*******************************************************************/
|
@@ -453,13 +488,48 @@ $(document).ready( function() {
|
|
453
488
|
* Sort action clicked on cmsedit
|
454
489
|
*******************************************************************/
|
455
490
|
$('.drgcms_sort').change( function(e) {
|
456
|
-
|
457
|
-
|
458
|
-
|
491
|
+
let table = e.target.getAttribute("data-table");
|
492
|
+
let form = e.target.getAttribute("data-form");
|
493
|
+
if (form === null) form = table;
|
494
|
+
let sort = e.target.value;
|
459
495
|
e.target.value = null;
|
460
496
|
window.location.href = "/cmsedit?sort=" + sort + "&table=" + table + "&form_name=" + form;
|
461
497
|
});
|
462
|
-
|
498
|
+
|
499
|
+
/*******************************************************************
|
500
|
+
* Click on dc-check-all icon. Check or uncheck all checkboxes
|
501
|
+
*******************************************************************/
|
502
|
+
$('.dc-check-all').on('click',function(e) {
|
503
|
+
let checkboxes = $('.dc-check');
|
504
|
+
if ($(this).hasClass('fa-check-square-o')) {
|
505
|
+
// check all checkboxes
|
506
|
+
checkboxes.each( function() {
|
507
|
+
$(this).prop('checked', true);
|
508
|
+
$(this).parent().closest('div').addClass('dc-checked');
|
509
|
+
});
|
510
|
+
$(this).removeClass('fa-check-square-o').addClass('fa-square-o');
|
511
|
+
} else {
|
512
|
+
// uncheck all checkboxes
|
513
|
+
checkboxes.each( function() {
|
514
|
+
$(this).prop('checked', false);
|
515
|
+
$(this).parent().closest('div').removeClass('dc-checked');
|
516
|
+
});
|
517
|
+
$(this).removeClass('fa-square-o').addClass('fa-check-square-o');
|
518
|
+
}
|
519
|
+
});
|
520
|
+
|
521
|
+
/*******************************************************************
|
522
|
+
* Click on dc-check icon. Change color of background of element
|
523
|
+
*******************************************************************/
|
524
|
+
$('.dc-check').on('click',function(e) {
|
525
|
+
let parent = $(this).parent().closest('div');
|
526
|
+
if ($(this).prop('checked')) {
|
527
|
+
parent.addClass('dc-checked');
|
528
|
+
} else {
|
529
|
+
parent.removeClass('dc-checked');
|
530
|
+
}
|
531
|
+
});
|
532
|
+
|
463
533
|
/*******************************************************************
|
464
534
|
* Tab clicked on form. Hide old and show selected div.
|
465
535
|
*******************************************************************/
|
@@ -523,7 +593,7 @@ $(document).ready( function() {
|
|
523
593
|
$('.iframe_embedded').on('load', function() {
|
524
594
|
let embedded_height = this.contentWindow.document.body.offsetHeight;
|
525
595
|
// workaround. It gets tricky when embedded field is on tab
|
526
|
-
if (embedded_height == 0) embedded_height =
|
596
|
+
if (embedded_height == 0) embedded_height = 50;
|
527
597
|
this.style.height = (embedded_height + 30) + 'px';
|
528
598
|
// resize parent iframe window too
|
529
599
|
let parentWindow = this.contentWindow.parent;
|
@@ -538,38 +608,55 @@ $(document).ready( function() {
|
|
538
608
|
$('.dc-link-ajax').on('click', function(e) {
|
539
609
|
// confirmation if required
|
540
610
|
if (confirmation_is_cancled(this)) {return false;}
|
541
|
-
|
611
|
+
|
612
|
+
// url must be specified in data-url
|
613
|
+
let url = this.getAttribute("data-url");
|
614
|
+
if (url.length < 5) return false;
|
615
|
+
|
542
616
|
// check HTML5 validations
|
543
617
|
if ($("form")[0] && !$("form")[0].checkValidity() ) {
|
544
618
|
$("form")[0].reportValidity();
|
545
619
|
return false;
|
546
620
|
}
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
621
|
+
|
622
|
+
let data = {};
|
623
|
+
let request = this.getAttribute("data-request");
|
624
|
+
switch (request) {
|
625
|
+
case 'script':
|
626
|
+
eval(this.getAttribute("data-script"));
|
627
|
+
return false;
|
628
|
+
|
629
|
+
case 'post':
|
630
|
+
data = $('form').serialize();
|
631
|
+
break;
|
632
|
+
|
633
|
+
default:
|
634
|
+
request = 'get'; // by default
|
559
635
|
}
|
560
636
|
|
561
|
-
|
562
|
-
|
637
|
+
// add checkbox id-s to data if checkboxes present
|
638
|
+
let checkboxes = $('.dc-check');
|
639
|
+
if (checkboxes.length > 0) {
|
640
|
+
let checked = [];
|
641
|
+
checkboxes.each( function() {
|
642
|
+
if ($(this).prop('checked')) checked.push($(this).attr("id"));
|
643
|
+
})
|
644
|
+
data['checked'] = checked;
|
645
|
+
}
|
563
646
|
|
564
647
|
$('.dc-spinner').show();
|
565
648
|
$.ajax({
|
566
649
|
url: url,
|
567
|
-
type:
|
650
|
+
type: request,
|
568
651
|
dataType: "json",
|
569
652
|
data: data,
|
570
653
|
success: function(data) {
|
571
654
|
process_json_result(data);
|
572
655
|
$('.dc-spinner').hide();
|
656
|
+
},
|
657
|
+
error: function (request, status, error) {
|
658
|
+
$('.dc-spinner').css('color','red');
|
659
|
+
alert(request.responseText);
|
573
660
|
}
|
574
661
|
});
|
575
662
|
});
|
@@ -593,24 +680,35 @@ $(document).ready( function() {
|
|
593
680
|
form.setAttribute('action', url);
|
594
681
|
form.setAttribute('method', "post");
|
595
682
|
form.submit();
|
596
|
-
});
|
597
|
-
|
683
|
+
});
|
684
|
+
|
598
685
|
/*******************************************************************
|
599
|
-
|
686
|
+
Will open a new window with URL specified.
|
600
687
|
********************************************************************/
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
688
|
+
$('.dc-window-open').on('click', function(e) {
|
689
|
+
// confirmation if required
|
690
|
+
if (confirmation_is_cancled(this)) { return false; }
|
691
|
+
|
692
|
+
let url = this.getAttribute("data-url");
|
693
|
+
let title = this.getAttribute("title");
|
694
|
+
let w = this.getAttribute("data-x") || 1000;
|
695
|
+
let h = this.getAttribute("data-y") || 800;
|
696
|
+
// add fields values from current formto url
|
697
|
+
let fields = this.getAttribute("data-fields");
|
698
|
+
if (fields) {
|
699
|
+
let form_parms = '?';
|
700
|
+
// ? separator already in url
|
701
|
+
if (url.match(/\?/)) { form_parms = ''; }
|
702
|
+
fields.split(',').forEach( function(field) {
|
703
|
+
let value = dc_get_field_value(field);
|
704
|
+
if (value) {form_parms += '&' + field + '=' + value;}
|
705
|
+
});
|
706
|
+
url += form_parms;
|
707
|
+
}
|
708
|
+
|
709
|
+
let win = popup_window(url, title, window, w, h);
|
710
|
+
win.focus();
|
711
|
+
});
|
614
712
|
|
615
713
|
/*******************************************************************
|
616
714
|
* Animate button on click
|
@@ -666,17 +764,28 @@ $(document).ready( function() {
|
|
666
764
|
|
667
765
|
$('.dc-link-submit').on('click', function(e) {
|
668
766
|
$('.dc-spinner').show();
|
669
|
-
});
|
767
|
+
});
|
768
|
+
|
769
|
+
/*******************************************************************
|
770
|
+
* Hide spinner when validation error occured
|
771
|
+
*******************************************************************/
|
772
|
+
$(':input').on("invalid", function(event) {
|
773
|
+
$('.dc-spinner').hide();
|
774
|
+
});
|
670
775
|
|
671
776
|
/*******************************************************************
|
672
777
|
* Add button clicked while in edit. Create window dialog for adding new record
|
673
778
|
* into required table. This is helper scenario, when user is selecting
|
674
779
|
* data from with text_autocomplete and data doesn't exist in belongs_to table.
|
675
780
|
*******************************************************************/
|
676
|
-
$('.in-edit-add').on('click', function(e) {
|
677
|
-
let
|
678
|
-
|
679
|
-
|
781
|
+
$('.in-edit-add').on('click', function(e) {
|
782
|
+
let id = this.getAttribute("data-id");
|
783
|
+
let table = this.getAttribute("data-table");
|
784
|
+
let url = '/cmsedit/new?window_close=0&table=' + table;
|
785
|
+
if (id) {
|
786
|
+
url = '/cmsedit/' + id + '/edit?window_close=0&table=' + table;
|
787
|
+
}
|
788
|
+
let w = popup_window(url, '', window, 1000, 800);
|
680
789
|
w.focus();
|
681
790
|
});
|
682
791
|
|
@@ -832,9 +941,16 @@ $(document).ready( function() {
|
|
832
941
|
* work on all field types.
|
833
942
|
*******************************************************************/
|
834
943
|
$('.record_filter_field_icon').on('click', function(e) {
|
835
|
-
|
836
|
-
|
837
|
-
|
944
|
+
let field = $('#_record__filter_field');
|
945
|
+
let url = $(this).parents('span').attr("data-url");
|
946
|
+
let value = null;
|
947
|
+
|
948
|
+
if (field.is(':checkbox')) {
|
949
|
+
value = field.is(':checked'); }
|
950
|
+
else {
|
951
|
+
value = field.val();
|
952
|
+
}
|
953
|
+
url = url + "&filter_value=" + value;
|
838
954
|
location.href = url;
|
839
955
|
});
|
840
956
|
|
@@ -1066,6 +1182,13 @@ $(document).ready( function() {
|
|
1066
1182
|
dc_toggle_div(div);
|
1067
1183
|
});
|
1068
1184
|
|
1185
|
+
/*******************************************************************
|
1186
|
+
* Show-Hide CMS menu on hamburger click
|
1187
|
+
*******************************************************************/
|
1188
|
+
$('#menu-hamburger').on('click', function(e) {
|
1189
|
+
$('.cmsedit-container #menu').toggleClass('visible');
|
1190
|
+
});
|
1191
|
+
|
1069
1192
|
});
|
1070
1193
|
|
1071
1194
|
/*******************************************************************
|