biovision-base 0.8.170916 → 0.8.171029

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/biovision/base/placeholders/image.svg +3 -18
  3. data/app/assets/javascripts/biovision/base/biovision.js +228 -124
  4. data/app/assets/stylesheets/biovision/base/admin.scss +8 -7
  5. data/app/assets/stylesheets/biovision/base/biovision.scss +1 -1
  6. data/app/assets/stylesheets/biovision/base/default.scss +6 -3
  7. data/app/assets/stylesheets/biovision/base/default_admin.scss +30 -0
  8. data/app/assets/stylesheets/biovision/base/layout.scss +22 -14
  9. data/app/assets/stylesheets/biovision/base/message-box.scss +8 -1
  10. data/app/controllers/admin/regions_controller.rb +0 -9
  11. data/app/controllers/admin/users_controller.rb +2 -2
  12. data/app/controllers/authentication_controller.rb +4 -1
  13. data/app/controllers/concerns/toggleable_entity.rb +12 -3
  14. data/app/controllers/regions_controller.rb +1 -1
  15. data/app/helpers/biovision_users_helper.rb +18 -8
  16. data/app/models/region.rb +6 -1
  17. data/app/models/user.rb +3 -3
  18. data/app/models/user_profile.rb +8 -0
  19. data/app/services/canonizer.rb +9 -8
  20. data/app/views/admin/metrics/show.html.erb +20 -12
  21. data/app/views/admin/privileges/entity/_groups.html.erb +12 -10
  22. data/app/views/admin/regions/entity/_in_list.html.erb +1 -1
  23. data/app/views/admin/regions/show.html.erb +1 -1
  24. data/app/views/admin/users/_filter.html.erb +2 -14
  25. data/app/views/admin/users/index.html.erb +1 -1
  26. data/app/views/admin/users/privileges.html.erb +53 -38
  27. data/app/views/agents/_filter.html.erb +28 -28
  28. data/app/views/authentication/new.jbuilder +6 -0
  29. data/app/views/editable_pages/_editable_page.html.erb +6 -0
  30. data/app/views/editable_pages/form/_ckeditor.html.erb +3 -3
  31. data/app/views/layouts/admin.html.erb +1 -1
  32. data/app/views/my/recoveries/show.html.erb +1 -1
  33. data/app/views/shared/_breadcrumbs.html.erb +6 -0
  34. data/app/views/shared/_list_of_errors.html.erb +5 -9
  35. data/config/locales/common-ru.yml +22 -22
  36. data/config/locales/users-ru.yml +9 -0
  37. data/config/routes.rb +1 -1
  38. data/db/migrate/20170301000001_create_metrics.rb +1 -1
  39. data/db/migrate/20170301000002_create_metric_values.rb +1 -1
  40. data/db/migrate/20170301000101_create_browsers.rb +1 -1
  41. data/db/migrate/20170301000102_create_agents.rb +1 -1
  42. data/db/migrate/20170301000201_create_regions.rb +4 -1
  43. data/db/migrate/20170302000001_create_users.rb +2 -1
  44. data/db/migrate/20170302000003_create_tokens.rb +1 -1
  45. data/db/migrate/20170302000005_create_codes.rb +1 -1
  46. data/db/migrate/20170302000101_create_privileges.rb +1 -1
  47. data/db/migrate/20170302000102_create_user_privileges.rb +1 -1
  48. data/db/migrate/20170302000103_create_privilege_groups.rb +1 -1
  49. data/db/migrate/20170302000104_create_privilege_group_privileges.rb +1 -1
  50. data/db/migrate/20170320000000_create_editable_pages.rb +4 -1
  51. data/db/migrate/20170425000001_create_foreign_sites.rb +1 -1
  52. data/db/migrate/20170425000002_create_foreign_users.rb +1 -1
  53. data/db/migrate/20171025222222_add_new_fields_171026.rb +29 -0
  54. data/lib/biovision/base/engine.rb +5 -0
  55. data/lib/biovision/base/version.rb +1 -1
  56. metadata +8 -4
@@ -1,13 +1,13 @@
1
1
  html {
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%);
3
- background-blend-mode: screen;
4
2
  background-attachment: fixed;
5
- font: 400 10px $font-family-main;
3
+ background-blend-mode: screen;
4
+ background-image: linear-gradient(to bottom, #dedfe3 2%, #aeb3b9 95%), radial-gradient(farthest-corner at 33% 100%, rgba(255, 255, 255, .5) 0%, rgba(0, 0, 0, .5) 100%);
5
+ font: 300 10px $font-family-main;
6
6
  margin: 0;
7
7
  padding: 0;
8
- -webkit-text-size-adjust: none;
9
8
  -moz-text-size-adjust: none;
10
9
  -ms-text-size-adjust: none;
10
+ -webkit-text-size-adjust: none;
11
11
  }
