Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added rubric doc url to external activities [PT-184748744] #1204

Merged
merged 1 commit into from
Jul 24, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ export class ExternalActivities {
@Column("varchar", { name: "rubric_url", nullable: true, length: 255 })
rubricUrl: string | null;

@Column("varchar", { name: "rubric_doc_url", nullable: true, length: 255 })
rubricDocUrl: string | null;

@Column("tinyint", {
name: "saves_student_data",
nullable: true,
Expand Down
4 changes: 2 additions & 2 deletions rails/app/assets/javascripts/react-components.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion rails/app/controllers/external_activities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,6 @@ def external_activity_strong_params(params)
:material_type, :name, :offerings_count, :popup, :print_url, :publication_status, :rubric_url,
:save_path, :saves_student_data, :short_description, :student_report_enabled, :teacher_copyable,
:teacher_guide_url, :teacher_resources_url, :template_id, :template_type, :thumbnail_url, :tool_id,
:url, :user_id)
:url, :user_id, :rubric_doc_url)
end
end
2 changes: 2 additions & 0 deletions rails/app/models/api/v1/offering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def initialize(student, offering, protocol, host_with_port)
attribute :material_type, String
attribute :report_url, String
attribute :rubric_url, String
attribute :rubric_doc_url, String
attribute :preview_url, String
attribute :has_teacher_edition, Boolean
# 2019-07-16 NP: TODO: deprecate `external_report` in favor of `external_reports`
Expand Down Expand Up @@ -89,6 +90,7 @@ def initialize(offering, protocol, host_with_port, current_user, additional_exte
self.has_teacher_edition = runnable.has_teacher_edition
self.reportable = offering.reportable?
self.rubric_url = runnable.respond_to?(:rubric_url) ? runnable.rubric_url : nil
self.rubric_doc_url = runnable.respond_to?(:rubric_doc_url) ? runnable.rubric_doc_url : nil
self.report_url = offering.reportable? ? report_portal_offering_url(id: offering.id, protocol: protocol, host: host_with_port) : nil
self.preview_url = run_url_for(runnable, preview_params(current_user, {protocol: protocol, host: host_with_port}))
# 2019-07-16 NP: TODO: deprecate `external_report` in favor of `external_reports`
Expand Down
6 changes: 6 additions & 0 deletions rails/app/views/external_activities/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,14 @@
- else
= f.check_box :has_teacher_edition, :disabled => true
This activity has a teacher edition.
= field_set_tag t('authoring.rubric_doc_url_label') do
= f.text_field :rubric_doc_url, :size => 60
%br
This is the URL to the human-readable rubric document.
= field_set_tag t('authoring.rubric_url_label') do
= f.text_field :rubric_url, :size => 60
%br
This is the URL to the machine-readable rubric data.
= field_set_tag 'Thumbnail image URL (300 x 250 px)' do
= f.text_field :thumbnail_url, :size => 60
= field_set_tag 'Feature On Landing Page' do
Expand Down
3 changes: 2 additions & 1 deletion rails/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ en:
external_report_label: External Reporting
external_report_description: Specify additional report links to be shown to teachers in the offering view. Unless you know what you are doing selecting none is recommended.
report_client: Report Auth Client
rubric_url_label: Rubric (URL)
rubric_url_label: Rubric JSON (URL)
rubric_doc_url_label: Rubric Document (URL)
short_description_description: Shown in search results, student listings, and used as a fallback for long descrption. It is recommended that every activity has this value provided.
long_description_description: Shown in places where activity details are vible (e.g. STEM Resource finder lightbox). Uses Short Description as a fallback.
long_description_for_teachers_description: Variant of Long Description visible only for teachers. Uses Long Description as a fallback.
Expand Down
5 changes: 5 additions & 0 deletions rails/db/migrate/20230720110611_add_rubric_doc_url.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddRubricDocUrl < ActiveRecord::Migration[6.1]
def change
add_column :external_activities, :rubric_doc_url, :string
end
end
3 changes: 2 additions & 1 deletion rails/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2023_03_20_192316) do
ActiveRecord::Schema.define(version: 2023_07_20_110611) do

create_table "access_grants", id: :integer, charset: "utf8", force: :cascade do |t|
t.string "code"
Expand Down Expand Up @@ -265,6 +265,7 @@
t.text "teacher_resources_url"
t.boolean "teacher_copyable"
t.text "legacy_lara_url"
t.string "rubric_doc_url"
t.index ["is_featured", "publication_status"], name: "featured_public"
t.index ["publication_status"], name: "pub_status"
t.index ["save_path"], name: "index_external_activities_on_save_path"
Expand Down
10 changes: 10 additions & 0 deletions rails/lib/materials/data_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,16 @@ def links_for_material( material,
end
end

if material.respond_to?(:rubric_doc_url) && !material.rubric_doc_url.blank?
if current_visitor.portal_teacher || current_visitor.has_role?('admin','manager')
links[:rubric_doc] = {
text: "Rubric",
target: "_blank",
url: material.rubric_doc_url
}
end
end

if policy(material).edit?
links[:edit] = {
text: "(portal settings)",
Expand Down
11 changes: 8 additions & 3 deletions rails/spec/libs/materials/data_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class DataHelpersTestController < ApplicationController
is_locked: false,
teacher_copyable: true,
teacher_resources_url: host + '/teacher-resources',
teacher_guide_url: host + '/teacher-guide'
teacher_guide_url: host + '/teacher-guide',
rubric_doc_url: host + '/rubric-doc'
)
}
let(:materials) { [material_a] }
Expand Down Expand Up @@ -159,22 +160,26 @@ class DataHelpersTestController < ApplicationController
expect(external_edit_iframe[:url]).not_to be_empty
end

it "should return values for teacher resource and teacher guide if a teacher is logged in" do
it "should return values for teacher resource, teacher guide and rubric if a teacher is logged in" do
sign_in teacher_user.user
links = controller.send(:links_for_material, material_a)
teacher_resources = links[:teacher_resources]
teacher_guide = links[:teacher_guide]
rubric_doc = links[:rubric_doc]
expect(teacher_resources).not_to be_empty
expect(teacher_guide).not_to be_empty
expect(rubric_doc).not_to be_empty
end

it "should not return values for teacher resource and teacher guide to guests" do
it "should not return values for teacher resource, teacher guide and rubric to guests" do
sign_in guest
links = controller.send(:links_for_material, material_a)
teacher_resources = links[:teacher_resources]
teacher_guide = links[:teacher_guide]
rubric_doc = links[:rubric_doc]
expect(teacher_resources).to be_nil
expect(teacher_guide).to be_nil
expect(rubric_doc).to be_nil
end
end

Expand Down
3 changes: 3 additions & 0 deletions react-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
},
"modulePaths": [
"src/library"
],
"setupFiles": [
"./setup-jest-mock.js"
]
},
"repository": {
Expand Down
2 changes: 2 additions & 0 deletions react-components/setup-jest-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// mock google tag manager
global.gtag = jest.fn();
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ const BrowsePage = Component({
})
},

