From b448c53481f2f7de56c7f353d2a8fbb8dd07d23c Mon Sep 17 00:00:00 2001 From: Kyle Huckins Date: Sun, 8 Dec 2019 00:07:26 +0000 Subject: [PATCH] Course Page - Perl Module and Course Page displaying name and course number of course, as well as names/roles of publicly viewable members, course details, and a table of all materials associated with the course. - URL listed as eg/opac/course/[COURSE_ID] Signed-off-by: Kyle Huckins Changes to be committed: modified: Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm modified: Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm new file: Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm new file: Open-ILS/src/templates/opac/course.tt2 modified: Open-ILS/src/templates/opac/css/style.css.tt2 new file: Open-ILS/src/templates/opac/parts/course/body.tt2 --- .../src/perlmods/lib/OpenILS/Application/Circ.pm | 116 ++++++++++++++++++++- .../src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm | 2 + .../perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm | 42 ++++++++ Open-ILS/src/templates/opac/course.tt2 | 16 +++ Open-ILS/src/templates/opac/css/style.css.tt2 | 35 +++++-- Open-ILS/src/templates/opac/parts/course/body.tt2 | 101 ++++++++++++++++++ 6 files changed, 301 insertions(+), 11 deletions(-) create mode 100644 Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm create mode 100644 Open-ILS/src/templates/opac/course.tt2 create mode 100644 Open-ILS/src/templates/opac/parts/course/body.tt2 diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm index 69befc2f64..0a7c80f7fe 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm @@ -1050,7 +1050,17 @@ __PACKAGE__->register_method( api_name => 'open-ils.circ.course_materials.retrieve', signature => q/ Returns an array of course materials. - @params copy_id : The id of the item who's materials we want to retrieve + @params args : Supplied object to filter search. + /); + +__PACKAGE__->register_method( + method => 'fetch_course_materials', + autoritative => 1, + api_name => 'open-ils.circ.course_materials.retrieve.fleshed', + signature => q/ + Returns an array of course materials, each fleshed out with information + from the item and the course_material object. + @params args : Supplied object to filter search. /); __PACKAGE__->register_method( @@ -1065,8 +1075,55 @@ __PACKAGE__->register_method( sub fetch_course_materials { my ($self, $conn, $args) = @_; my $e = new_editor(); + my $materials = {}; + my %items; + + $materials->{list} = $e->search_asset_course_module_course_materials($args); + return $materials->{list} unless ($self->api_name =~ /\.fleshed/); + + # If we want it fleshed out... + for my $course_material (@{$materials->{list}}) { + my $material = {}; + $material->{id} = $course_material->id; + $material->{relationship} = $course_material->relationship; + $material->{record} = $course_material->record; + my $copy = $e->retrieve_asset_copy([ + $course_material->item, { + flesh => 3, flesh_fields => { + 'acp' => ['call_number'], + 'acn' => ['record'] + } + } + ]); + + $material->{item_data} = $copy; + $material->{volume_data} = $copy->call_number; + $material->{record_data} = $copy->call_number->record; + $items{$course_material->item} = $material; + } - return $e->search_asset_course_module_course_materials($args); + my $targets = (); + for my $item (values %items) { + my $final_item = {}; + my $mvr = $U->record_to_mvr($item->{record_data}); + $final_item->{id} = $item->{id}; + $final_item->{relationship} = $item->{relationship}; + $final_item->{record} = $item->{record}; + $final_item->{barcode} = $item->{item_data}->barcode; + $final_item->{circ_lib} = $item->{item_data}->circ_lib; + $final_item->{title} = $mvr->title; + $final_item->{call_number} = $item->{volume_data}->label; + $final_item->{location} = $e->retrieve_asset_copy_location( + $item->{item_data}->location + ); + $final_item->{status} = $e->retrieve_config_copy_status( + $item->{item_data}->status + ); + + push @$targets, $final_item; + } + + return $targets; } sub fetch_courses { @@ -1084,6 +1141,61 @@ sub fetch_courses { } __PACKAGE__->register_method( + method => 'fetch_course_users', + autoritative => 1, + api_name => 'open-ils.circ.course_users.retrieve', + signature => q/ + Returns an array of course users. + @params course_id: The id of the course we want to retrieve from + /); +__PACKAGE__->register_method( + method => 'fetch_course_users', + autoritative => 1, + api_name => 'open-ils.circ.course_users.retrieve.staff', + signature => q/ + Returns an array of course users. + @params course_id: The id of the course we want to retrieve from + /); + +sub fetch_course_users { + my ($self, $conn, $course_id) = @_; + my $e = new_editor(); + my $filter = {}; + my $users = {}; + my %patrons; + + $filter->{course} = $course_id; + $filter->{is_public} = 't' + unless ($self->api_name =~ /\.staff/) and $e->allowed('MANAGE_RESERVES'); + + + $users->{list} = $e->search_asset_course_module_course_users($filter); + for my $course_user (@{$users->{list}}) { + my $patron = {}; + $patron->{id} = $course_user->id; + $patron->{usr_role} = $course_user->usr_role; + $patron->{patron_data} = $e->retrieve_actor_user($course_user->usr); + $patrons{$course_user->usr} = $patron; + } + + my $targets = (); + for my $user (values %patrons) { + my $final_user = {}; + $final_user->{id} = $user->{id}; + $final_user->{usr_role} = $user->{usr_role}; + $final_user->{first_given_name} = $user->{patron_data}->first_given_name; + $final_user->{family_name} = $user->{patron_data}->family_name; + $final_user->{pref_first_given_name} = $user->{patron_data}->pref_first_given_name; + $final_user->{pref_family_name} = $user->{patron_data}->pref_family_name; + + push @$targets, $final_user; + } + + return $targets; + +} + +__PACKAGE__->register_method( method => 'fetch_copy_tags', authoritative => 1, api_name => 'open-ils.circ.copy_tags.retrieve', diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index 7388d79706..25461727f6 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -23,6 +23,7 @@ use OpenILS::WWW::EGCatLoader::Browse; use OpenILS::WWW::EGCatLoader::Library; use OpenILS::WWW::EGCatLoader::Search; use OpenILS::WWW::EGCatLoader::Record; +use OpenILS::WWW::EGCatLoader::Course; use OpenILS::WWW::EGCatLoader::Container; use OpenILS::WWW::EGCatLoader::SMS; use OpenILS::WWW::EGCatLoader::Register; @@ -149,6 +150,7 @@ sub load { return $self->load_record if $path =~ m|opac/record/\d|; return $self->load_cnbrowse if $path =~ m|opac/cnbrowse|; return $self->load_browse if $path =~ m|opac/browse|; + return $self->load_course if $path =~ m|opac/course|; return $self->load_mylist_add if $path =~ m|opac/mylist/add|; return $self->load_mylist_delete if $path =~ m|opac/mylist/delete|; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm new file mode 100644 index 0000000000..bd340eadfb --- /dev/null +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm @@ -0,0 +1,42 @@ +package OpenILS::WWW::EGCatLoader; +use strict; use warnings; +use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_GONE HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST HTTP_NOT_FOUND); +use OpenSRF::Utils::Logger qw/$logger/; +use OpenILS::Utils::CStoreEditor qw/:funcs/; +use OpenILS::Utils::Fieldmapper; +use OpenILS::Application::AppUtils; +use Net::HTTP::NB; +use IO::Select; +my $U = 'OpenILS::Application::AppUtils'; + +sub load_course { + my $self = shift; + my $ctx = $self->ctx; + + $ctx->{page} = 'course'; + $ctx->{readonly} = $self->cgi->param('readonly'); + + my $course_id = $ctx->{page_args}->[0]; + + return Apache2::Const::HTTP_BAD_REQUEST + unless $course_id and $course_id =~ /^\d+$/; + + $ctx->{course} = $U->simplereq( + 'open-ils.circ', + 'open-ils.circ.courses.retrieve', + [$course_id] + )->[0]; + + $ctx->{instructors} = $U->simplereq( + 'open-ils.circ', + 'open-ils.circ.course_users.retrieve', + $course_id + ); + + $ctx->{course_materials} = $U->simplereq( + 'open-ils.circ', + 'open-ils.circ.course_materials.retrieve.fleshed', + {course => $course_id} + ); + return Apache2::Const::OK; +} \ No newline at end of file diff --git a/Open-ILS/src/templates/opac/course.tt2 b/Open-ILS/src/templates/opac/course.tt2 new file mode 100644 index 0000000000..e53fc064aa --- /dev/null +++ b/Open-ILS/src/templates/opac/course.tt2 @@ -0,0 +1,16 @@ +[%- PROCESS "opac/parts/header.tt2"; + WRAPPER "opac/parts/base.tt2"; + INCLUDE "opac/parts/topnav.tt2"; + ctx.page_title = l("Course Details: [_1] - [_2]", ctx.course.name, ctx.course.course_number); +-%] + [%- INCLUDE "opac/parts/searchbar.tt2" %] +

[% l('Course Details') %]

+
+
+
+ [% INCLUDE "opac/parts/course/body.tt2" %] +
+
+
+
+[%- END %] diff --git a/Open-ILS/src/templates/opac/css/style.css.tt2 b/Open-ILS/src/templates/opac/css/style.css.tt2 index 6fe12ea051..f998b7f927 100644 --- a/Open-ILS/src/templates/opac/css/style.css.tt2 +++ b/Open-ILS/src/templates/opac/css/style.css.tt2 @@ -672,7 +672,8 @@ div.format_icon { padding-top: 1.5em; } -#rdetails_status td { +#rdetails_status td, +#course_material_table td { [% IF rtl == 't' -%] padding: 7px 13px 3px 0px; [%- ELSE %] @@ -685,7 +686,8 @@ div.format_icon { white-space: normal; } -#rdetails_status thead th { +#rdetails_status thead th, +#course_material_table thead th { [% IF rtl == 't' -%] padding: 13px 13px 13px 0px; text-align: right; @@ -698,7 +700,8 @@ div.format_icon { font-weight: bold; } -#rdetails_status tbody td { +#rdetails_status tbody td, +#course_material_table tbody td { [% IF rtl == 't' -%] padding-right: 13px; text-align: right; @@ -707,7 +710,8 @@ div.format_icon { text-align: left; [%- END %] } -#rdetails_status tbody td.copy_note { +#rdetails_status tbody td.copy_note +#course_material_table tbody { color: [% css_colors.primary %]; text-wrap:normal; white-space:pre-wrap !important; @@ -1875,7 +1879,7 @@ a.dash-link:hover { text-decoration: underline !important; } vertical-align: top; [% END -%] } -.rdetail-author-div { +.rdetail-author-div, .course-instructor-div { padding-bottom: 10px; display: inline-block; } @@ -2654,7 +2658,7 @@ a.preflib_change { display: none; } -.rdetail_authors_div { +.rdetail_authors_div, .course_instructors_div { margin-bottom: 1em; } @@ -2996,14 +3000,17 @@ a.preflib_change { #main-content { margin: 0 1px; } - #rdetails_status thead { + #rdetails_status thead, + #course_material_table thead { display: none; } - #rdetails_status tr { + #rdetails_status tr, + #course_material_table tr { display: block; margin-top: 3px; } - #rdetails_status td { + #rdetails_status td, + #course_material_table td { display: block; padding: 1px; } @@ -3444,3 +3451,13 @@ label[for*=expert_] .carousel .glide__arrow--left { left: -5em; } +.archived_course { + color: [% css_colors.text_badnews %]; + font-weight: bold; +} +.course_details { + padding-top: 1em; +} +.course_details_div { + padding-bottom: 1em; +} \ No newline at end of file diff --git a/Open-ILS/src/templates/opac/parts/course/body.tt2 b/Open-ILS/src/templates/opac/parts/course/body.tt2 new file mode 100644 index 0000000000..cae56e2d1f --- /dev/null +++ b/Open-ILS/src/templates/opac/parts/course/body.tt2 @@ -0,0 +1,101 @@ +
+
+
+

+ [% l(ctx.course.name) %] ([% ctx.course.course_number %]) + [% IF ctx.course.is_archived == 't' %] + + This course is inactive. + + [% END %] +

+ [% IF ctx.instructors.size %] +
+ Course Instructors: + [%- FOR instructor IN ctx.instructors; + instructorString = ''; + IF instructor.pref_family_name; + instructorString = instructorString _ instructor.pref_family_name _ ', '; + ELSE; + instructorString = instructorString _ instructor.family_name _ ', '; + END; + IF instructor.pref_first_given_name; + instructorString = instructorString _ instructor.pref_first_given_name; + ELSE; + instructorString = instructorString _ instructor.first_given_name; + END; + instructorString = instructorString _ ' (' _ l(instructor.usr_role) _ ')'; %] + [% instructorString %]. + [% END %] +
+ [% END %] + +
+

[% l('Course Details') %]

+
+ [% l('Course Title') %]: + [% ctx.course.name %] +
+
+ [% l('Course Number') %]: + [% ctx.course.course_number %] +
+
+ [% l('Section Number') %]: + [% ctx.course.section_number %] +
+
+ [% + owning_lib = ctx.get_aou(ctx.course.owning_lib); + lib_url = ctx.get_org_setting(owning_lib.id, 'lib.info_url'); + prefer_external_url = ctx.get_org_setting(owning_lib.id, 'lib.prefer_external_url'); + UNLESS lib_url && prefer_external_url; + lib_url = mkurl(ctx.opac_root _ '/library/' _ owning_lib.shortname, {}, 1); + END; + %] + [% l('Owning Library') %]: + [% owning_lib.name %] +
+
+ + [%- UNLESS ctx.course.is_archived == 't' %] +
+

[% l('Course Materials') %]

+ + + + + + + + + + + + + + [% FOREACH copy_info IN ctx.course_materials %] + + + + + + + + + + [% END %] + +
LocationCall NumberTitleBarcodeRelationshipStatusShelving Location
[%- INCLUDE "opac/parts/library_name_link.tt2"; -%] + + + [% copy_info.call_number %] + + [% copy_info.title %] + + [% copy_info.barcode %][% copy_info.relationship %][% copy_info.status.name %][% copy_info.location.name %]
+
+ [% END %] +
+
+
-- 2.11.0