biovision-base 0.7.170709 → 0.8.170916

Sign up to get free protection for your applications and to get access to all the features.
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