biovision-base 0.8.171029 → 0.9.171227

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +49 -0
  3. data/app/assets/images/biovision/base/icons/breadcrumb-hover.svg +1 -0
  4. data/app/assets/images/biovision/base/icons/breadcrumb.svg +1 -0
  5. data/app/assets/images/biovision/base/placeholders/file.svg +1 -0
  6. data/app/assets/javascripts/biovision/base/biovision-sliders.js +64 -0
  7. data/app/assets/stylesheets/biovision/base/admin.scss +66 -53
  8. data/app/assets/stylesheets/biovision/base/biovision.scss +107 -55
  9. data/app/assets/stylesheets/biovision/base/layout.scss +64 -54
  10. data/app/assets/stylesheets/biovision/base/tootik.scss +70 -56
  11. data/app/assets/stylesheets/biovision/base/track.scss +2 -10
  12. data/app/controllers/admin/feedback_requests_controller.rb +23 -0
  13. data/app/controllers/admin/media_files_controller.rb +25 -0
  14. data/app/controllers/admin/media_folders_controller.rb +31 -0
  15. data/app/controllers/errors_controller.rb +43 -0
  16. data/app/controllers/feedback_requests_controller.rb +23 -0
  17. data/app/controllers/media_files_controller.rb +104 -0
  18. data/app/controllers/media_folders_controller.rb +85 -0
  19. data/app/helpers/biovision_users_helper.rb +7 -0
  20. data/app/helpers/media_helper.rb +26 -0
  21. data/app/mailers/feedback_mailer.rb +10 -0
  22. data/app/models/editable_page.rb +1 -1
  23. data/app/models/feedback_request.rb +31 -0
  24. data/app/models/media_file.rb +48 -0
  25. data/app/models/media_folder.rb +114 -0
  26. data/app/models/metric.rb +4 -1
  27. data/app/models/privilege_group.rb +1 -1
  28. data/app/uploaders/media_file_uploader.rb +30 -0
  29. data/app/uploaders/media_snapshot_uploader.rb +32 -0
  30. data/app/views/admin/feedback_requests/_nav_item.html.erb +2 -0
  31. data/app/views/admin/feedback_requests/entity/_in_list.html.erb +18 -0
  32. data/app/views/admin/feedback_requests/index.html.erb +16 -0
  33. data/app/views/admin/index/_biovision_base.html.erb +6 -0
  34. data/app/views/admin/index/_custom_dashboard.html.erb +0 -0
  35. data/app/views/admin/index/dashboard/_biovision_feedback.html.erb +9 -0
  36. data/app/views/admin/index/dashboard/_biovision_region.html.erb +8 -0
  37. data/app/views/admin/index/dashboard/_biovision_track.html.erb +8 -0
  38. data/app/views/admin/index/dashboard/_biovision_user.html.erb +13 -0
  39. data/app/views/admin/index/dashboard/_editorial.html.erb +12 -0
  40. data/app/views/admin/index/dashboard/_settings.html.erb +9 -0
  41. data/app/views/admin/index/index.html.erb +2 -22
  42. data/app/views/admin/media_files/_nav_item.html.erb +2 -0
  43. data/app/views/admin/media_files/entity/_in_list.html.erb +26 -0
  44. data/app/views/admin/media_files/index.html.erb +17 -0
  45. data/app/views/admin/media_files/show.html.erb +60 -0
  46. data/app/views/admin/media_folders/_nav_item.html.erb +2 -0
  47. data/app/views/admin/media_folders/entity/_in_list.html.erb +32 -0
  48. data/app/views/admin/media_folders/files.html.erb +28 -0
  49. data/app/views/admin/media_folders/index.html.erb +21 -0
  50. data/app/views/admin/media_folders/show.html.erb +79 -0
  51. data/app/views/application/error.html.erb +9 -0
  52. data/app/views/editable_pages/_editable_page.html.erb +1 -8
  53. data/app/views/editable_pages/entity/_metadata.html.erb +14 -0
  54. data/app/views/editable_pages/form/_ckeditor.html.erb +1 -1
  55. data/app/views/errors/error.html.erb +7 -0
  56. data/app/views/feedback_mailer/new_feedback_request.html.erb +12 -0
  57. data/app/views/feedback_mailer/new_feedback_request.text.erb +5 -0
  58. data/app/views/feedback_requests/_form.html.erb +60 -0
  59. data/app/views/feedback_requests/create.js.erb +10 -0
  60. data/app/views/media_files/_form.html.erb +75 -0
  61. data/app/views/media_files/ckeditor.html.erb +8 -0
  62. data/app/views/media_files/edit.html.erb +19 -0
  63. data/app/views/media_files/edit.js.erb +1 -0
  64. data/app/views/media_files/new.html.erb +15 -0
  65. data/app/views/media_files/new.js.erb +1 -0
  66. data/app/views/media_folders/_form.html.erb +54 -0
  67. data/app/views/media_folders/edit.html.erb +22 -0
  68. data/app/views/media_folders/edit.js.erb +1 -0
  69. data/app/views/media_folders/new.html.erb +19 -0
  70. data/app/views/media_folders/new.js.erb +1 -0
  71. data/app/views/shared/_meta_texts.html.erb +3 -0
  72. data/app/views/shared/_pagination.jbuilder +3 -3
  73. data/app/views/shared/admin/_toggleable.html.erb +7 -0
  74. data/app/views/shared/editable_pages/_body.html.erb +1 -10
  75. data/app/views/shared/forms/_default_ajax_handler.html.erb +13 -0
  76. data/app/views/shared/forms/_list_of_errors.js.erb +19 -0
  77. data/config/locales/common-en.yml +152 -0
  78. data/config/locales/common-ru.yml +41 -0
  79. data/config/locales/feedback-en.yml +30 -0
  80. data/config/locales/feedback-ru.yml +36 -0
  81. data/config/locales/media-ru.yml +92 -0
  82. data/config/routes.rb +34 -0
  83. data/db/migrate/20170301000002_create_metric_values.rb +1 -1
  84. data/db/migrate/20170301000102_create_agents.rb +1 -1
  85. data/db/migrate/20170302000001_create_users.rb +2 -2
  86. data/db/migrate/20170302000002_create_user_profiles.rb +1 -1
  87. data/db/migrate/20170302000003_create_tokens.rb +2 -2
  88. data/db/migrate/20170302000005_create_codes.rb +3 -3
  89. data/db/migrate/20170302000102_create_user_privileges.rb +3 -3
  90. data/db/migrate/20170302000104_create_privilege_group_privileges.rb +2 -2
  91. data/db/migrate/20170425000002_create_foreign_users.rb +3 -3
  92. data/db/migrate/20170629120000_create_login_attempts.rb +2 -2
  93. data/db/migrate/20171202000000_create_media_folders.rb +28 -0
  94. data/db/migrate/20171202000001_create_media_files.rb +27 -0
  95. data/db/migrate/20171211000000_create_feedback_requests.rb +26 -0
  96. data/db/migrate/20171217222222_add_fields_to_feedback_requests.rb +10 -0
  97. data/db/migrate/20171223333333_amend_foreign_keys.rb +72 -0
  98. data/lib/biovision/base/base_methods.rb +1 -1
  99. data/lib/biovision/base/engine.rb +1 -1
  100. data/lib/biovision/base/version.rb +1 -1
  101. metadata +94 -26
