biovision-base 0.7.170709 → 0.8.170916

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -13
  3. data/app/assets/javascripts/biovision/base/biovision.js +128 -45
  4. data/app/assets/stylesheets/biovision/base/admin.scss +64 -104
  5. data/app/assets/stylesheets/biovision/base/biovision.scss +2 -11
  6. data/app/assets/stylesheets/biovision/base/buttons.scss +156 -52
  7. data/app/assets/stylesheets/biovision/base/default.scss +2 -37
  8. data/app/assets/stylesheets/biovision/base/default_admin.scss +1 -0
  9. data/app/assets/stylesheets/biovision/base/default_application.scss +1 -0
  10. data/app/assets/stylesheets/biovision/base/layout.scss +64 -2
  11. data/app/assets/stylesheets/biovision/base/toggleable.scss +71 -0
  12. data/app/assets/stylesheets/biovision/base/users.scss +77 -13
  13. data/app/controllers/about_controller.rb +15 -0
  14. data/app/controllers/admin/stored_values_controller.rb +25 -0
  15. data/app/controllers/concerns/toggleable_entity.rb +17 -1
  16. data/app/controllers/index_controller.rb +1 -0
  17. data/app/controllers/my/profiles_controller.rb +6 -1
  18. data/app/controllers/stored_values_controller.rb +56 -0
  19. data/app/controllers/users_controller.rb +6 -0
  20. data/app/helpers/biovision_users_helper.rb +3 -3
  21. data/app/helpers/stored_values_helper.rb +6 -0
  22. data/app/models/central_region.rb +4 -0
  23. data/app/models/region.rb +5 -0
  24. data/app/models/stored_value.rb +28 -0
  25. data/app/models/user.rb +33 -13
  26. data/app/models/user_profile.rb +21 -0
  27. data/app/services/user_manager.rb +32 -0
  28. data/app/views/about/editable.html.erb +11 -0
  29. data/app/views/admin/index/index.html.erb +1 -0
  30. data/app/views/admin/login_attempts/entity/_in_list.html.erb +1 -1
  31. data/app/views/admin/stored_values/_nav_item.html.erb +6 -0
  32. data/app/views/admin/stored_values/entity/_in_list.html.erb +15 -0
  33. data/app/views/admin/stored_values/index.html.erb +14 -0
  34. data/app/views/admin/stored_values/show.html.erb +37 -0
  35. data/app/views/admin/users/_filter.html.erb +2 -0
  36. data/app/views/admin/users/codes.html.erb +1 -1
  37. data/app/views/admin/users/search.jbuilder +4 -2
  38. data/app/views/admin/users/show.html.erb +11 -11
  39. data/app/views/authentication/_form.html.erb +2 -2
  40. data/app/views/authentication/new.html.erb +1 -1
  41. data/app/views/editable_pages/_editable_page.html.erb +8 -0
  42. data/app/views/index/index.html.erb +7 -3
  43. data/app/views/layouts/application/_footer.html.erb +9 -0
  44. data/app/views/my/confirmations/show.html.erb +21 -15
  45. data/app/views/my/login_attempts/index.html.erb +1 -1
  46. data/app/views/my/profiles/edit/_form.html.erb +112 -65
  47. data/app/views/my/profiles/edit.html.erb +5 -4
  48. data/app/views/my/profiles/new/_form.html.erb +5 -5
  49. data/app/views/my/recoveries/show.html.erb +28 -17
  50. data/app/views/my/tokens/index.html.erb +1 -1
  51. data/app/views/profiles/_profile.html.erb +34 -40
  52. data/app/views/shared/admin/_list_with_priority.html.erb +11 -0
  53. data/app/views/stored_values/_form.html.erb +33 -0
  54. data/app/views/stored_values/edit.html.erb +17 -0
  55. data/app/views/stored_values/new.html.erb +15 -0
  56. data/app/views/users/_form.html.erb +42 -31
  57. data/app/views/users/new.html.erb +1 -1
  58. data/config/locales/common-ru.yml +10 -0
  59. data/config/locales/editable-pages-ru.yml +34 -2
  60. data/config/locales/users-ru.yml +19 -12
  61. data/config/routes.rb +7 -0
  62. data/db/migrate/20170302000001_create_users.rb +1 -5
  63. data/db/migrate/20170302000002_create_user_profiles.rb +21 -0
  64. data/db/migrate/{20170302000002_create_tokens.rb → 20170302000003_create_tokens.rb} +0 -0
  65. data/db/migrate/{20170302000003_create_code_types.rb → 20170302000004_create_code_types.rb} +0 -0
  66. data/db/migrate/{20170302000004_create_codes.rb → 20170302000005_create_codes.rb} +0 -0
  67. data/db/migrate/20170320000000_create_editable_pages.rb +4 -0
  68. data/db/migrate/20170823000001_create_stored_values.rb +19 -0
  69. data/lib/biovision/base/engine.rb +1 -0
  70. data/lib/biovision/base/version.rb +1 -1
  71. data/lib/tasks/regions.rake +37 -2
  72. metadata +32 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9442305845e4868b36e06500f26e8bdd681de387
