Skip to content

Commit

Permalink
Merge pull request #1258 from concord-consortium/187154175-researcher…
Browse files Browse the repository at this point in the history
…-assignments-ui

Implement read-only view of a class materials for researcher
  • Loading branch information
pjanik committed Mar 26, 2024
2 parents 6844898 + e7742cc commit bc3f9b5
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 18 deletions.
4 changes: 2 additions & 2 deletions rails/app/assets/javascripts/react-components.js

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion rails/app/views/portal/clazzes/materials.html.haml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#assignments-page

:javascript
PortalComponents.renderAssignments({classDataUrl: Portal.API_V1.class("#{@portal_clazz.id}")}, 'assignments-page')
PortalComponents.renderAssignments({
classDataUrl: Portal.API_V1.class("#{@portal_clazz.id}"),
readOnly: #{!current_user.has_full_access_to_student_data?(@portal_clazz)},
}, 'assignments-page')
14 changes: 12 additions & 2 deletions react-components/src/library/components/assigments/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,23 @@ export default class Assignments extends React.Component {
}

render () {
const { readOnly } = this.props
const { loading, clazz, offerings, offeringDetails } = this.state
if (loading) {
return null
}
return (
<div>
<ClassAssignments clazz={clazz} handleNewAssignment={this.handleNewAssignments} />
<OfferingsTable offerings={offerings} offeringDetails={offeringDetails} clazz={clazz}
onOfferingsReorder={this.onOfferingsReorder} onOfferingUpdate={this.onOfferingUpdate} requestOfferingDetails={this.requestOfferingDetails} />
<OfferingsTable
offerings={offerings}
offeringDetails={offeringDetails}
clazz={clazz}
readOnly={readOnly}
requestOfferingDetails={this.requestOfferingDetails}
onOfferingsReorder={this.onOfferingsReorder}
onOfferingUpdate={this.onOfferingUpdate}
/>
</div>
)
}
Expand All @@ -178,6 +186,8 @@ export default class Assignments extends React.Component {
Assignments.defaultProps = {
// classDataUrl is pretty much required. It can be set to any default value, as it depends on the current class.
classDataUrl: null,
// When user is not a class teacher, but e.g. a researcher, this component should be read-only.
readOnly: false,
// If initialData is not provided, component will use API (dataUrl) to get it.
initialClassData: null
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export default class OfferingRow extends React.Component {

onCheckboxUpdate (name, event) {
const { offering, onOfferingUpdate } = this.props
onOfferingUpdate(offering, name, event.target.checked)
if (onOfferingUpdate) {
onOfferingUpdate(offering, name, event.target.checked)
}
}

onDetailsToggle () {
Expand All @@ -36,14 +38,15 @@ export default class OfferingRow extends React.Component {

render () {
const { detailsVisible } = this.state
const { offering, offeringDetails, clazz } = this.props
const { offering, offeringDetails, clazz, readOnly } = this.props

return (
<div className={css.offering}>
<div>
<span className={css.iconCell}><span className={`${css.sortIcon} icon-sort`} /></span>
{ !readOnly && <span className={css.iconCell}><span className={`${css.sortIcon} icon-sort`} /></span> }
<span className={css.activityNameCell}>{ offering.name }</span>
<span className={css.checkboxCell}><input type='checkbox' checked={offering.active} onChange={this.onActiveUpdate} /></span>
<span className={css.checkboxCell}><input type='checkbox' checked={offering.locked} onChange={this.onLockedUpdate} /></span>
<span className={css.checkboxCell}><input type='checkbox' disabled={readOnly} checked={offering.active} onChange={this.onActiveUpdate} /></span>
<span className={css.checkboxCell}><input type='checkbox' disabled={readOnly} checked={offering.locked} onChange={this.onLockedUpdate} /></span>
<span className={css.detailsCell}><button className={'textButton adminOption'} onClick={this.onDetailsToggle}>{ this.detailsLabel }</button></span>
</div>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import css from './style.scss'

const SortableOffering = SortableElement(OfferingRow)

const SortableOfferings = SortableContainer(({ offerings, offeringDetails, onOfferingUpdate, requestOfferingDetails, clazz }) => {
const SortableOfferings = SortableContainer(({ readOnly, offerings, offeringDetails, onOfferingUpdate, requestOfferingDetails, clazz }) => {
const RowComponent = readOnly ? SortableOffering : OfferingRow
return (
<div className={css.offeringsTable}>
<div className={`${css.offeringsTable} ${readOnly ? css.readOnly : ''}`}>
<div className={css.headers}>
<span className={css.activityNameCell}>Name</span>
{/* Empty icon cell just to make sure that total width is correct */}
Expand All @@ -20,8 +21,8 @@ const SortableOfferings = SortableContainer(({ offerings, offeringDetails, onOff
</div>
{
offerings.map((offering, idx) =>
<SortableOffering key={offering.id} index={idx} offering={offering} offeringDetails={offeringDetails[offering.id]} clazz={clazz}
requestOfferingDetails={requestOfferingDetails} onOfferingUpdate={onOfferingUpdate} />)
<RowComponent key={offering.id} index={idx} offering={offering} offeringDetails={offeringDetails[offering.id]} clazz={clazz}
requestOfferingDetails={requestOfferingDetails} onOfferingUpdate={onOfferingUpdate} readOnly={readOnly} />)
}
</div>
)
Expand All @@ -30,14 +31,13 @@ const SortableOfferings = SortableContainer(({ offerings, offeringDetails, onOff
export default class OfferingsTable extends React.Component {
render () {
const shouldCancelStart = shouldCancelSorting([ css.sortIcon, css.activityNameCell ])

const { offerings, offeringDetails, onOfferingsReorder, onOfferingUpdate, requestOfferingDetails, clazz } = this.props
const { offerings, offeringDetails, onOfferingsReorder, onOfferingUpdate, requestOfferingDetails, clazz, readOnly } = this.props
if (offerings.length === 0) {
return <div className={css.noMaterials}>No materials have been assigned to this class.</div>
}
return (
<SortableOfferings offerings={offerings} offeringDetails={offeringDetails} clazz={clazz} onSortEnd={onOfferingsReorder}
shouldCancelStart={shouldCancelStart} distance={3}
shouldCancelStart={shouldCancelStart} distance={3} readOnly={readOnly}
onOfferingUpdate={onOfferingUpdate} requestOfferingDetails={requestOfferingDetails} />
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import '../../../shared/styles/mixins/_mixins.scss';
@import '../../../shared/styles/variables/_colors.scss';
@import '../../../shared/styles/variables/_variables.scss';

.classAssignments {

header {
Expand Down Expand Up @@ -32,7 +33,7 @@
&:active {
background: $col-lightblue;
border-color: $col-lightblue;
color: $white;
color: $white;
}
}
ul {
Expand Down Expand Up @@ -134,6 +135,10 @@
vertical-align: middle;
}

.readOnly .activityNameCell {
cursor: default;
}

.checkboxCell {
display: inline-block;
flex: 1;
Expand Down

0 comments on commit bc3f9b5

Please sign in to comment.