@@ -1,4 +1,4 @@
1
- // https://eliorshalev.github.io/tootik/
1
+ // Original: https://github.com/eliortabeka/tootik
2
2
 
3
3
  $tootik_background_color: #000000 !default;
4
4
  $tootik_success_color: #8bc34a !default;
@@ -11,44 +11,45 @@ $tootik_text_color: #ffffff !default;
11
11
  position: relative;
12
12
 
13
13
  &:after {
14
- content: attr(data-tootik);
14
+ background: $tootik_background_color;
15
+ border-radius: .7rem;
16
+ bottom: 100%;
15
17
  box-sizing: border-box;
18
+ color: $tootik_text_color;
19
+ content: attr(data-tootik);
20
+ font-size: 1.3rem;
16
21
  font-style: normal;
22
+ line-height: 1.4rem;
23
+ max-width: 32rem;
24
+ overflow: hidden;
25
+ padding: .6rem .6rem .5rem;
26
+ pointer-events: none;
17
27
  text-align: center;
18
- padding: 6px 6px 5px;
19
- font-size: 13px;
20
- line-height: 14px;
21
- border-radius: 7px;
22
- color: $tootik_text_color;
28
+ text-overflow: ellipsis;
23
29
  transition: opacity .3s cubic-bezier(.73, .01, 0, 1), transform .3s cubic-bezier(.73, .01, 0, 1);
24
- pointer-events: none;
25
- z-index: 100000;
30
+ transform: translate(calc(-100% + 1.4rem), 1.2rem);
26
31
  white-space: nowrap;
27
- bottom: 100%;
28
- transform: translate(-50%, 12px);
29
- max-width: 320px;
30
- text-overflow: ellipsis;
31
- overflow: hidden;
32
- background: $tootik_background_color;
32
+ z-index: 100000;
33
33
  }