4
- data.tar.gz: dc47d68e9fe96816f24508f26acec9fcdcaaa8e7
3
+ metadata.gz: 5cfc144ad5307b7e9d5d93dcbbb6f7d14eab5bb0
4
+ data.tar.gz: 386e0f6f547aaef0befb3ad99f887f87dd533263
5
5
  SHA512:
6
- metadata.gz: 0a512829d7c58e3e3b53dd88ad0372a2966c799e8317b4285f42ac6eb065262c141693447bbb57cce3879276c7cfbd9d5dd5232b69955459a4c0fcf77fa8257e
7
- data.tar.gz: 6ae25499bc961b8818d6bf5968619dcbc421f45095f51468bc957e1ae5a18e041a635a57c6c32c1518a2574957349728bdf5ba038f592b07d68d3f41c1ddb310
6
+ metadata.gz: 1691ce1bf90cc9c6c36f0d6b5777ee955f80821de8bd983fb53c344300e4df20e26da20f0f997369bb6000f1ecf2833f5911babd54f594b01d516767181522af
7
+ data.tar.gz: 07f2394d5f168f067cb749c10b16d371971dcac15753facc76246d4d4657ffd881f21429dd30160b4805b089de7bb4abf1ca551bc01805a90549bb30a334c38d
data/README.md CHANGED
@@ -1,22 +1,11 @@
1
1
  Biovision::Base
2
2
  ===============
3
3
 
4
- Базовый функционал: пользователи, метрики, браузеры, АП, привилегии.
4
+ Базовый функционал: пользователи, метрики, привилегии, редактируемые страницы.
5
5
 
6
6
  Используйте на свой страх и риск без каких-либо гарантий работоспособности.
7
7
 
8
- ToDo
9
- -----
10
-
11
- * Тесты для запирания/отпирания в контроллерах
12
- * Тесты для смены порядка сортировки в контроллерах
13
- * Подгрузка метрик через AJAX
14
- * Несколько метрик в одном графике
15
- * Настройка цветов в графиках
16
- * Анализ журнала доступа nginx
17
- * Работа с подсетями (чёрные списки IP и так далее)
18
-
19
- Описание необходимых и рекомендуемых действий находится в `biovision/snippets`
8
+ Описание необходимых и рекомендуемых действий находится в `setup.md`
20
9
 
21
10
  Очистка устаревших сессий
22
11
  -------------------------
