diff --git a/app/components/common_components/organization_statistics.rb b/app/components/common_components/organization_statistics.rb index 7fcf85346..95ef624b2 100644 --- a/app/components/common_components/organization_statistics.rb +++ b/app/components/common_components/organization_statistics.rb @@ -2,23 +2,32 @@ class CommonComponents::OrganizationStatistics < ViewComponent::Base include ApplicationHelper include CollectionHelper - def initialize(group_lesson_summaries, selected_date = Time.zone.today) - @lesson_summaries = group_lesson_summaries + # rubocop:disable Metrics/ParameterLists + def initialize(lesson_summaries, number_of_lessons:, total_data_points:, selected_date:, available_lesson_dates: [], used_default_date: false) + @lesson_summaries = lesson_summaries + @number_of_lessons = number_of_lessons + @total_data_points = total_data_points @selected_date = selected_date - @number_of_lessons = @lesson_summaries.count - @total_data_points = @lesson_summaries.sum(&:grade_count) + @available_lesson_dates = available_lesson_dates + @used_default_date = used_default_date end + # rubocop:enable Metrics/ParameterLists erb_template <<~ERB
- <%= render Datepicker.new(date: @selected_date, target: 'selected_date') do |picker| %> - <% picker.with_input_field do %> - - <%= render CommonComponents::ButtonComponent.new(label: t(:filter), options: { 'data-datepicker-target' => 'anchor' })%> +
+ <%= render Datepicker.new(date: @selected_date, target: 'selected_date', enabled_dates: @available_lesson_dates.map(&:to_s)) do |picker| %> + <% picker.with_input_field do %> + + <%= render CommonComponents::ButtonComponent.new(label: t(:filter), options: { 'data-datepicker-target' => 'anchor' })%> + <% end %> + <% end %> + <% if @used_default_date && @available_lesson_dates.any? %> +

<%= t(:showing_data_for_last_lessons) %>

<% end %> - <% end %> +
<% if @lesson_summaries.any? %>
@@ -40,7 +49,7 @@ def initialize(group_lesson_summaries, selected_date = Time.zone.today)
<% else %> -

No data for the selected date

+

<%= t(:no_lessons_data_exists) %>