34
34
 
35
- &:after, &:before {
35
+ &:after,
36
+ &:before {
37
+ backface-visibility: hidden;
38
+ left: 50%;
36
39
  opacity: 0;
37
40
  position: absolute;
38
- left: 50%;
39
- backface-visibility: hidden;
40
41
  }
41
42
 
42
43
  &:before {
43
- border: 4px solid transparent;
44
+ border: .4rem solid transparent;
44
45
  border-top-color: $tootik_background_color;
45
46
  border-bottom-width: 0;
46
47
  content: '';
47
- top: -2px;
48
- width: 0;
49
48
  height: 0;
50
- transform: translate(-50%, calc(-50% - 6px));
49
+ top: -.2rem;
50
+ transform: translate(-50%, calc(-50% - .6rem));
51
51
  transition: opacity .1s cubic-bezier(.73, .01, 0, 1) 0s, transform .6s cubic-bezier(.73, .01, 0, 1) 0s;
52
+ width: 0;
52
53
  z-index: 110000;
53
54
  }
54
55
 
@@ -73,80 +74,89 @@ $tootik_text_color: #ffffff !default;
73
74
  border-left-color: $tootik_background_color;
74
75
  }
75
76
 
76
- &:focus:after, &:focus:before, &:hover:after, &:hover:before {
77
+ &:focus:after,
78
+ &:focus:before,
79
+ &:hover:after,
80
+ &:hover:before {
77
81
  opacity: 1;
78
82
  }
79
83
 
80
- &:focus:before, &:hover:before {
84
+ &:focus:before,
85
+ &:hover:before {
81
86
  transition: opacity .1s cubic-bezier(.73, .01, 0, 1) .1s, transform .6s cubic-bezier(.73, .01, 0, 1) .1s;
82
- transform: translate(-50%, calc(-50% - 2px));
87
+ transform: translate(-50%, calc(-50% - .2rem));
83
88
  }
84
89
 
85
- &:focus:after, &:hover:after {
86
- transform: translate(-50%, -6px);
90
+ &:focus:after,
91
+ &:hover:after {
92
+ transform: translate(calc(-100% + 1.4rem), -.6rem);
87
93
  }
88
94
 
89
95
  &[data-tootik-conf*=right] {
90
96
  &:before {
91
- border: 4px solid;
97
+ border: .4rem solid;
92
98
  border-left-width: 0;
93
99
  left: auto;
94
- right: -6px;
100
+ right: -.6rem;
95
101
  top: 50%;
96
- transform: translate(calc(-50% + 7px), -50%);
102
+ transform: translate(calc(-50% + .7rem), -50%);
97
103
  }
98
104
 
99
105
  &:after {
100
106
  top: 50%;
101
107
  left: 100%;
102
108
  bottom: auto;
103
- transform: translate(-12px, -50%);
109
+ transform: translate(-1.2rem, -50%);
104
110
  }
105
111
 
106
- &:focus:before, &:hover:before {
107
- transform: translate(calc(-50% + 3px), -50%);
112
+ &:focus:before,
113
+ &:hover:before {
114
+ transform: translate(calc(-50% + .3rem), -50%);
108
115
  }
109
116
 
110
- &:focus:after, &:hover:after {
111
- transform: translate(7px, -50%);
117
+ &:focus:after,
118
+ &:hover:after {
119
+ transform: translate(.7rem, -50%);
112
120
  }
113
121
  }
114
122
 
115
123
  &[data-tootik-conf*=bottom] {
116
124
  &:before {
117
- border: 4px solid;
125
+ border: .4rem solid;
118
126
  border-top-width: 0;
119
127
  top: auto;
120
- bottom: -6px;
128
+ bottom: -.6rem;
121
129
  left: 50%;
122
- transform: translate(-50%, calc(-50% + 6px));
130
+ transform: translate(-50%, calc(-50% + .6rem));
123
131
  }
124
132
 
125
133
  &:after {
126
134
  top: 100%;
127
135
  left: 50%;
128
136
  bottom: auto;
129
- transform: translate(-50%, -12px);
137
+ transform: translate(-50%, -1.2rem);
130
138
  }
131
139
 
132
- &:focus:before, &:hover:before {
133
- transform: translate(-50%, calc(-50% + 2px));
140
+ &:focus:before,
141
+ &:hover:before {
142
+ transform: translate(-50%, calc(-50% + .2rem));
134
143
  }
135
144
 
136
- &:focus:after, &:hover:after {
137
- transform: translate(-50%, 6px);
145
+ &:focus:after,
146
+ &:hover:after {
147
+ transform: translate(-50%, .6rem);
138
148
  }
139
149
  }
140
150
 
141
151
  &[data-tootik-conf*=left] {
142
152
  &:before {
143
- border: 4px solid;
153
+ border: .4rem solid;
144
154
  border-right-width: 0;
145
- left: -2px;
155
+ left: -.2rem;
146
156
  top: 50%;
147
157
  width: 0;
148
158
  height: 0;
149
- transform: translate(calc(-50% - 8px), -50%);
159
+ transform: translate(calc(-50% - .8rem), -50%);
150
160
  }
151
161
 
152
162
  &:after {
@@ -154,23 +164,25 @@ $tootik_text_color: #ffffff !default;
154
164
  right: 100%;
155
165
  bottom: auto;
156
166
  left: auto;
157
- transform: translate(12px, -50%);
167
+ transform: translate(1.2rem, -50%);
158
168
  }
159
169
 
160
- &:focus:after, &:hover:after {
161
- transform: translate(-7px, -50%);
170
+ &:focus:after,
171
+ &:hover:after {
172
+ transform: translate(-.7rem, -50%);
162
173
  }
163
174
 
164
- &:focus:before, &:hover:before {
165
- transform: translate(calc(-50% - 3px), -50%);
175
+ &:focus:before,
176
+ &:hover:before {
177
+ transform: translate(calc(-50% - .3rem), -50%);
166
178
  }
167
179
  }
168
180
 
169
181
  &[data-tootik-conf*=multiline]:after {
170
182
  word-break: break-all;
171
183
  white-space: normal;
172
- min-width: 140px;
173
- max-width: 140px;
184
+ min-width: 14rem;
185
+ max-width: 14rem;
174
186
  text-overflow: clip;
175
187
  }
176
188
 
@@ -193,10 +205,11 @@ $tootik_text_color: #ffffff !default;
193
205
  }
194
206
 
195
207
  &[data-tootik-conf*=shadow]:after {
196
- box-shadow: 0 2px 10px 2px rgba(0, 0, 0, .1);
208
+ box-shadow: 0 .2rem 1rem .2rem rgba(0, 0, 0, .1);
197
209
  }
198
210
 
199
- &[data-tootik-conf*=no-fading]:after, &[data-tootik-conf*=no-fading]:before {
211
+ &[data-tootik-conf*=no-fading]:after,
212
+ &[data-tootik-conf*=no-fading]:before {
200
213
  transition: none;
201
214
  }
202
215
 
@@ -379,7 +392,8 @@ $tootik_text_color: #ffffff !default;
379
392
  }
380
393
  }
381
394
 
382
- &[data-tootik='']:after, &[data-tootik='']:before {
395
+ &[data-tootik='']:after,
396
+ &[data-tootik='']:before {
383
397
  display: none;
384
398
  }
385
399
  }
@@ -14,16 +14,8 @@
14
14
 
15
15
  div.track {
16
16
  border: .1rem dotted;
17
- box-sizing: border-box;
17
+ color: $text-color-secondary;
18
18
  font-size: $font-size-decreased;
19
- margin: .4rem;
19
+ margin: 1.6rem .4rem;
20
20
  padding: .4rem;
21
- width: 100%;
22
-
23
- > div {
24
- //overflow: hidden;
25
- //text-overflow: ellipsis;
26
- //white-space: nowrap;
27
- //width: 100%;
28
- }
29
21
  }
@@ -0,0 +1,23 @@
1
+ class Admin::FeedbackRequestsController < AdminController
2
+ include ToggleableEntity
3
+
4
+ before_action :set_entity, except: [:index]
5
+
6
+ # get /admin/feedback_requests
7
+ def index
8
+ @collection = FeedbackRequest.page_for_administration(current_page)
9
+ end
10
+
11
+ private
12
+
13
+ def restrict_access
14
+ require_privilege :feedback_manager
15
+ end
16
+
17
+ def set_entity
18
+ @entity = FeedbackRequest.find_by(id: params[:id])
19
+ if @entity.nil?
20
+ handle_http_404('Cannot find feedback request')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ class Admin::MediaFilesController < AdminController
2
+ before_action :set_entity, except: [:index]
3
+
4
+ # get /admin/media_files
5
+ def index
6
+ @collection = MediaFile.page_for_administration(current_page)
7
+ end
8
+
9
+ # get /admin/media_files/:id
10
+ def show
11
+ end
12
+
13
+ private
14
+
15
+ def set_entity
16
+ @entity = MediaFile.find_by(id: params[:id])
17
+ if @entity.nil?
18
+ handle_http_404('Cannot find media file')
19
+ end
20
+ end
21
+
22
+ def restrict_access
23
+ require_privilege_group :editorial_office
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ class Admin::MediaFoldersController < AdminController
2
+ before_action :set_entity, except: [:index]
3
+
4
+ # get /admin/media_folders
5
+ def index
6
+ @collection = MediaFolder.for_tree(params[:parent_id])
7
+ end
8
+
9
+ # get /admin/media_folders/:id
10
+ def show
11
+ @collection = MediaFolder.for_tree(@entity.id)
12
+ end
13
+
14
+ # get /admin/media_folders/:id/files
15
+ def files
16
+ @collection = @entity.media_files.page_for_administration(current_page)
17
+ end
18
+
19
+ private
20
+
21
+ def set_entity
22
+ @entity = MediaFolder.find_by(id: params[:id])
23
+ if @entity.nil?
24
+ handle_http_404('Cannot find media folder')
25
+ end
26
+ end
27
+
28
+ def restrict_access
29
+ require_privilege_group :editors
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+ class ErrorsController < ApplicationController
2
+ # /400
3
+ def bad_request
4
+ Metric.register(Metric::METRIC_HTTP_400)
5
+
6
+ render :error, status: :bad_request
7
+ end
8
+
9
+ # /401
10
+ def unauthorized
11
+ Metric.register(Metric::METRIC_HTTP_401)
12
+
13
+ render :error, status: :unauthorized
14
+ end
15
+
16
+ # /403
17
+ def forbidden
18
+ Metric.register(Metric::METRIC_HTTP_403)
19
+
20
+ render :error, status: :forbidden
21
+ end
22
+
23
+ # /404
24
+ def not_found
25
+ Metric.register(Metric::METRIC_HTTP_404)
26
+
27
+ render :error, status: :not_found
28
+ end
29
+
30
+ # 422
31
+ def unprocessable_entity
32
+ Metric.register(Metric::METRIC_HTTP_422)
33
+
34
+ render :error, status: :unprocessable_entity
35
+ end
36
+
37
+ # /500
38
+ def internal_server_error
39
+ Metric.register(Metric::METRIC_HTTP_500)
40
+
41
+ render :error, status: :internal_server_error
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ class FeedbackRequestsController < ApplicationController
2
+ # post /feedback_requests
3
+ def create
4
+ @entity = FeedbackRequest.new(creation_parameters)
5
+ if @entity.save
6
+ respond_to do |format|
7
+ format.html { redirect_to root_path }
8
+ format.js
9
+ end
10
+
11
+ FeedbackMailer.new_feedback_request(@entity.id).deliver_later
12
+ else
13
+ redirect_to root_path
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def creation_parameters
20
+ parameters = params.require(:feedback_request).permit(FeedbackRequest.creation_parameters)
21
+ parameters.merge(tracking_for_entity)
22
+ end
23
+ end
@@ -0,0 +1,104 @@
1
+ class MediaFilesController < ApplicationController
2
+ skip_before_action :verify_authenticity_token, only: :ckeditor
3
+
4
+ before_action :set_entity, only: [:edit, :update, :destroy]
5
+ before_action :restrict_editing, only: [:edit, :update, :destroy]
6
+
7
+ layout 'admin', except: :ckeditor
8
+
9
+ # get /media_files/new
10
+ def new
11
+ @entity = MediaFile.new
12
+ end
13
+
14
+ # post /media_files
15
+ def create
16
+ @entity = MediaFile.new(creation_parameters)
17
+ if @entity.save
18
+ next_page = admin_media_file_path(@entity.id)
19
+ respond_to do |format|
20
+ format.html { redirect_to(next_page) }
21
+ format.json { render json: { links: { self: next_page } } }
22
+ format.js { render(js: "document.location.href = '#{next_page}'") }
23
+ end
24
+ else
25
+ render :new, status: :bad_request
26
+ end
27
+ end
28
+
29
+ # get /media_files/:id/edit
30
+ def edit
31
+ end
32
+
33
+ # patch /media_files/:id
34
+ def update
35
+ if @entity.update entity_parameters
36
+ next_page = admin_media_file_path(@entity)
37
+ respond_to do |format|
38
+ format.html { redirect_to(next_page, notice: t('media_files.update.success')) }
39
+ format.json { render json: { links: { self: next_page } } }
40
+ format.js { render(js: "document.location.href = '#{next_page}'") }
41
+ end
42
+ else
43
+ render :edit, status: :bad_request
44
+ end
45
+ end
46
+
47
+ # delete /media_files/:id
48
+ def destroy
49
+ if @entity.destroy
50
+ flash[:notice] = t('media_files.destroy.success')
51
+ end
52
+ redirect_to(admin_media_files_path)
53
+ end
54
+
55
+ def ckeditor
56
+ parameters = {
57
+ file: params[:upload],
58
+ snapshot: params[:upload],
59
+ name: params[:upload].original_filename,
60
+ original_name: params[:upload].original_filename,
61
+ }.merge(owner_for_entity(true))
62
+
63
+ @entity = MediaFile.create!(parameters)
64
+
65
+ render layout: false
66
+ end
67
+
68
+ protected
69
+
70
+ def restrict_access
71
+ require_privilege_group :editors
72
+ end
73
+
74
+ def restrict_upload
75
+ require_privilege_group :editorial_office
76
+ end
77
+
78
+ def restrict_editing
79
+ unless @entity.editable_by?(current_user)
80
+ redirect_to admin_media_file_path(@entity.id), alert: t('media_files.edit.forbidden')
81
+ end
82
+ end
83
+
84
+ def set_entity
85
+ @entity = MediaFile.find_by(id: params[:id])
86
+ if @entity.nil?
87
+ handle_http_404('Cannot find media_file')
88
+ end
89
+ end
90
+
91
+ def entity_parameters
92
+ params.require(:media_file).permit(MediaFile.entity_parameters)
93
+ end
94
+
95
+ def creation_parameters
96
+ media_file = params.require(:media_file)
97
+ parameters = media_file.permit(MediaFile.creation_parameters)
98
+ if media_file[:file]
99
+ file = media_file[:file]
100
+ parameters.merge!(snapshot: file, original_name: file.original_filename)
101
+ end
102
+ parameters.merge(owner_for_entity(true))
103
+ end
104
+ end
@@ -0,0 +1,85 @@
1
+ class MediaFoldersController < AdminController
2
+ before_action :set_entity, only: [:edit, :update, :destroy]
3
+ before_action :restrict_editing, only: [:edit, :update, :destroy]
4
+ before_action :restrict_destroying, only: [:destroy]
5
+
6
+ # get /media_folders/new
7
+ def new
8
+ @entity = MediaFolder.new
9
+ end
10
+
11
+ # post /media_folders
12
+ def create
13
+ @entity = MediaFolder.new(creation_parameters)
14
+ if @entity.save
15
+ next_page = admin_media_folder_path(@entity.id)
16
+ respond_to do |format|
17
+ format.html { redirect_to next_page }
18
+ format.json { render json: { links: { self: next_page } } }
19
+ format.js { render js: "document.location.href = '#{next_page}'" }
20
+ end
21
+ else
22
+ render :new, status: :bad_request
23
+ end
24
+ end
25
+
26
+ # get /media_folders/:id/edit
27
+ def edit
28
+ end
29
+
30
+ # patch /media_folders/:id
31
+ def update
32
+ if @entity.update(entity_parameters)
33
+ next_page = admin_media_folder_path(@entity.id)
34
+ respond_to do |format|
35
+ format.html { redirect_to next_page }
36
+ format.json { render json: { links: { self: next_page } } }
37
+ format.js { render js: "document.location.href = '#{next_page}'" }
38
+ end
39
+ else
40
+ render :edit, status: :bad_request
41
+ end
42
+ end
43
+
44
+ # delete /media_folders/:id
45
+ def destroy
46
+ if @entity.destroy
47
+ flash[:notice] = t('media_folders.destroy.success')
48
+ end
49
+ redirect_to admin_media_folders_path
50
+ end
51
+
52
+ private
53
+
54
+ def set_entity
55
+ @entity = MediaFolder.find_by(id: params[:id])
56
+ if @entity.nil?
57
+ handle_http_404('Cannot find post')
58
+ end
59
+ end
60
+
61
+ def restrict_access
62
+ require_privilege_group :editors
63
+ end
64
+
65
+ def restrict_editing
66
+ unless @entity.editable_by?(current_user)
67
+ handle_http_403('MediaFolder is not editable by current user')
68
+ end
69
+ end
70
+
71
+ def restrict_destroying
72
+ unless @entity.can_be_deleted?
73
+ handle_http_403('MediaFolder cannot be deleted')
74
+ end
75
+ end
76
+
77
+ def entity_parameters
78
+ params.require(:media_folder).permit(MediaFolder.entity_parameters)
79
+ end
80
+
81
+ def creation_parameters
82
+ parameters = params.require(:media_folder).permit(MediaFolder.creation_parameters)
83
+ parameters.merge(owner_for_entity(true))
84
+ end
85
+ end
@@ -21,6 +21,13 @@ module BiovisionUsersHelper
21
21
  link_to(text, admin_user_path(entity.id), class: 'profile')
22
22
  end
23
23
 
24
+ # @param [User] entity
25
+ def editor_user_link(entity)
26
+ return t(:anonymous) if entity.nil?
27
+
28
+ entity.profile_name
29
+ end
30
+
24
31
  # @param [Token] entity
25
32
  def admin_token_link(entity)
26
33
  link_to entity.name, admin_token_path(entity.id)
@@ -0,0 +1,26 @@
1
+ module MediaHelper
2
+ # @param [MediaFolder] entity
3
+ # @param [String] text
4
+ def admin_media_folder_link(entity, text = entity.name)
5
+ link_to(text, admin_media_folder_path(entity.id))
6
+ end
7
+
8
+ # @param [MediaFile] entity
9
+ def admin_media_file_link(entity)
10
+ link_to(entity.name, admin_media_file_path(entity.id))
11
+ end
12
+
13
+ # @param [MediaFolder|MediaFile] entity
14
+ def media_snapshot_preview(entity)
15
+ versions = "#{entity.snapshot.preview_2x.url} 2x"
16
+ image_tag(entity.snapshot.preview.url, alt: entity.name, srcset: versions)
17
+ end
18
+
19
+ # @param [MediaFile] entity
20
+ def media_file_medium(entity)
21
+ return '' if entity.file.blank?
22
+
23
+ versions = "#{entity.file.medium_2x.url} 2x"
24
+ image_tag(entity.file.medium.url, alt: entity.description, srcset: versions)
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ class FeedbackMailer < ApplicationMailer
2
+ # @param [Integer] id
3
+ def new_feedback_request(id)
4
+ @entity = FeedbackRequest.find_by(id: id)
5
+
6
+ receiver = StoredValue.receive('feedback_receiver')
7
+
8
+ mail to: receiver unless @entity.nil? || receiver.nil?
9
+ end
10
+ end
@@ -14,7 +14,7 @@ class EditablePage < ApplicationRecord
14
14
  validates_length_of :title, maximum: META_LIMIT
15
15
  validates_length_of :keywords, maximum: META_LIMIT
16
16
  validates_length_of :description, maximum: META_LIMIT
17
- validates_length_of :body, maximum: BODY_LIMIT
17
+ # validates_length_of :body, maximum: BODY_LIMIT
18
18
 
19
19
  def self.page_for_administration
20
20
  ordered_by_name
@@ -0,0 +1,31 @@
1
+ class FeedbackRequest < ApplicationRecord
2
+ include Toggleable
3
+
4
+ NAME_LIMIT = 100
5
+ EMAIL_LIMIT = 250
6
+ PHONE_LIMIT = 30
7
+ COMMENT_LIMIT = 5000
8
+ PER_PAGE = 20
9
+
10
+ toggleable :processed
11
+
12
+ belongs_to :agent, optional: true
13
+
14
+ validates_length_of :name, maximum: NAME_LIMIT
15
+ validates_length_of :phone, maximum: PHONE_LIMIT
16
+ validates_length_of :comment, maximum: COMMENT_LIMIT
17
+ validates_length_of :email, maximum: EMAIL_LIMIT
18
+ validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z0-9][-a-z0-9]+)\z/i, allow_blank: true
19
+
20
+ scope :recent, -> { order('id desc') }
21
+ scope :unprocessed, -> { where(processed: false) }
22
+
23
+ # @param [Integer] page
24
+ def self.page_for_administration(page = 1)
25
+ recent.page(page).per(PER_PAGE)
26
+ end
27
+
28
+ def self.creation_parameters
29
+ %i(name email phone comment)
30
+ end
31
+ end