12
12
 
13
13
  * {
@@ -17,6 +17,7 @@ html {
17
17
  a:link,
18
18
  a:visited {
19
19
  color: $link-color;
20
+ font-weight: 400;
20
21
  text-decoration: none;
21
22
  }
22
23
 
@@ -29,6 +30,7 @@ img {
29
30
  }
30
31
 
31
32
  h1, h2, h3, h4, h5, h6 {
33
+ color: $text-color-heading;
32
34
  font-family: $font-family-heading;
33
35
  font-weight: 500;
34
36
  margin: 0;
@@ -121,6 +123,7 @@ article {
121
123
 
122
124
  &.preview {
123
125
  img {
126
+ box-shadow: $block-shadow;
124
127
  max-width: 32rem;
125
128
  }
126
129
  }
@@ -132,7 +135,7 @@ article {
132
135
 
133
136
  dt {
134
137
  border-top: $border-secondary;
135
- font: 500 $font-size-increased $font-family-main;
138
+ font: 400 $font-size-increased $font-family-main;
136
139
  margin: .8rem 0 0 0;
137
140
  padding: .4rem 0;
138
141
  }
@@ -181,8 +184,6 @@ article {
181
184
  }
182
185
 
183
186
  nav.admin-breadcrumbs {
184
- background: linear-gradient(to right, rgba(192, 230, 192, .125), rgba(255, 255, 255, 0));
185
- border-left: .2rem solid rgba(80, 230, 80, .5);
186
187
  margin-bottom: .8rem;
187
188
  padding: .4rem;
188
189
 
@@ -337,7 +337,7 @@ ul.actions {
337
337
  background: $row-background-odd;
338
338
  list-style: none;
339
339
  margin: 0;
340
- padding: .4rem;
340
+ padding: .8rem;
341
341
  position: relative;
342
342
 
343
343
  &:nth-last-of-type(even) {
@@ -17,11 +17,14 @@ $text-color-heading: #000 !default;
17
17
  $text-color-primary: rgb(28, 28, 28) !default;
18
18
  $text-color-secondary: #777 !default;
19
19
 
20
- $block-shadow: 0 0 .2rem .2rem rgba(0, 0, 0, .25) !default;
20
+ $block-shadow: .2rem .2rem .4rem .2rem rgba(0, 0, 0, .125) !default;
21
21
 
22
- $border-primary: .1rem solid rgb(192, 192, 192) !default;
23
- $border-secondary: .1rem solid rgb(230, 230, 230) !default;
22
+ $border-color-primary: rgb(192, 192, 192) !default;
23
+ $border-color-secondary: rgb(230, 230, 230) !default;
24
+ $border-primary: .1rem solid $border-color-primary !default;
25
+ $border-secondary: .1rem solid $border-color-secondary !default;
24
26
 
27
+ $background-body: #f4f4f4 linear-gradient(to top, #f4f4f4 0%, #dfdedc 100%) no-repeat center / cover !default;
25
28
  $background-header: #fff !default;
26
29
  $background-main: #fff !default;
27
30
  $background-footer: #fff !default;
@@ -1,3 +1,33 @@
1
+ $font-family-heading: "Cormorant Garamond", serif !default;
2
+ $font-family-main: "Roboto", sans-serif !default;
3
+
4
+ $font-size-large: 2rem !default;
5
+ $font-size-increased: 1.6rem !default;
6
+ $font-size-normal: 1.4rem !default;
7
+ $font-size-decreased: 1.2rem !default;
8
+ $font-size-small: 1rem !default;
9
+
10
+ $content-width: 100rem !default;
11
+ $content-width-min: 32rem !default;
12
+
13
+ $row-background-even: hsl(0, 0%, 95%) !default;
14
+ $row-background-odd: hsl(0, 0%, 98%) !default;
15
+
16
+ $text-color-heading: #000 !default;
17
+ $text-color-primary: rgb(28, 28, 28) !default;
18
+ $text-color-secondary: #777 !default;
19
+
20
+ $block-shadow: .2rem .2rem .4rem .2rem rgba(0, 0, 0, .125) !default;
21
+
22
+ $border-color-primary: rgb(192, 192, 192) !default;
23
+ $border-color-secondary: rgb(230, 230, 230) !default;
24
+ $border-primary: .1rem solid $border-color-primary !default;
25
+ $border-secondary: .1rem solid $border-color-secondary !default;
26
+
27
+ $link-color: rgb(20, 127, 255) !default;
28
+ $link-color-visited: rgb(20, 77, 250) !default;
29
+ $link-color-hover: rgb(255, 77, 20) !default;
30
+
1
31
  @import "biovision/base/toggleable";
2
32
  @import "biovision/base/buttons";
3
33
  @import "biovision/base/biovision";
@@ -1,3 +1,7 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
1
5
  html {
2
6
  font: 10px $font-family-main;
3
7
  margin: 0;
@@ -7,10 +11,6 @@ html {
7
11
  -ms-text-size-adjust: none;
8
12
  }
9
13
 
10
- * {
11
- box-sizing: border-box;
12
- }
13
-
14
14
  h1, h2, h3, h4, h6, h6 {
15
15
  color: $text-color-heading;
16
16
  font-family: $font-family-heading;
@@ -48,6 +48,7 @@ img {
48
48
  }
49
49
 
50
50
  body {
51
+ background: $background-body;
51
52
  color: $text-color-primary;
52
53
  display: flex;
53
54
  flex-direction: column;
@@ -60,10 +61,14 @@ body {
60
61
 
61
62
  > footer,
62
63
  > header {
64
+ padding: .4rem 0;
65
+
63
66
  > div {
67
+ display: flex;
68
+ flex-wrap: wrap;
64
69
  margin: 0 auto;
65
- padding: .4rem;
66
70
  max-width: $content-width;
71
+ padding: .4rem;
67
72
 
68
73
  .authentication {
69
74
  > div {
@@ -95,8 +100,6 @@ body {
95
100
 
96
101
  > div {
97
102
  align-items: center;
98
- display: flex;
99
- flex-wrap: wrap;
100
103
 
101
104
  .logo {
102
105
  margin-right: auto;
@@ -110,18 +113,22 @@ body {
110
113
  margin: auto 0 0 0;
111
114
 
112
115
  > div {
113
- align-items: center;
114
116
  color: $text-color-secondary;
115
- display: flex;
116
- flex-wrap: wrap;
117
117
  font-size: $font-size-decreased;
118
118
 
119
- .copyright {
120
- margin-right: auto;
121
- }
122
-
123
119
  nav {
124
120
  margin: 0 auto;
121
+
122
+ ul {
123
+ margin: 0;
124
+ padding: 0;
125
+
126
+ li {
127
+ list-style: none;
128
+ margin: 0;
129
+ padding: 0;
130
+ }
131
+ }
125
132
  }
126
133
  }
127
134
  }
@@ -133,6 +140,7 @@ body {
133
140
  margin: 0 auto;
134
141
  max-width: $content-width;
135
142
  padding: .8rem;
143
+ width: 100%;
136
144
  }
137
145
 
138
146
  form {
@@ -32,7 +32,6 @@ section.errors {
32
32
  padding: 1.6rem;
33
33
 
34
34
  > h2 {
35
- background: #fee image_url('biovision/base/icons/alert.svg') no-repeat center left 1.6rem / 1.6rem 1.6rem;
36
35
  color: #400;
37
36
  font-size: $font-size-large;
38
37
  padding: 1.6rem 1.6rem 1.6rem 4.8rem;
@@ -43,6 +42,14 @@ section.errors {
43
42
  }
44
43
  }
45
44
 
45
+ ol.errors {
46
+ background: #fee image_url('biovision/base/icons/alert.svg') no-repeat top 1rem left 1rem / 1.6rem 1.6rem;
47
+ box-shadow: .2rem .2rem .2rem 0 hsla(0, 75%, 50%, .5);
48
+ color: hsl(0, 75%, 50%);
49
+ margin: 1rem 1.6rem;
50
+ padding: 1rem 1rem 1rem 5.4rem;
51
+ }
52
+
46
53
  .field_with_errors {
47
54
  background: #fee;
48
55
  display: inline-block;
@@ -3,7 +3,6 @@ class Admin::RegionsController < AdminController
3
3
  include LockableEntity
4
4
 
5
5
  before_action :set_entity, except: [:index]
6
- before_action :check_entity_lock, only: [:toggle]
7
6
 
8
7
  # get /admin/regions
9
8
  def index
@@ -20,18 +19,10 @@ class Admin::RegionsController < AdminController
20
19
  require_privilege_group :region_managers
21
20
  end
22
21
 
23
- def restrict_editing
24
- unless @entity.editable_by?(current_user)
25
- handle_http_401('Current user cannot edit region')
26
- end
27
- end
28
-
29
22
  def set_entity
30
23
  @entity = Region.find_by(id: params[:id])
31
24
  if @entity.nil?
32
25
  handle_http_404("Cannot find region #{params[:id]}")
33
- else
34
- restrict_editing
35
26
  end
36
27
  end
37
28
  end
@@ -7,8 +7,8 @@ class Admin::UsersController < AdminController
7
7
 
8
8
  # get /admin/users
9
9
  def index
10
- @filter = params[:filter] || Hash.new
11
- @collection = User.page_for_administration current_page, @filter
10
+ @search = param_from_request(:q)
11
+ @collection = User.page_for_administration current_page, @search
12
12
  end
13
13
 
14
14
  # get /admin/users/:id
@@ -66,6 +66,9 @@ class AuthenticationController < ApplicationController
66
66
  return_path = my_path unless return_path[0] == '/'
67
67
  cookies.delete 'return_path', domain: :all
68
68
 
69
- redirect_to return_path
69
+ respond_to do |format|
70
+ format.json { render(json: { data: { url: return_path } }) }
71
+ format.html { redirect_to(return_path) }
72
+ end
70
73
  end
71
74
  end
@@ -3,7 +3,9 @@ module ToggleableEntity
3
3
 
4
4
  # Toggle entity flag when allowed
5
5
  def toggle
6
- if allow_toggle?
6
+ if entity_is_locked?
7
+ render json: { errors: { locked: true } }, status: :forbidden
8
+ elsif entity_is_editable?
7
9
  render json: { data: @entity.toggle_parameter(params[:parameter].to_s) }
8
10
  else
9
11
  head :unauthorized
@@ -12,12 +14,19 @@ module ToggleableEntity
12
14
 
13
15
  private
14
16
 
15
- # If entity responds to #editable_by?, it should be editable to be toggled
16
- def allow_toggle?
17
+ def entity_is_editable?
17
18
  if @entity.respond_to?(:editable_by?)
18
19
  @entity.editable_by?(current_user)
19
20
  else
20
21
  true
21
22
  end
22
23
  end
24
+
25
+ def entity_is_locked?
26
+ if @entity.respond_to?(:locked?)
27
+ @entity.locked?
28
+ else
29
+ false
30
+ end
31
+ end
23
32
  end
@@ -49,7 +49,7 @@ class RegionsController < AdminController
49
49
  end
50
50
 
51
51
  def restrict_editing
52
- unless @entity.editable_by?(current_user)
52
+ if @entity.locked? || !@entity.editable_by?(current_user)
53
53
  redirect_to admin_region_path(@entity.id), alert: t('regions.edit.forbidden')
54
54
  end
55
55
  end
@@ -2,7 +2,7 @@ module BiovisionUsersHelper
2
2
  def genders_for_select
3
3
  genders = [[t(:not_selected), '']]
4
4
  prefix = 'activerecord.attributes.user_profile.genders.'
5
- genders + UserProfile.genders.keys.to_a.map { |o| [I18n.t("#{prefix}#{o}"), o] }
5
+ genders + UserProfile.genders.keys.to_a.map { |o| [t("#{prefix}#{o}"), o] }
6
6
  end
7
7
 
8
8
  # @param [User] entity
@@ -26,23 +26,33 @@ module BiovisionUsersHelper
26
26
  link_to entity.name, admin_token_path(entity.id)
27
27
  end
28
28
 
29
- # @param [User] user
30
- def profile_avatar(user)
31
- if user.is_a?(User) && !user.image.blank? && !user.deleted?
32
- image_tag user.image.profile.url
29
+ # @param [User] entity
30
+ def profile_avatar(entity)
31
+ if entity.is_a?(User) && !entity.image.blank? && !entity.deleted?
32
+ user_image_profile(entity)
33
33
  else
34
- image_tag 'biovision/base/placeholders/user.svg'
34
+ image_tag('biovision/base/placeholders/user.svg')
35
35
  end
36
36
  end
37
37
 
38
38
  # @param [User] entity
39
39
  def user_image_preview(entity)
40
- return image_tag('biovision/base/placeholders/user.svg') if entity.image.blank?
41
-
42
40
  versions = "#{entity.image.preview_2x.url} 2x"
43
41
  image_tag(entity.image.preview.url, alt: entity.profile_name, srcset: versions)
44
42
  end
45
43
 
44
+ # @param [User] entity
45
+ def user_image_profile(entity)
46
+ versions = "#{entity.image.profile_2x.url} 2x"
47
+ image_tag(entity.image.profile.url, alt: entity.profile_name, srcset: versions)
48
+ end
49
+
50
+ # @param [User] entity
51
+ def user_image_big(entity)
52
+ versions = "#{entity.image.big_2x.url} 2x"
53
+ image_tag(entity.image.big.url, alt: entity.profile_name, srcset: versions)
54
+ end
55
+
46
56
  # @param [ForeignSite] foreign_site
47
57
  def foreign_login_link(foreign_site)
48
58
  image = "biovision/base/icons/foreign/#{foreign_site.slug}.svg"
data/app/models/region.rb CHANGED
@@ -47,7 +47,7 @@ class Region < ApplicationRecord
47
47
  def editable_by?(user)
48
48
  administrator = UserPrivilege.user_has_privilege?(user, :administrator)
49
49
  manager = UserPrivilege.user_has_privilege?(user, :region_manager, self)
50
- (administrator || manager) && !locked?
50
+ administrator || manager
51
51
  end
52
52
 
53
53
  def parents
@@ -78,6 +78,11 @@ class Region < ApplicationRecord
78
78
  "#{parents.map(&:name).join('/')}/#{name}"
79
79
  end
80
80
 
81
+ def branch_name
82
+ return short_name if parents.blank?
83
+ "#{parents.map(&:short_name).join('/')}/#{short_name}"
84
+ end
85
+
81
86
  def cache_parents!
82
87
  return if parent.nil?
83
88
  self.parents_cache = "#{parent.parents_cache},#{parent_id}".gsub(/\A,/, '')
data/app/models/user.rb CHANGED
@@ -55,9 +55,9 @@ class User < ApplicationRecord
55
55
  scope :filtered, ->(f) { email_like(f[:email]).screen_name_like(f[:screen_name]) }
56
56
 
57
57
  # @param [Integer] page
58
- # @param [Hash] filter
59
- def self.page_for_administration(page, filter = {})
60
- bots(filter[:bots]).filtered(filter).order('id desc').page(page).per(PER_PAGE)
58
+ # @param [String] search_query
59
+ def self.page_for_administration(page, search_query)
60
+ search(search_query).order('id desc').page(page).per(PER_PAGE)
61
61
  end
62
62
 
63
63
  def self.profile_parameters
@@ -18,4 +18,12 @@ class UserProfile < ApplicationRecord
18
18
  def search_string
19
19
  "#{name} #{surname}"
20
20
  end
21
+
22
+ def age
23
+ now = Time.now
24
+ bd = birthday || now
25
+ result = now.year - bd.year
26
+ result = result - 1 if (bd.month > now.month || (bd.month >= now.month && bd.day > now.day))
27
+ result
28
+ end
21
29
  end
@@ -1,29 +1,30 @@
1
1
  class Canonizer
2
2
  TRANSLITERATION_MAP = {
3
- 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo',
4
- 'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm',
5
- 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u',
6
- 'ф' => 'f', 'х' => 'kh', 'ц' => 'c', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shh', 'ъ' => '',
7
- 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', 'я' => 'ya',
3
+ 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e',
4
+ 'ё' => 'yo', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k',
5
+ 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r',
6
+ 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'kh', 'ц' => 'c',
7
+ 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shh', 'ъ' => '', 'ы' => 'y', 'ь' => '',
8
+ 'э' => 'e', 'ю' => 'yu', 'я' => 'ya',
8
9
  }
9
10
 
10
11
  # @param [String] text
11
12
  def self.transliterate(text)
12
- result = text.mb_chars.downcase.to_s
13
+ result = text.downcase
13
14
  TRANSLITERATION_MAP.each { |r, e| result.gsub!(r, e) }
14
15
  result.downcase.gsub(/[^-a-z0-9_]/, '-').gsub(/^[-_]*([-a-z0-9_]*[a-z0-9]+)[-_]*$/, '\1').gsub(/--+/, '-')
15
16
  end
16
17
 
17
18
  # @param [String] input
18
19
  def self.canonize(input)
19
- lowered = input.mb_chars.downcase.to_s.strip
20
+ lowered = input.downcase.strip
20
21
  canonized = lowered.gsub(/[^a-zа-я0-9ё]/, '')
21
22
  canonized.empty? ? lowered : canonized
22
23
  end
23
24
 
24
25
  # @param [String] input
25
26
  def self.urlize(input)
26
- lowered = input.mb_chars.downcase.to_s.squish
27
+ lowered = input.downcase.squish
27
28
  lowered.gsub(/[^a-zа-я0-9ё]/, '-').gsub(/-\z/, '')
28
29
  end
29
30
  end