diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb index 8d563a0d32b..ba588c7dece 100644 --- a/app/decorators/user_decorator.rb +++ b/app/decorators/user_decorator.rb @@ -5,6 +5,7 @@ module UserDecorator include Role include Retire + include ReportStatus def twitter_url "https://twitter.com/#{twitter_account}" diff --git a/app/decorators/user_decorator/report_status.rb b/app/decorators/user_decorator/report_status.rb new file mode 100644 index 00000000000..bc024cf5f43 --- /dev/null +++ b/app/decorators/user_decorator/report_status.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module UserDecorator + module ReportStatus + REPORT_COUNT_LEVELS = { + 'is-success' => 0..1, + 'is-primary' => 2..4, + 'is-warning' => 5..9 + }.freeze + + LAST_UNCHECKED_REPORT_COUNT = 1 + + def user_report_count_class(count) + REPORT_COUNT_LEVELS.find { |_, range| range.include?(count) }&.first || 'is-danger' + end + + def unchecked_report_message(count, user) + if count.zero? + "#{user.login_name}さんの日報へ" + elsif count == LAST_UNCHECKED_REPORT_COUNT + "#{user.login_name}さんの未チェックの日報はこれで最後です。" + else + "#{user.login_name}さんの未チェックの日報が#{count}件あります。" + end + end + end +end diff --git a/app/javascript/stylesheets/application.sass b/app/javascript/stylesheets/application.sass index 1648020d458..1f5d260153b 100644 --- a/app/javascript/stylesheets/application.sass +++ b/app/javascript/stylesheets/application.sass @@ -13,6 +13,7 @@ @import application/blocks/auth-form/skip-practices @import application/blocks/cards/card-counts +@import application/blocks/cards/card-body-main-actions @import application/blocks/company/company-links @import application/blocks/company/company-profile diff --git a/app/javascript/stylesheets/application/blocks/cards/_card-body-main-actions.sass b/app/javascript/stylesheets/application/blocks/cards/_card-body-main-actions.sass new file mode 100644 index 00000000000..45c1d1cd5bb --- /dev/null +++ b/app/javascript/stylesheets/application/blocks/cards/_card-body-main-actions.sass @@ -0,0 +1,47 @@ +.card-body-main-actions + +position(relative, 1) + padding-block: .75rem + margin-inline: 1rem + border-radius: 4px + +media-breakpoint-up(md) + padding-inline: 2rem + margin-bottom: 1.5rem + +media-breakpoint-down(sm) + padding-inline: .75rem + margin-bottom: 1rem + &.is-success + background-color: #f8fff2 + border: 1px solid var(--success) + color: var(--success-text) + &.is-primary + border: 1px solid var(--primary) + background-color: #f5f5ff + color: var(--primary-text) + &.is-warning + border: 1px solid var(--warning) + background-color: #fff9e7 + color: var(--warning-text) + &.is-danger + border: 1px solid var(--danger) + background-color: var(--danger-tint) + color: var(--danger-text) + +.card-body-main-actions__description + +text-block(.875rem 1.4) + margin-bottom: .75em + text-align: center + +.card-body-main-actions__items + display: flex + justify-content: center + +.card-body-main-actions__item + text-align: center + flex: 1 + +media-breakpoint-up(md) + max-width: 16rem + +.card-body-main-actions__item-cancel + +hover-link-reversal + color: var(--muted-text) + font-size: .8125rem diff --git a/app/javascript/stylesheets/application/blocks/event/_event-main-actions.sass b/app/javascript/stylesheets/application/blocks/event/_event-main-actions.sass index 59be5dfb7ec..49143836221 100644 --- a/app/javascript/stylesheets/application/blocks/event/_event-main-actions.sass +++ b/app/javascript/stylesheets/application/blocks/event/_event-main-actions.sass @@ -15,8 +15,8 @@ color: #4e732e &.is-unparticipationed.is-available border: 1px solid var(--primary) - background-color: #e9f9ff - color: #116e94 + background-color: #f5f5ff + color: #28248c &.is-unparticipationed.is-capacity-over border: 1px solid var(--warning) background-color: #fff9e7 @@ -27,7 +27,7 @@ color: var(--danger) .event-main-actions__description - +text-block(.8125rem 1.4) + +text-block(.875rem 1.4) margin-bottom: .75em text-align: center diff --git a/app/models/cache.rb b/app/models/cache.rb index b2353db6b19..020f1a9df80 100644 --- a/app/models/cache.rb +++ b/app/models/cache.rb @@ -12,6 +12,16 @@ def delete_unchecked_report_count Rails.cache.delete 'unchecked_report_count' end + def user_unchecked_report_count(user) + Rails.cache.fetch "#{user.id}-user_unchecked_report_count" do + Report.unchecked.not_wip.user(user).count + end + end + + def delete_user_unchecked_report_count(user_id) + Rails.cache.delete "#{user_id}-user_unchecked_report_count" + end + def unchecked_product_count Rails.cache.fetch 'unchecked_product_count' do Product.unhibernated_user_products.unchecked.not_wip.count diff --git a/app/models/check_callbacks.rb b/app/models/check_callbacks.rb index ac22a01dfe3..f6a902ba67c 100644 --- a/app/models/check_callbacks.rb +++ b/app/models/check_callbacks.rb @@ -24,7 +24,9 @@ def after_destroy(check) def delete_report_cache(check) return unless check.checkable_type == 'Report' + report = check.checkable Cache.delete_unchecked_report_count + Cache.delete_user_unchecked_report_count(report.user_id) end def delete_product_cache(check) diff --git a/app/models/report.rb b/app/models/report.rb index 4b25cc751a6..6c8c6ebcd25 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -60,6 +60,8 @@ class Report < ApplicationRecord # rubocop:todo Metrics/ClassLength .default_order } + scope :user, ->(user) { where(user_id: user.id) } + class << self def faces @faces ||= emotions.keys diff --git a/app/models/report_callbacks.rb b/app/models/report_callbacks.rb index ba5ab439fdd..f1f7164e310 100644 --- a/app/models/report_callbacks.rb +++ b/app/models/report_callbacks.rb @@ -7,6 +7,7 @@ def after_create(report) def after_destroy(report) Cache.delete_unchecked_report_count + Cache.delete_user_unchecked_report_count(report.user_id) delete_notification(report) end diff --git a/app/models/report_notifier.rb b/app/models/report_notifier.rb index db793737dbd..79ea5ff383c 100644 --- a/app/models/report_notifier.rb +++ b/app/models/report_notifier.rb @@ -4,6 +4,7 @@ class ReportNotifier def call(_name, _started, _finished, _unique_id, payload) report = payload[:report] Cache.delete_unchecked_report_count + Cache.delete_user_unchecked_report_count(report.user_id) return unless report.first_public? diff --git a/app/views/reports/_report_body.html.slim b/app/views/reports/_report_body.html.slim index 9ff8c49b48f..c926ba159bd 100644 --- a/app/views/reports/_report_body.html.slim +++ b/app/views/reports/_report_body.html.slim @@ -6,6 +6,23 @@ .card-body__description .a-long-text.is-md.js-markdown-view(data-taskable-id="#{report.id}" data-taskable-type='Report' data-taskable="#{report.taskable?(current_user).to_s}") = report.description + - if staff_login? + - count = Cache.user_unchecked_report_count(report.user) + .card-body-main-actions(class="#{report.user.user_report_count_class(count)} #{mentor_login? ? 'is-only-mentor' : ''}") + .card-body-main-actions__description + p + = report.user.unchecked_report_message(count, report.user) + ul.card-body-main-actions__items + li.card-body-main-actions__item + = link_to user_reports_path(report.user), class: "card-body-main-actions__action a-button is-sm #{report.user.user_report_count_class(count)} is-block", target: '_blank', rel: 'noopener' do + | #{report.user.login_name}さんの日報一覧へ + - else + .card-body-main-actions.p-0 + ul.card-body-main-actions__items + li.card-body-main-actions__item + = link_to user_reports_path(report.user), class: 'card-body-main-actions__action a-button is-sm is-secondary is-block', target: '_blank', rel: 'noopener' do + | #{report.user.login_name}さんの日報一覧へ + hr.a-border-tint = render 'reactions/reactions', reactionable: report diff --git a/test/decorators/user_decorator/report_status.rb b/test/decorators/user_decorator/report_status.rb new file mode 100644 index 00000000000..e034c4889d8 --- /dev/null +++ b/test/decorators/user_decorator/report_status.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'active_decorator_test_case' + +module UserDecorator + class ReportStatusTest < ActiveDecoratorTestCase + test 'user_report_count_class' do + assert_equal 'is-success', user_report_count_class(0) + assert_equal 'is-success', user_report_count_class(1) + + assert_equal 'is-primary', user_report_count_class(2) + assert_equal 'is-primary', user_report_count_class(4) + + assert_equal 'is-warning', user_report_count_class(5) + assert_equal 'is-warning', user_report_count_class(9) + + assert_equal 'is-danger', user_report_count_class(10) + assert_equal 'is-danger', user_report_count_class(100) + end + + test 'unchecked_report_message' do + user = users(:hajime) + assert_equal "#{user.login_name}さんの日報へ", unchecked_report_message(0, user) + assert_equal "#{user.login_name}さんの未チェックの日報はこれで最後です。", unchecked_report_message(1, user) + assert_equal "#{user.login_name}さんの未チェックの日報が2件あります。", unchecked_report_message(2, user) + end + end +end