<% end %> ERB diff --git a/app/components/datepicker.rb b/app/components/datepicker.rb index 070c50f30..4ea2c68ba 100644 --- a/app/components/datepicker.rb +++ b/app/components/datepicker.rb @@ -2,7 +2,7 @@ class Datepicker < ViewComponent::Base renders_one :input_field erb_template <<~ERB -
> +
<% if @enabled_dates %> data-datepicker-enabled-dates-value='<%= @enabled_dates.to_json %>'<% end %>> <% if @form %> <%= @form.text_field @target, data: { 'datepicker-target' => 'picker' }, class: @custom_class || 'rounded-md border-purple-500 text-sm focus:border-green-600 focus:outline-hidden focus:ring-green-600', autocomplete: 'disabled' %> @@ -15,11 +15,14 @@ class Datepicker < ViewComponent::Base
ERB - def initialize(date:, target:, form: nil, custom_name: nil, custom_class: nil) + # rubocop:disable Metrics/ParameterLists + def initialize(date:, target:, form: nil, custom_name: nil, custom_class: nil, enabled_dates: nil) @date = date @target = target @form = form @custom_name = custom_name @custom_class = custom_class + @enabled_dates = enabled_dates end + # rubocop:enable Metrics/ParameterLists end diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index f695b6d9b..f2b858e89 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -118,8 +118,7 @@ def initialize_organization(id) @new_member = User.new @roles = Role::LOCAL_ROLES.keys - @selected_date = params[:selected_date] || Time.zone.today - @lesson_summaries = GroupLessonSummary.where(chapter_id: @organization.chapters, lesson_date: @selected_date) + populate_lesson_activity end def chapter_order_scope @@ -171,6 +170,16 @@ def undelete private + def populate_lesson_activity + lesson_summaries_for_organization = GroupLessonSummary.where(chapter_id: @organization.chapters) + @available_lesson_dates = lesson_summaries_for_organization.distinct.pluck(:lesson_date).sort + @used_default_date = params[:selected_date].blank? + @selected_date = params[:selected_date].presence || @available_lesson_dates.last || Time.zone.today + @lesson_summaries = lesson_summaries_for_organization.where(lesson_date: @selected_date).to_a + @number_of_lessons = @lesson_summaries.count + @total_data_points = @lesson_summaries.sum(&:grade_count) + end + def file_is_csv?(content_type) %w[text/csv text/x-csv application/vnd.ms-excel application/csv application/x-csv].include? content_type end diff --git a/app/javascript/controllers/datepicker_controller.js b/app/javascript/controllers/datepicker_controller.js index 6c4f25459..63b2251cd 100644 --- a/app/javascript/controllers/datepicker_controller.js +++ b/app/javascript/controllers/datepicker_controller.js @@ -3,7 +3,7 @@ import * as pikaday from 'pikaday' // Connects to data-controller="datepicker" export default class extends Controller { - static values = { date: String } + static values = { date: String, enabledDates: Array } static targets = [ "picker", "anchor" ] updateFilter() { @@ -19,16 +19,18 @@ export default class extends Controller { } connect() { + const formatDate = (date) => { + const parts = [date.getFullYear(), ('0'+(date.getMonth()+1)).slice(-2), ('0'+date.getDate()).slice(-2)]; + return parts.join("-"); + } + const enabledDates = this.hasEnabledDatesValue ? new Set(this.enabledDatesValue) : null + const picker = new Pikaday({ field: this.pickerTarget, minDate: new Date(Date.parse('1970-01-01')), maxDate: new Date(), format: 'YYYY-MM-DD', - toString(date, format) { - // showing the date here in the format defined above - const parts = [date.getFullYear(), ('0'+(date.getMonth()+1)).slice(-2), ('0'+date.getDate()).slice(-2)]; - return parts.join("-"); - }, + toString: formatDate, parse(dateString, format) { // dateString is the result of the `toString` method const parts = dateString.split('-'); @@ -36,7 +38,8 @@ export default class extends Controller { const month = parseInt(parts[1]) - 1; const day = parseInt(parts[2]); return new Date(year, month, day); - } + }, + disableDayFn: enabledDates ? (date) => !enabledDates.has(formatDate(date)) : undefined }); } } diff --git a/app/views/organizations/show.html.erb b/app/views/organizations/show.html.erb index 9d490c4bb..a1676987e 100644 --- a/app/views/organizations/show.html.erb +++ b/app/views/organizations/show.html.erb @@ -31,10 +31,10 @@ end %> <% end %> <% end %> <% end %> - <%= render CommonComponents::Card.new(title: "Statistics".capitalize) do |card| %> + <%= render CommonComponents::Card.new(title: t(:lesson_activity)) do |card| %> <% card.with_card_content do %>
- <%= render CommonComponents::OrganizationStatistics.new(@lesson_summaries, @selected_date) %> + <%= render CommonComponents::OrganizationStatistics.new(@lesson_summaries, number_of_lessons: @number_of_lessons, total_data_points: @total_data_points, selected_date: @selected_date, available_lesson_dates: @available_lesson_dates, used_default_date: @used_default_date) %>
<% end %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 83b1a7f19..1e112cdbf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -395,6 +395,9 @@ en: groups_with_lessons: Groups with Lessons performance_change: Performance change + lesson_activity: Lesson Activity + showing_data_for_last_lessons: Showing data for last lessons + no_lessons_data_exists: No lessons data exists nr_of_lessons: Nr. of Lessons nr_of_assessments: Nr. of Assessments nr_of_graded_students: Nr. of Graded students diff --git a/spec/features/organization_features_spec.rb b/spec/features/organization_features_spec.rb index fcae57eb8..f85f27265 100644 --- a/spec/features/organization_features_spec.rb +++ b/spec/features/organization_features_spec.rb @@ -48,17 +48,9 @@ end end - it 'does not display the organization\'s statistics when there is no data' do - expect(page).to have_content 'No data for the selected date' - expect(page).to have_content 'Statistics' - end - - it 'does display the organization\'s statistics when there is data' do - expect(page).to have_content 'Statistics' - - fill_in 'select_date', with: @lesson.date - click_link 'Filter' - + it 'defaults to the most recent lesson date and shows lesson activity immediately' do + expect(page).to have_content 'Lesson Activity' + expect(page).to have_content 'Showing data for last lessons' expect(page).to have_content 'Nr. of Lessons' expect(page).to have_content 'Nr. of Assessments' expect(page).to have_content 'Groups with Lessons' @@ -69,6 +61,25 @@ expect(statistic_components[1]).to have_content 3 expect(statistic_components[2]).to have_content @groups.first.group_chapter_name end + + it 'shows a clear message when the selected date has no lesson data' do + empty_date = @lesson.date - 100 + + visit organization_path(@organization, selected_date: empty_date) + + expect(page).to have_content 'No lessons data exists' + expect(page).not_to have_content 'Showing data for last lessons' + end + + it 'still shows lesson activity when explicitly filtering to a date with data' do + fill_in 'select_date', with: @lesson.date + click_link 'Filter' + + expect(page).to have_content 'Nr. of Lessons' + expect(page).to have_content 'Nr. of Assessments' + expect(page).to have_content 'Groups with Lessons' + expect(page).not_to have_content 'Showing data for last lessons' + end end describe 'Adding members to organization' do