diff --git a/app/assets/stylesheets/atoms/_a-dropdown.sass b/app/assets/stylesheets/atoms/_a-dropdown.sass
new file mode 100644
index 00000000000..c38fbe94133
--- /dev/null
+++ b/app/assets/stylesheets/atoms/_a-dropdown.sass
@@ -0,0 +1,10 @@
+.a-dropdown
+ overflow: hidden
+ background-color: $base
+ border: solid 1px $border-shade
+ box-shadow: rgba(black, .2) 0 0 .375rem
+ border-radius: .25rem
+
+.a-dropdown__item
+ &:not(:last-child)
+ border-bottom: solid 1px $border
diff --git a/app/assets/stylesheets/blocks/header/_.header-notification-icon.sass b/app/assets/stylesheets/blocks/header/_.header-notification-icon.sass
new file mode 100644
index 00000000000..baec03ddd12
--- /dev/null
+++ b/app/assets/stylesheets/blocks/header/_.header-notification-icon.sass
@@ -0,0 +1,50 @@
+.header-notification-icon
+ +text-block(1.25rem 1, center)
+ +media-breakpoint-down(sm)
+ +text-block(1.125rem 1)
+ .has-count &
+ color: $default-text
+
+.header-notification-count
+ background-color: $badge-color
+ +text-block(.625rem 1, center $reversal-text flex)
+ align-items: center
+ justify-content: center
+ border-radius: 1rem
+ position: absolute
+ +media-breakpoint-up(md)
+ +size(1.25rem .875rem)
+ +position(right .25rem, top .25rem)
+ +media-breakpoint-down(sm)
+ +size(1.125rem .75rem)
+ +position(right .125rem, top .125rem)
+
+.header-notifications-item__body
+ width: 100%
+ +media-breakpoint-up(md)
+ color: $default-text
+ +media-breakpoint-down(sm)
+ color: $reversal-text
+
+.header-notifications-item__user-icon
+ float: left
+ +size(2rem)
+ margin-right: .5rem
+ margin-bottom: .25rem
+
+.header-notifications-item__message
+ p
+ line-height: 1.45
+ margin-bottom: .375em
+ +media-breakpoint-up(md)
+ font-size: .8125rem
+ +media-breakpoint-down(sm)
+ font-size: .75rem
+
+.header-notifications-item__created-at
+ text-align: right
+ display: block
+ +media-breakpoint-up(md)
+ font-size: .75rem
+ +media-breakpoint-down(sm)
+ font-size: .625rem
diff --git a/app/assets/stylesheets/blocks/header/_header-drop-down.sass b/app/assets/stylesheets/blocks/header/_header-drop-down.sass
deleted file mode 100644
index 97c1d60b5d9..00000000000
--- a/app/assets/stylesheets/blocks/header/_header-drop-down.sass
+++ /dev/null
@@ -1,119 +0,0 @@
-.header-drop-down
- +position(absolute, left 50%, top 3.5rem)
- width: 16rem
- margin-left: -7rem
- display: none
- +media-breakpoint-down(sm)
- margin-left: -10rem
- top: 2.5rem
- .header-links__item.is-active &,
- .header-show-mobile-nav.is-active &
- display: block
-
-.header-drop-down__items
- border: solid 1px #ccc
- box-shadow: rgba(black, .1) 0 .0625rem .0625rem
- background-color: $base
- border-radius: .45rem
- +position(relative, 2)
- +media-breakpoint-down(sm)
- width: 14rem
- top: .5rem
- &::before
- content: ""
- +size(0)
- display: block
- border-style: solid
- border-width: 10px 10px
- border-color: transparent
- border-bottom-color: #ccc
- +position(absolute, left 50%, top -20px)
- margin-left: -10px
- +media-breakpoint-down(sm)
- left: 71%
- &::after
- content: ""
- +size(0)
- display: block
- border-style: solid
- border-width: 10px 10px
- border-color: transparent
- border-bottom-color: $base
- +position(absolute, left 50%, top -18px)
- margin-left: -10px
- +media-breakpoint-down(sm)
- left: 71%
-
-.header-drop-down__item
- cursor: pointer
-
-.header-drop-down__item:not(:last-child)
- border-bottom: solid 1px $background
-
-.header-drop-down__item-link
- +text-block(.875rem 1.6, block $main)
- padding: .5rem .75rem
- transition: all .2s ease-in
- .header-drop-down__item:first-child &
- +border-radius(top, .25rem)
- .header-drop-down__item:last-child &
- +border-radius(bottom, .25rem)
- &:hover
- background-color: $background-more-tint
-
-
-
-
-.header-notification-icon
- +text-block(1.25rem 1, center)
- +media-breakpoint-down(sm)
- +text-block(1.125rem 1)
- .has-count &
- color: $default-text
-
-.header-notification-count
- background-color: $badge-color
- +text-block(.625rem 1, center $reversal-text flex)
- align-items: center
- justify-content: center
- border-radius: 1rem
- position: absolute
- +media-breakpoint-up(md)
- +size(1.25rem .875rem)
- +position(right .25rem, top .25rem)
- +media-breakpoint-down(sm)
- +size(1.125rem .75rem)
- +position(right .125rem, top .125rem)
-
-.header-notifications-item__body
- width: 100%
- +media-breakpoint-up(md)
- color: $default-text
- +media-breakpoint-down(sm)
- color: $reversal-text
-
-.header-notifications-item__user-icon
- float: left
- +size(2rem)
- margin-right: .5rem
- margin-bottom: .25rem
-
-.header-notifications-item__message
- p
- line-height: 1.45
- margin-bottom: .375em
- +media-breakpoint-up(md)
- font-size: .8125rem
- +media-breakpoint-down(sm)
- font-size: .75rem
-
-.header-notifications-item_created-at
- text-align: right
- display: block
- +media-breakpoint-up(md)
- font-size: .75rem
- +media-breakpoint-down(sm)
- font-size: .625rem
-
-.header-drop-down__overlay
- +position(fixed, left 0, top 0, right 0, bottom 0, 1)
diff --git a/app/assets/stylesheets/blocks/header/_header-dropdown.sass b/app/assets/stylesheets/blocks/header/_header-dropdown.sass
index 9fed3dc5956..3cef8269344 100644
--- a/app/assets/stylesheets/blocks/header/_header-dropdown.sass
+++ b/app/assets/stylesheets/blocks/header/_header-dropdown.sass
@@ -16,8 +16,8 @@
.header-dropdown__inner
+media-breakpoint-up(md)
- background-color: $base
+position(absolute, right 0, top 100%, 2)
+ background-color: $base
border: solid 1px $border-shade
width: 14rem
box-shadow: rgba(black, .2) 0 0 .375rem
@@ -63,7 +63,7 @@
.header-dropdown__item:not(:last-child) &
border-bottom: solid 1px $background
&:hover
- background-color: $background-more-tint
+ background-color: $hover-background
+media-breakpoint-down(sm)
color: $reversal-text
border-bottom: solid 1px $side-border
diff --git a/app/assets/stylesheets/blocks/page/_page-tabs.sass b/app/assets/stylesheets/blocks/page/_page-tabs.sass
index 974811ea124..a73a9428abc 100644
--- a/app/assets/stylesheets/blocks/page/_page-tabs.sass
+++ b/app/assets/stylesheets/blocks/page/_page-tabs.sass
@@ -31,7 +31,7 @@
.page-tabs__item-link
+flex-link
- +text-block(.825rem 1, $default-text 600)
+ +text-block(.825rem 1, $semi-muted-text 600)
align-items: center
justify-content: center
height: 2.75rem
diff --git a/app/assets/stylesheets/blocks/shared/_tab-nav.sass b/app/assets/stylesheets/blocks/shared/_tab-nav.sass
index 77ddfa29a86..0101424e07a 100644
--- a/app/assets/stylesheets/blocks/shared/_tab-nav.sass
+++ b/app/assets/stylesheets/blocks/shared/_tab-nav.sass
@@ -25,14 +25,14 @@
.tab-nav__item-link
+block-link
- +text-block(.75rem 2.3, $muted-text center nowrap)
+ +text-block(.75rem 2.3, $semi-muted-text center nowrap)
background-color: $background-shade
border-radius: 20rem
width: 7rem
transition: all.2s ease-out
&:hover
background-color: shade($background-shade, 10%)
- color: $main-text
+ color: $default-text
&.is-active
background-color: $accent
- color: $main-text
+ color: $default-text
diff --git a/app/assets/stylesheets/blocks/user/_following.sass b/app/assets/stylesheets/blocks/user/_following.sass
new file mode 100644
index 00000000000..23bed703446
--- /dev/null
+++ b/app/assets/stylesheets/blocks/user/_following.sass
@@ -0,0 +1,32 @@
+.following
+ position: relative
+
+.following__dropdown
+ +position(absolute, 2)
+ width: 18.75rem
+
+.following-option
+ cursor: pointer
+ width: 100%
+ padding: .75rem
+ display: block
+ text-align: left
+ transition: all .2s ease-out
+ &:hover
+ background-color: $hover-background
+
+.following-option__inner
+ position: relative
+ padding-left: 1.5rem
+ .following-option.is-active &::before
+ +fa(fas '\f00c')
+ +position(absolute, left 0, top 0)
+
+.following-option__label
+ +text-block(.875rem 1.4, 600 $semi-muted-text)
+ .following-option.is-active &
+ color: $default-text
+
+.following-option__desciption
+ +text-block(.75rem 1.5, $muted-text)
+ margin-top: .125rem
diff --git a/app/assets/stylesheets/initializers/_reset.sass b/app/assets/stylesheets/initializers/_reset.sass
index d474b5d355f..37e171d17a7 100644
--- a/app/assets/stylesheets/initializers/_reset.sass
+++ b/app/assets/stylesheets/initializers/_reset.sass
@@ -50,5 +50,6 @@ hr
border: none
details,
-details *
+details *,
+summary
box-sizing: border-box
diff --git a/app/assets/stylesheets/mixins/_button.sass b/app/assets/stylesheets/mixins/_button.sass
index e74570c05ae..ded79fb04c9 100644
--- a/app/assets/stylesheets/mixins/_button.sass
+++ b/app/assets/stylesheets/mixins/_button.sass
@@ -15,6 +15,7 @@
&.is-block
display: flex
width: 100%
+ max-width: 100%
&.is-select
+margin(horizontal, 0)
&:focus
@@ -30,7 +31,6 @@
margin-right: .35em
margin-top: .02em
font-size: 1.07em
- font-weight: normal
&.is-icon
i
+text-block(1.3em 1)
diff --git a/app/assets/stylesheets/variables/_colors.sass b/app/assets/stylesheets/variables/_colors.sass
index 263d2b38485..9e408ecdf60 100644
--- a/app/assets/stylesheets/variables/_colors.sass
+++ b/app/assets/stylesheets/variables/_colors.sass
@@ -5,6 +5,8 @@ $background: #ececec
$background-shade: #d6d6d6
$background-tint: #eceeef
$background-more-tint: #f7f7f9
+$hover-background: $background-more-tint
+
$default-text: #403f47
$reversal-text: white
diff --git a/app/controllers/api/followings_controller.rb b/app/controllers/api/followings_controller.rb
index c88af55e8ac..ffdd969255b 100644
--- a/app/controllers/api/followings_controller.rb
+++ b/app/controllers/api/followings_controller.rb
@@ -5,13 +5,24 @@ class API::FollowingsController < API::BaseController
def create
user = User.find(params[:id])
- if current_user.follow(user)
+ watch = params[:watch] == 'true'
+ if current_user.follow(user, watch: watch)
render json: { id: user.id }
else
head :bad_request
end
end
+ def update
+ user = User.find(params[:id])
+ watch = params[:watch] == 'true'
+ if current_user.change_watching(user, watch)
+ head :no_content
+ else
+ head :bad_request
+ end
+ end
+
def destroy
user = User.find(params[:id])
if current_user.unfollow(user)
diff --git a/app/controllers/api/users_controller.rb b/app/controllers/api/users_controller.rb
index 7bbb461791e..813800fbb43 100644
--- a/app/controllers/api/users_controller.rb
+++ b/app/controllers/api/users_controller.rb
@@ -9,11 +9,11 @@ def index
@tag = params[:tag]
@target = params[:target]
@target = 'student_and_trainee' unless target_allowlist.include?(@target)
+ @watch = params[:watch]
target_users =
if @target == 'followings'
- followings = Following.where(follower_id: current_user.id).select('followed_id')
- User.where(id: followings)
+ current_user.following_list(watch: @watch)
elsif params[:tag]
User.tagged_with(params[:tag])
else
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 42de99ff5a8..18175b4e3df 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -9,11 +9,11 @@ class UsersController < ApplicationController
def index
@target = params[:target]
@target = 'student_and_trainee' unless target_allowlist.include?(@target)
+ @watch = params[:watch]
target_users =
if @target == 'followings'
- followings = Following.where(follower_id: current_user.id).select('followed_id')
- User.where(id: followings)
+ current_user.following_list(watch: @watch)
elsif params[:tag]
User.tagged_with(params[:tag])
else
diff --git a/app/javascript/following.js b/app/javascript/following.js
index 893f7113574..ef86f606acd 100644
--- a/app/javascript/following.js
+++ b/app/javascript/following.js
@@ -8,13 +8,15 @@ document.addEventListener('DOMContentLoaded', () => {
const following = followings[i]
const isFollowing = following.getAttribute('data-is-following')
const userId = following.getAttribute('data-user-id')
+ const isWatching = following.getAttribute('data-is-watching')
new Vue({
render: (h) =>
h(Following, {
props: {
isFollowing: isFollowing === 'true',
- userId: Number(userId)
+ userId: Number(userId),
+ isWatching: isWatching === 'true'
}
})
}).$mount('.js-following')
diff --git a/app/javascript/following.vue b/app/javascript/following.vue
index 42cfd66bd0b..5a84aefd77f 100644
--- a/app/javascript/following.vue
+++ b/app/javascript/following.vue
@@ -1,9 +1,69 @@
-button.card-main-actions__action.a-button.is-sm.is-block(
- :class='following ? "is-danger" : "is-secondary"',
- @click='followOrUnfollow'
-)
- | {{ buttonLabel }}
+details.following
+ summary.a-button.is-warning.is-md.is-block(v-if='following && watching')
+ i.fas.fa-check
+ span
+ | コメントあり
+ summary.a-button.is-warning.is-md.is-block(
+ v-else-if='following && !watching'
+ )
+ i.fas.fa-check
+ span
+ | コメントなし
+ summary.a-button.is-secondary.is-md.is-block(v-else)
+ | {{ buttonLabel }}
+ .following__dropdown.a-dropdown
+ ul.a-dropdown__items
+ li.following__dropdown-item.a-dropdown__item
+ button.following-option.a-dropdown__item-inner.is-active(
+ v-if='following && watching'
+ )
+ .following-option__inner
+ .following-option__label
+ | コメントあり
+ .following-option__desciption
+ | フォローしたユーザーの日報を自動でWatch状態にします。日報投稿時の通知と日報にコメントが来た際に通知を受け取ります。
+ button.following-option.a-dropdown__item-inner(
+ v-else,
+ @click='followOrChangeFollow(true)'
+ )
+ .following-option__inner
+ .following-option__label
+ | コメントあり
+ .following-option__desciption
+ | フォローしたユーザーの日報を自動でWatch状態にします。日報投稿時の通知と日報にコメントが来た際に通知を受け取ります。
+ li.following__dropdown-item.a-dropdown__item
+ button.following-option.a-dropdown__item-inner.is-active(
+ v-if='following && !watching'
+ )
+ .following-option__inner
+ .following-option__label
+ | コメントなし
+ .following-option__desciption
+ | フォローしたユーザーの日報はWatch状態にしません。日報投稿時の通知だけ通知を受けとります。
+ button.following-option.a-dropdown__item-inner(
+ v-else,
+ @click='followOrChangeFollow(false)'
+ )
+ .following-option__inner
+ .following-option__label
+ | コメントなし
+ .following-option__desciption
+ | フォローしたユーザーの日報はWatch状態にしません。日報投稿時の通知だけ通知を受けとります。
+ li.following__dropdown-item.a-dropdown__item
+ button.following-option.a-dropdown__item-inner.is-active(
+ v-if='!following'
+ )
+ .following-option__inner
+ .following-option__label
+ | フォローしない
+ button.following-option.a-dropdown__item-inner(
+ v-else,
+ @click='unfollow'
+ )
+ .following-option__inner
+ .following-option__label
+ | フォローしない
-
diff --git a/app/javascript/notifications_bell.vue b/app/javascript/notifications_bell.vue
index 230fd55cc12..569ff812d23 100644
--- a/app/javascript/notifications_bell.vue
+++ b/app/javascript/notifications_bell.vue
@@ -29,7 +29,7 @@ li.header-links__item(v-bind:class='hasCountClass')
)
.header-notifications-item__message
p.test-notification-message {{ notification.message }}
- time.header-notifications-item_created-at {{ createdAtFromNow(notification.created_at) }}
+ time.header-notifications-item__created-at {{ createdAtFromNow(notification.created_at) }}
footer.header-dropdown__footer
a.header-dropdown__footer-link(href='/notifications?status=unread') 全ての未読通知
a.header-dropdown__footer-link(href='/notifications') 全ての通知
diff --git a/app/javascript/user-secret-attributes.vue b/app/javascript/user-secret-attributes.vue
index 3061323721f..a507b22032c 100644
--- a/app/javascript/user-secret-attributes.vue
+++ b/app/javascript/user-secret-attributes.vue
@@ -27,6 +27,11 @@
:class='{ "is-important": isInactive }'
)
| {{ user.updated_at }}
+ .user-secret-attributes__action(v-if='currentUser.admin')
+ a.card-main-actions__action.a-button.is-sm.is-secondary.is-block(
+ :href='user.edit_admin_user_path'
+ )
+ | 管理者として変更