handleRubricDocClick: function (e) {
const resource = this.state.resource
gtag('event', 'click', {
'category': 'Browse Page - Rubric Doc Link',
'resource': resource.name
})
},

handleAddToCollectionClick: function (e) {
const resource = this.state.resource
gtag('event', 'click', {
Expand Down Expand Up @@ -199,6 +207,7 @@ const BrowsePage = Component({
<>
{links.assign_material ? <a id={'assign-button'} className='portal-pages-secondary-button' href={`javascript: ${links.assign_material.onclick}`} onClick={this.handleAssignClick}>{links.assign_material.text}</a> : null}
{Portal.currentUser.isTeacher && resource.has_teacher_edition ? <a className='teacherEditionLink portal-pages-secondary-button' href={MakeTeacherEditionLink(resource.external_url)} target='_blank' onClick={this.handleTeacherEditionClick}>Teacher Edition</a> : null}
{links.rubric_doc ? <a className='portal-pages-secondary-button' href={links.rubric_doc.url} target='_blank' onClick={this.handleRubricDocClick}>{links.rubric_doc.text}</a> : null}
{links.teacher_resources ? <a className='teacherResourcesLink portal-pages-secondary-button' href={links.teacher_resources.url} target='_blank' onClick={this.handleTeacherResourcesClick}>{links.teacher_resources.text}</a> : null}
{links.assign_collection ? <a className='portal-pages-secondary-button' href={`${links.assign_collection.url}`} onClick={this.handleAddToCollectionClick} target='_blank'>{links.assign_collection.text}</a> : null}
{links.teacher_guide ? <a className='portal-pages-secondary-button' href={links.teacher_guide.url} target='_blank' onClick={this.handleTeacherGuideClick}>{links.teacher_guide.text}</a> : null}
Expand Down
9 changes: 9 additions & 0 deletions react-components/src/library/components/resource-lightbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ var ResourceLightbox = Component({
})
},

handleRubricDocClick: function (e) {
const resource = this.state.resource
gtag('event', 'click', {
'category': 'Rubric Doc Link',
'resource': resource.name
})
},

handleAddToCollectionClick: function (e) {
const resource = this.state.resource
gtag('event', 'click', {
Expand Down Expand Up @@ -380,6 +388,7 @@ var ResourceLightbox = Component({
return (
<span>
{Portal.currentUser.isTeacher && resource.has_teacher_edition ? <a className='teacherEditionLink portal-pages-secondary-button' href={MakeTeacherEditionLink(resource.external_url)} target='_blank' onClick={this.handleTeacherEditionClick}>Teacher Edition</a> : null}
{links.rubric_doc ? <a className='portal-pages-secondary-button' href={links.rubric_doc.url} target='_blank' onClick={this.handleRubricDocClick}>{links.rubric_doc.text}</a> : null}
{links.teacher_resources && showTeacherResourcesButton ? <a className='teacherResourcesLink portal-pages-secondary-button' href={links.teacher_resources.url} target='_blank' onClick={this.handleTeacherResourcesClick}>{links.teacher_resources.text}</a> : null}
{links.assign_material ? <a id={'assign-button'} className='portal-pages-secondary-button' href={`javascript: ${links.assign_material.onclick}`} onClick={this.handleAssignClick}>{links.assign_material.text}</a> : null}
{links.assign_collection ? <a className='portal-pages-secondary-button' href={`${links.assign_collection.url}`} onClick={this.handleAddToCollectionClick} target='_blank'>{links.assign_collection.text}</a> : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export default class SMaterialInfo extends React.Component {
if (material.links.teacher_guide) {
links.push(material.links.teacher_guide)
}
if (material.links.rubric_doc) {
links.push(material.links.rubric_doc)
}
if (material.material_type !== 'Collection') {
if (material.links.assign_material) {
links.push(material.links.assign_material)
Expand Down
12 changes: 12 additions & 0 deletions react-components/src/library/components/stem-finder-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ const StemFinderResult = Component({
})
},

handleRubricDocClick: function (e) {
const { resource } = this.props
gtag('event', 'click', {
'category': 'Resource Rubric Doc Button',
'resource': resource.name
})
},

handleAssignClick: function (e) {
const { resource } = this.props
gtag('event', 'click', {
Expand Down Expand Up @@ -264,6 +272,9 @@ const StemFinderResult = Component({
const teacherResourcesLink = resource.links.teacher_resources && Portal.currentUser.isTeacher
? <a href={resource.links.teacher_resources.url} target='_blank' rel='noopener' onClick={this.handleTeacherResourcesClick}>{resource.links.teacher_resources.text}</a>
: null
const rubricDocLink = resource.links.rubric_doc && Portal.currentUser.isTeacher
? <a href={resource.links.rubric_doc.url} target='_blank' rel='noopener' onClick={this.handleRubricDocClick}>{resource.links.rubric_doc.text}</a>
: null
const assignCollectionLink = resource.links.assign_collection && (Portal.currentUser.isAdmin || Portal.currentUser.isManager)
? <a href={resource.links.assign_collection.url} target='_blank' onClick={this.handleAddToCollectionClick}>{resource.links.assign_collection.text}</a>
: null
Expand All @@ -275,6 +286,7 @@ const StemFinderResult = Component({
<>
{assignLink}
{teacherEditionLink}
{rubricDocLink}
{teacherGuideLink}
{teacherResourcesLink}
{editLink}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@ Enzyme.configure({adapter: new Adapter()})

// form uses Portal global
global.Portal = {
currentUser: {
isAdmin: false,
},
API_V1: {
EXTERNAL_RESEARCHER_REPORT_LEARNER_QUERY: 'http://query-test.concord.org'
}
}

describe('LearnerReportForm', () => {
const externalReports = [{url: 'url1', label: 'label1'}, {url: 'url2', label: 'label2'}]
const externalReports = [{url: 'url1', name: 'first', label: 'label1'}, {url: 'url2', name: 'second', label: 'label2'}]
const wrapper = Enzyme.shallow(
<LearnerReportForm externalReports={externalReports} />
)

it('renders all the report buttons', () => {
expect(wrapper.html()).toEqual(expect.stringContaining('Usage Report'))
expect(wrapper.html()).toEqual(expect.stringContaining('Details Report'))
expect(wrapper.html()).toEqual(expect.stringContaining('Arg Block Report'))
})

it('renders custom external report buttons', () => {
expect(wrapper.find(ExternalReportButton).length).toEqual(2)
expect(wrapper.find({reportUrl: 'url1', label: 'label1'}).length).toEqual(1)
Expand All @@ -37,7 +34,7 @@ describe('LearnerReportForm', () => {
it('renders filter forms', () => {
expect(wrapper.text()).toEqual(expect.stringContaining('Schools'))
expect(wrapper.text()).toEqual(expect.stringContaining('Teachers'))
expect(wrapper.text()).toEqual(expect.stringContaining('Runnables'))
expect(wrapper.text()).toEqual(expect.stringContaining('Resources'))
expect(wrapper.text()).toEqual(expect.stringContaining('Permission forms'))
expect(wrapper.find(Select).length).toEqual(4)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,6 @@ describe('When I try to render a student roster', () => {
it("should render with default parameters", () => {
const studentRoster = Enzyme.shallow(<StudentRoster canEdit={true} students={students} otherStudents={otherStudents} />);
expect(studentRoster.html()).toBe(pack(`
<div class="header">
<div class="search">
<div class="select">
<select id="student_id_selector">
<option selected="" value="0">Select registered student ...</option>
<option value="3">Student 3 (s3)</option>
<option value="4">Student 4 (s4)</option>
</select>
</div>
<div>
<button disabled="">Add</button>
</div>
</div>
<div class="or">
or
</div>
<div>
<span class="link" role="link">Register &amp; Add New Student</span>
</div>
</div>
<table class="table">
<tbody>
<tr>
Expand All @@ -82,8 +62,7 @@ describe('When I try to render a student roster', () => {
<td>1</td>
<td class="hide_in_print">
<span class="link" role="link">Remove Student</span>
<span class="link" role="link">Change Password</span>
</td>
<span class="link" role="link">Change Password</span></td>
</tr>
<tr>
<td>Student 2</td>
Expand All @@ -92,8 +71,7 @@ describe('When I try to render a student roster', () => {
<td>2</td>
<td class="hide_in_print">
<span class="link" role="link">Remove Student</span>
<span class="link" role="link">Change Password</span>
</td>
<span class="link" role="link">Change Password</span></td>
</tr>
</tbody>
</table>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ describe('When I try to render search material info', () => {
url: "http://example.com/teacher_guide",
text: "teacher_guide text"
},
rubric_doc: {
url: "http://example.com/rubric_doc",
text: "rubric_doc text"
},
assign_material: {
url: "http://example.com/assign_material",
text: "assign_material text"
Expand Down Expand Up @@ -134,6 +138,9 @@ describe('When I try to render search material info', () => {
<div style="float:right;margin-right:5px">
<a href="http://example.com/teacher_guide" class="button">teacher_guide text</a>
</div>
<div style="float:right;margin-right:5px">
<a href="http://example.com/rubric_doc" class="button">rubric_doc text</a>
</div>
<div style="float:right;margin-right:5px">
<a href="http://example.com/assign_material" class="button">assign_material text</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ Enzyme.configure({adapter: new Adapter()})

// form uses Portal global
global.Portal = {
currentUser: {
isAdmin: false,
},
API_V1: {
EXTERNAL_RESEARCHER_REPORT_LEARNER_QUERY: 'http://query-test.concord.org'
}
}

describe('UserReportForm', () => {
const externalReports = [{url: 'url1', label: 'label1'}, {url: 'url2', label: 'label2'}]
const externalReports = [{url: 'url1', name: 'first', label: 'label1'}, {url: 'url2', name: 'second', label: 'label2'}]
const wrapper = Enzyme.shallow(
<UserReportForm externalReports={externalReports} />
)
Expand All @@ -31,7 +34,7 @@ describe('UserReportForm', () => {
it('renders filter forms', () => {
expect(wrapper.text()).toEqual(expect.stringContaining('Teachers'))
expect(wrapper.text()).toEqual(expect.stringContaining('Cohorts'))
expect(wrapper.text()).toEqual(expect.stringContaining('Runnables'))
expect(wrapper.text()).toEqual(expect.stringContaining('Resources'))
expect(wrapper.find(Select).length).toEqual(3)

expect(wrapper.text()).toEqual(expect.stringContaining('Earliest date'))
Expand Down