Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions app/components/common_components/organization_statistics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
<div>
<div class="flex align-center justify-between w-full p-2">
<%= render Datepicker.new(date: @selected_date, target: 'selected_date') do |picker| %>
<% picker.with_input_field do %>
<input id="select_date" data-datepicker-target="picker" value="<%= @selected_date %>" class="mt-1 rounded-md border-purple-500 text-sm focus:border-green-600 focus:outline-hidden focus:ring-green-600"
data-action="change->datepicker#updateFilter"/>
<%= render CommonComponents::ButtonComponent.new(label: t(:filter), options: { 'data-datepicker-target' => 'anchor' })%>
<div>
<%= render Datepicker.new(date: @selected_date, target: 'selected_date', enabled_dates: @available_lesson_dates.map(&:to_s)) do |picker| %>
<% picker.with_input_field do %>
<input id="select_date" data-datepicker-target="picker" value="<%= @selected_date %>" class="mt-1 rounded-md border-purple-500 text-sm focus:border-green-600 focus:outline-hidden focus:ring-green-600"
data-action="change->datepicker#updateFilter"/>
<%= render CommonComponents::ButtonComponent.new(label: t(:filter), options: { 'data-datepicker-target' => 'anchor' })%>
<% end %>
<% end %>
<% if @used_default_date && @available_lesson_dates.any? %>
<p class="text-xs text-gray-500 mt-1"><%= t(:showing_data_for_last_lessons) %></p>
<% end %>
<% end %>
</div>
</div>
<% if @lesson_summaries.any? %>
<dl class="mt-6 grid grid-cols-2 gap-5 sm:grid-cols-2">
Expand All @@ -40,7 +49,7 @@ def initialize(group_lesson_summaries, selected_date = Time.zone.today)
</div>
</dl>
<% else %>
<h1 class="text-center text-xxl font-bold text-gray-500"> No data for the selected date </h1>
<h1 class="text-center text-xxl font-bold text-gray-500"> <%= t(:no_lessons_data_exists) %> </h1>
<% end %>
</div>
ERB
Expand Down
7 changes: 5 additions & 2 deletions app/components/datepicker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Datepicker < ViewComponent::Base
renders_one :input_field

erb_template <<~ERB
<div class="inline-block" data-controller="datepicker" data-datepicker-date-value=<%= @date %> >
<div class="inline-block" data-controller="datepicker" data-datepicker-date-value=<%= @date %><% 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' %>
Expand All @@ -15,11 +15,14 @@ class Datepicker < ViewComponent::Base
</div>
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
13 changes: 11 additions & 2 deletions app/controllers/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
17 changes: 10 additions & 7 deletions app/javascript/controllers/datepicker_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -19,24 +19,27 @@ 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('-');
const year = parseInt(parts[0]);
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
});
}
}
4 changes: 2 additions & 2 deletions app/views/organizations/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
<div class="bg-white py-1 px-4 pb-8">
<%= 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) %>
</div>
<% end %>
<% end %>
Expand Down
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 22 additions & 11 deletions spec/features/organization_features_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
Expand Down
Loading