@@ -1,13 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var Biovision = {
3
+ let Biovision = {
4
4
  storage: {
5
5
  available: function (type) {
6
6
  try {
7
- var storage = window[type],
8
- x = '__storage_test__';
9
- storage.setItem(x, x);
10
- storage.removeItem(x);
7
+ const x = '__storage_test__';
8
+
9
+ window[type].setItem(x, x);
10
+ window[type].removeItem(x);
11
+
11
12
  return true;
12
13
  }
13
14
  catch (e) {
@@ -58,32 +59,61 @@ var Biovision = {
58
59
  Biovision.storage.remove('localStorage', key);
59
60
  }
60
61
  }
61
- }
62
- };
62
+ },
63
+ preview_file: function (input) {
64
+ const target_image = input.getAttribute('data-image');
63
65
 
64
- $(function () {
65
- $(document).on('change', 'input[type=file]', function () {
66
- if ($(this).data('image')) {
67
- var target = $('#' + $(this).data('image')).find('img');
68
- var input = this;
66
+ if (target_image) {
67
+ const target = document.querySelector('#' + target_image + ' img');
69
68
 
70
- if (input.files && input.files[0]) {
71
- var reader = new FileReader();
69
+ if (target && input.files && input.files[0]) {
70
+ const reader = new FileReader();
72
71
 
73
- reader.onload = function (e) {
74
- target.attr('src', e.target.result);
72
+ reader.onload = function (event) {
73
+ target.setAttribute('src', event.target.result);
75
74
  };
76
75
 
77
76
  reader.readAsDataURL(input.files[0]);
78
77
  }
79
78
  }
79
+ },
80
+ new_ajax_request: function(method, url, on_load, on_error) {
81
+ const request = new XMLHttpRequest();
82
+
83
+ request.addEventListener('load', on_load);
84
+ request.addEventListener('error', on_error || Biovision.handle_ajax_failure);
85
+ request.open(method, url);
86
+ request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
87
+ request.setRequestHeader('X-CSRF-Token', Biovision.csrf_token);
88
+
89
+ return request;
90
+ },
91
+ handle_ajax_failure: function(response) {
92
+ if (response.hasOwnProperty('responseJSON')) {
93
+ console.log(response['responseJSON']);
94
+ } else {
95
+ console.log(response);
96
+ }
97
+ }
98
+ };
99
+
100
+ document.addEventListener('DOMContentLoaded', function () {
101
+ Biovision.csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
102
+
103
+ // Предварительный просмотр картинки при выборе файла
104
+ document.addEventListener('change', function (event) {
105
+ const input = event.target;
106
+
107
+ if (input.matches('input[type=file]')) {
108
+ Biovision.preview_file(input);
109
+ }
80
110
  });
81
111
 
82
112
  $(document).on('click', 'div.toggleable > span', function () {
83
113
  if (!$(this).hasClass('switch')) {
84
- var $flag = $(this);
85
- var url = $(this).parent().data('url');
86
- var parameter = $(this).data('flag');
114
+ let $flag = $(this);
115
+ let url = $(this).parent().data('url');
116
+ let parameter = $(this).data('flag');
87
117
 
88
118
  $.post({
89
119
  url: url,
@@ -118,16 +148,16 @@ $(function () {
118
148
  });
119
149
 
120
150
  $(document).on('click', 'li.lock > a', function () {
121
- var $container = $(this).closest('li');
122
- var $edit = $container.parent().find('.lockable');
123
- var url = $container.data('url');
151
+ let $container = $(this).closest('li');
152
+ let $edit = $container.parent().find('.lockable');
153
+ let url = $container.data('url');
124
154
 
125
155
  if (url.length > 1) {
126
156
  $.ajax(url, {
127
157
  method: $(this).hasClass('lock') ? 'put' : 'delete',
128
158
  success: function (response) {
129
159
  if (response.hasOwnProperty('data') && response['data'].hasOwnProperty('locked')) {
130
- var locked = response['data']['locked'];
160
+ let locked = response['data']['locked'];
131
161
 
132
162
  locked ? $edit.addClass('hidden') : $edit.removeClass('hidden');
133
163
 
@@ -147,22 +177,22 @@ $(function () {
147
177
  });
148
178
 
149
179
  $(document).on('click', 'li.priority-changer > button', function () {
150
- var $li = $(this).closest('li[data-number]');
151
- var delta = parseInt($(this).data('delta'));
152
- var url = $(this).parent().data('url');
180
+ let $li = $(this).closest('li[data-number]');
181
+ let delta = parseInt(this.getAttribute('data-delta'));
182
+ let url = $(this).parent().data('url');
153
183
 
154
184
  if (parseInt($li.data('number')) + delta > 0) {
155
185
  $.post(url, {delta: delta}, function (response) {
156
186
  console.log(response);
157
187
  if (response.hasOwnProperty('data')) {
158
- var $container = $li.parent();
159
- var $list = $container.children('li');
188
+ let $container = $li.parent();
189
+ let $list = $container.children('li');
160
190
 
161
191
  if (response['data'].hasOwnProperty('priority')) {
162
192
  $li.data('number', response['data']['priority']);
163
193
  $li.attr('data-number', response['data']['priority']);
164
194
  } else {
165
- for (var entity_id in response['data']) {
195
+ for (let entity_id in response['data']) {
166
196
  if (response['data'].hasOwnProperty(entity_id)) {
167
197
  $li = $container.find('li[data-id=' + entity_id + ']');
168
198
  $li.data('number', response['data'][entity_id]);
@@ -171,8 +201,8 @@ $(function () {
171
201
  }
172
202
  }
173
203
  $list.sort(function (a, b) {
174
- var an = parseInt($(a).data('number'));
175
- var bn = parseInt($(b).data('number'));
204
+ let an = parseInt($(a).data('number'));
205
+ let bn = parseInt($(b).data('number'));
176
206
 
177
207
  if (an > bn) {
178
208
  return 1;
@@ -190,8 +220,8 @@ $(function () {
190
220
  });
191
221
 
192
222
  $('div[data-destroy-url] button.destroy').on('click', function () {
193
- var $button = $(this);
194
- var $container = $(this).closest('div[data-destroy-url]');
223
+ let $button = $(this);
224
+ let $container = $(this).closest('div[data-destroy-url]');
195
225
 
196
226
  $button.attr('disabled', true);
197
227
 
@@ -203,10 +233,10 @@ $(function () {
203
233
  }).fail(handle_ajax_failure);
204
234
  });
205
235
 
206
- $('.user-search button').on('click', function() {
207
- var $container = $(this).closest('.user-search');
208
- var $input = $container.find('input[type=search]');
209
- var $results = $container.find('.results');
236
+ $('.user-search button').on('click', function () {
237
+ let $container = $(this).closest('.user-search');
238
+ let $input = $container.find('input[type=search]');
239
+ let $results = $container.find('.results');
210
240
 
211
241
  $.get($container.data('url'), {q: $input.val()}, function (response) {
212
242
  if (response.hasOwnProperty('data')) {
@@ -215,18 +245,20 @@ $(function () {
215
245
  }).fail(handle_ajax_failure);
216
246
  });
217
247
 
218
- $(document).on('click', '.user-search .results li', function() {
219
- var $container = $(this).closest('.user-search');
220
- var $target = $('#' + $container.data('target'));
248
+ $(document).on('click', '.user-search .results li', function () {
249
+ let $container = $(this).closest('.user-search');
250
+ let $target = $('#' + $container.data('target'));
221
251
 
222
252
  $target.val($(this).data('id'));
223
253
  });
224
254
 
225
- $.ajaxSetup({
226
- headers: {
227
- 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
228
- }
229
- });
255
+ if (jQuery) {
256
+ jQuery.ajaxSetup({
257
+ headers: {
258
+ 'X-CSRF-Token': Biovision.csrf_token
259
+ }
260
+ });
261
+ }
230
262
  });
231
263
 
232
264
  function handle_ajax_failure(response) {
@@ -236,3 +268,54 @@ function handle_ajax_failure(response) {
236
268
  console.log(response);
237
269
  }
238
270
  }
271
+
272
+ /*
273
+ *************
274
+ * Polyfills *
275
+ *************
276
+ */
277
+
278
+ /**
279
+ * Element.closest()
280
+ *
281
+ * IE 9+
282
+ *
283
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
284
+ */
285
+ if (!Element.prototype.matches) {
286
+ Element.prototype.matches =
287
+ Element.prototype.msMatchesSelector ||
288
+ Element.prototype.webkitMatchesSelector;
289
+ }
290
+
291
+ if (!Element.prototype.closest) {
292
+ Element.prototype.closest = function (s) {
293
+ let el = this;
294
+ let ancestor = this;
295
+
296
+ if (!document.documentElement.contains(el)) {
297
+ return null;
298
+ }
299
+ do {
300
+ if (ancestor.matches(s)) {
301
+ return ancestor;
302
+ }
303
+ ancestor = ancestor.parentElement;
304
+ } while (ancestor !== null);
305
+
306
+ return null;
307
+ };
308
+ }
309
+
310
+ /**
311
+ * Element.matches()
312
+ *
313
+ * IE 9+
314
+ *
315
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
316
+ */
317
+ if (!Element.prototype.matches) {
318
+ Element.prototype.matches =
319
+ Element.prototype.msMatchesSelector ||
320
+ Element.prototype.webkitMatchesSelector;
321
+ }
@@ -1,14 +1,8 @@
1
- $toggleable-active: #34c749 !default;
2
- $toggleable-inactive: #fc605c !default;
3
- $toggleable-switch: #fdbc40 !default;
4
- $toggleable-unknown: #c0c0c0 !default;
5
- $toggleable-background: #fff !default;
6
-
7
1
  html {
8
- background-image: linear-gradient(#dedfe3 2%, #aeb3b9 95%), radial-gradient(33% 100%, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%);
2
+ background-image: linear-gradient(to bottom, #dedfe3 2%, #aeb3b9 95%), radial-gradient(33% 100%, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%);
9
3
  background-blend-mode: screen;
10
4
  background-attachment: fixed;
11
- font: 10px $font-family-main;
5
+ font: 400 10px $font-family-main;
12
6
  margin: 0;
13
7
  padding: 0;
14
8
  -webkit-text-size-adjust: none;
@@ -16,6 +10,10 @@ html {
16
10
  -ms-text-size-adjust: none;
17
11
  }
18
12
 
13
+ * {
14
+ box-sizing: border-box;
15
+ }
16
+
19
17
  a:link,
20
18
  a:visited {
21
19
  color: $link-color;
@@ -30,6 +28,22 @@ img {
30
28
  max-width: 100%;
31
29
  }
32
30
 
31
+ h1, h2, h3, h4, h5, h6 {
32
+ font-family: $font-family-heading;
33
+ font-weight: 500;
34
+ margin: 0;
35
+ }
36
+
37
+ h1 {
38
+ font-size: 3.6rem;
39
+ margin-bottom: .8rem;
40
+ }
41
+
42
+ h2 {
43
+ font-size: 3rem;
44
+ margin-bottom: .4rem;
45
+ }
46
+
33
47
  body {
34
48
  background: #fff;
35
49
  color: $text-color-primary;
@@ -67,7 +81,7 @@ body {
67
81
 
68
82
  a:link,
69
83
  a:visited {
70
- @include nav-button;
84
+ @include button-nav;
71
85
  }
72
86
  }
73
87
  }
@@ -96,59 +110,62 @@ body {
96
110
 
97
111
  #main {
98
112
  padding: 1rem;
113
+ width: 100%;
114
+ }
99
115
 
100
- article {
101
- position: relative;
116
+ article {
117
+ position: relative;
102
118
 
103
- figure {
104
- margin: 0;
119
+ figure {
120
+ margin: 0;
105
121
 
106
- &.preview {
107
- img {
108
- max-width: 32rem;
109
- }
122
+ &.preview {
123
+ img {
124
+ max-width: 32rem;
110
125
  }
111
126
  }
127
+ }
112
128
 
113
- dl {
114
- margin: 0 0 1.6rem 0;
115
- padding: 0;
129
+ dl {
130
+ margin: 0 0 1.6rem 0;
131
+ padding: 0;
116
132
 
117
- dt {
118
- border-top: .1rem solid #f0f0f0;
119
- margin: 1rem 0 0 0;
120
- padding: 0;
121
- }
133
+ dt {
134
+ border-top: $border-secondary;
135
+ font: 500 $font-size-increased $font-family-main;
136
+ margin: .8rem 0 0 0;
137
+ padding: .4rem 0;
138
+ }
122
139
 
123
- dd {
124
- margin: 0 0 0 .8rem;
125
- padding: 0;
140
+ dd {
141
+ margin: .2rem 0;
142
+ padding: 0;
126
143
 
127
- input,
128
- textarea {
129
- font-size: $font-size-normal;
130
- }
144
+ input,
145
+ textarea {
146
+ font-size: $font-size-normal;
147
+ }
131
148
 
132
- input:not([type=checkbox]):not([type=radio]):not([size]):not([max]),
133
- textarea {
134
- width: calc(100% - 1rem);
135
- }
149
+ input:not([type=checkbox]):not([type=radio]):not([size]):not([max]),
150
+ textarea {
151
+ width: 100%;
152
+ }
136
153
 
137
- input,
138
- textarea {
139
- max-width: calc(100% - 1rem);
140
- }
154
+ input,
155
+ textarea {
156
+ max-width: 100%;
141
157
  }
142
158
  }
143
159
 
144
- ul.flags {
145
- margin: 1.6rem 0;
160
+ ul {
161
+ margin: 0;
146
162
  padding: 0;
147
163
 
148
164
  > li {
149
165
  list-style: none;
150
166
  margin: 0;
151
167
  padding: 0;
168
+ position: relative;
152
169
 
153
170
  label {
154
171
  font-weight: normal;
@@ -156,6 +173,11 @@ body {
156
173
  }
157
174
  }
158
175
  }
176
+
177
+ > section {
178
+ border-top: .1rem solid $text-color-secondary;
179
+ padding: .8rem 0 0 0;
180
+ }
159
181
  }
160
182
 
161
183
  nav.admin-breadcrumbs {
@@ -171,68 +193,6 @@ nav.admin-breadcrumbs {
171
193
  }
172
194
  }
173
195
 
174
- .toggleable {
175
- font-size: $font-size-decreased;
176
- margin: .8rem;
177
-
178
- > span {
179
- background-color: $toggleable-background;
180
- border: .1rem solid;
181
- border-radius: .8rem;
182
- cursor: pointer;
183
- display: inline-block;
184
- line-height: #{$font-size-decreased * 2};
185
- margin: .4rem;
186
- padding: 0 .8rem 0 0;
187
-
188
- &::before {
189
- border-radius: .6rem 0 0 .6rem;
190
- display: inline-block;
191
- line-height: #{$font-size-decreased * 2};
192
- margin: 0 .4rem 0 0;
193
- text-align: center;
194
- width: 2.2rem;
195
- }
196
- }
197
-
198
- .active {
199
- border-color: $toggleable-active;
200
-
201
- &::before {
202
- background-color: $toggleable-active;
203
- content: '\2611';
204
- }
205
- }
206
-
207
- .inactive {
208
- border-color: $toggleable-inactive;
209
-
210
- &::before {
211
- background-color: $toggleable-inactive;
212
- content: '\2610';
213
- }
214
- }
215
-
216
- .switch {
217
- border-color: $toggleable-switch;
218
- cursor: not-allowed;
219
-
220
- &::before {
221
- background-color: $toggleable-switch;
222
- content: '\231B';
223
- }
224
- }
225
-
226
- .unknown {
227
- border-color: $toggleable-unknown;
228
-
229
- &::before {
230
- background-color: $toggleable-unknown;
231
- content: '\26A0';
232
- }
233
- }
234
- }
235
-
236
196
  .privileges {
237
197
  ul {
238
198
  border-left: $border-primary;
@@ -22,21 +22,12 @@ article.entity-page {
22
22
  margin: 0 1.6rem;
23
23
 
24
24
  a {
25
- @include nav-button;
25
+ @include button-nav;
26
26
  }
27
27
  }
28
28
  }
29
29
  }
30
30
 
31
- > section {
32
- border-top: .1rem solid $text-color-secondary;
33
- padding: .8rem 0 0 0;
34
-
35
- > h2 {
36
- font-size: $font-size-large;
37
- }
38
- }
39
-
40
31
  table {
41
32
  border-spacing: 0;
42
33
  margin: 1.6rem;
@@ -404,7 +395,7 @@ form {
404
395
  }
405
396
 
406
397
  button {
407
- @include action-button;
398
+ @include button-action;
408
399
  }
409
400
  }
410
401