add steps component to canvas
fixes COMMS-1724 COMMS-1723 Test Plan: - Open up assignments 2.0 student view - notice steps component is integrated and accessible Change-Id: Ie5a381a74162d8dd68a521bc7d8d8d4a4decea83 Reviewed-on: https://gerrit.instructure.com/172987 Reviewed-by: Landon Gilbert-Bland <lbland@instructure.com> Reviewed-by: Aaron Hsu <ahsu@instructure.com> Tested-by: Jenkins QA-Review: Steven Burnett <sburnett@instructure.com> Product-Review: Steven Burnett <sburnett@instructure.com>
This commit is contained in:
parent
c8dd356848
commit
0c0af583e6
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import StepItem from '../index'
|
||||
import $ from 'jquery'
|
||||
|
||||
beforeAll(() => {
|
||||
const found = document.getElementById('fixtures')
|
||||
if (!found) {
|
||||
const fixtures = document.createElement('div')
|
||||
fixtures.setAttribute('id', 'fixtures')
|
||||
document.body.appendChild(fixtures)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById('fixtures'))
|
||||
})
|
||||
|
||||
it('should render', async () => {
|
||||
ReactDOM.render(<StepItem label={() => {}} />, document.getElementById('fixtures'))
|
||||
const component = $('.step-item-step')
|
||||
expect(component).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should render complete status', async () => {
|
||||
ReactDOM.render(
|
||||
<StepItem status="complete" label="Test label" />,
|
||||
document.getElementById('fixtures')
|
||||
)
|
||||
const component = $('.step-item-step')
|
||||
expect(component.hasClass('complete')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should render in-progress status', async () => {
|
||||
ReactDOM.render(
|
||||
<StepItem status="in-progress" label="Test label" />,
|
||||
document.getElementById('fixtures')
|
||||
)
|
||||
const component = $('.step-item-step')
|
||||
expect(component.hasClass('in-progress')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should render label correctly', async () => {
|
||||
ReactDOM.render(
|
||||
<StepItem status="complete" label={status => `progress 2 ${status}`} />,
|
||||
document.getElementById('fixtures')
|
||||
)
|
||||
const component = $('.step-item-step')
|
||||
expect(component.text()).toEqual('progress 2 complete')
|
||||
})
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import IconCheckMark from '@instructure/ui-icons/lib/Solid/IconCheckMark'
|
||||
import {omitProps} from '@instructure/ui-utils/lib/react/passthroughProps'
|
||||
import classNames from 'classnames'
|
||||
import px from '@instructure/ui-utils/lib/px'
|
||||
|
||||
class StepItem extends Component {
|
||||
static propTypes = {
|
||||
status: PropTypes.oneOf(['complete', 'in-progress']),
|
||||
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string]).isRequired,
|
||||
icon: PropTypes.element,
|
||||
pinSize: PropTypes.string,
|
||||
placement: PropTypes.oneOf(['first', 'last', 'interior'])
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
placement: 'interior'
|
||||
}
|
||||
|
||||
renderIcon() {
|
||||
const Icon = this.props.icon
|
||||
if (!Icon && this.props.status === 'complete') {
|
||||
return <IconCheckMark color="primary-inverse" />
|
||||
} else if (typeof this.props.icon === 'function') {
|
||||
return <Icon />
|
||||
} else if (Icon) {
|
||||
return Icon
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
pinSize = () => {
|
||||
if (this.props.status === 'complete') {
|
||||
return Math.round(px(this.props.pinSize) / 1.5)
|
||||
} else if (this.props.status === 'in-progress') {
|
||||
return px(this.props.pinSize)
|
||||
} else {
|
||||
return Math.round(px(this.props.pinSize) / 2.25)
|
||||
}
|
||||
}
|
||||
|
||||
renderLabel = () => {
|
||||
const {label, status} = this.props
|
||||
if (typeof label === 'function') {
|
||||
return label(status)
|
||||
} else {
|
||||
return label
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {status, placement} = this.props
|
||||
|
||||
const classes = {
|
||||
'step-item-step': true,
|
||||
[status]: true,
|
||||
[`placement--${placement}`]: true
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={classNames(classes)} {...omitProps(this.props, StepItem.propTypes)}>
|
||||
<span
|
||||
className="pinLayout"
|
||||
style={{
|
||||
height: px(this.props.pinSize)
|
||||
}}
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style={{
|
||||
width: `${this.pinSize()}px`,
|
||||
height: `${this.pinSize()}px`
|
||||
}}
|
||||
className="step-item-pin"
|
||||
>
|
||||
{this.renderIcon()}
|
||||
</span>
|
||||
</span>
|
||||
<span className="step-item-label">{this.renderLabel()}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default StepItem
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import Steps from '../index'
|
||||
import StepItem from '../StepItem'
|
||||
import $ from 'jquery'
|
||||
|
||||
beforeAll(() => {
|
||||
const found = document.getElementById('fixtures')
|
||||
if (!found) {
|
||||
const fixtures = document.createElement('div')
|
||||
fixtures.setAttribute('id', 'fixtures')
|
||||
document.body.appendChild(fixtures)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById('fixtures'))
|
||||
})
|
||||
|
||||
it('should render', async () => {
|
||||
ReactDOM.render(<Steps />, document.getElementById('fixtures'))
|
||||
const element = $('[data-test-id="assignment-2-step-index"]')
|
||||
expect(element).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should render with StepItems', async () => {
|
||||
ReactDOM.render(
|
||||
<Steps label="Settings">
|
||||
<StepItem label={status => `Phase one ${status}`} status="complete" />
|
||||
<StepItem label={status => `Phase two ${status}`} status="in-progress" />
|
||||
<StepItem label="Phase three" />
|
||||
</Steps>,
|
||||
document.getElementById('fixtures')
|
||||
)
|
||||
const element = $('li')
|
||||
expect(element).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('should render aria-current for the item that is in progress', async () => {
|
||||
ReactDOM.render(
|
||||
<Steps label="Settings">
|
||||
<StepItem label={status => `Phase one ${status}`} status="complete" />
|
||||
<StepItem label={status => `Phase two ${status}`} status="in-progress" />
|
||||
<StepItem label="Phase three" />
|
||||
</Steps>,
|
||||
document.getElementById('fixtures')
|
||||
)
|
||||
|
||||
const items = $('li')
|
||||
expect(items[0].getAttribute('aria-current')).toEqual('false')
|
||||
expect(items[1].getAttribute('aria-current')).toEqual('true')
|
||||
expect(items[2].getAttribute('aria-current')).toEqual('false')
|
||||
})
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react'
|
||||
|
||||
import View from '@instructure/ui-layout/lib/components/View'
|
||||
|
||||
import {omitProps} from '@instructure/ui-utils/lib/react/passthroughProps'
|
||||
import safeCloneElement from '@instructure/ui-utils/lib/react/safeCloneElement'
|
||||
|
||||
class Steps extends Component {
|
||||
static propTypes = {
|
||||
children: props => {
|
||||
const inProgressArr = []
|
||||
for (const child in props.children) {
|
||||
if (!props.children[child]) {
|
||||
continue
|
||||
}
|
||||
if (props.children[child].props.status === 'in-progress') {
|
||||
inProgressArr.push(props.children[child])
|
||||
}
|
||||
if (props.children[child].type.displayName !== 'StepItem') {
|
||||
new Error("Warning Step has children that aren't StepItem components")
|
||||
}
|
||||
}
|
||||
if (inProgressArr.length > 1) {
|
||||
new Error('Warning: Step has two StepItems with a status of in-progress')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static findInProgressChild(element) {
|
||||
return element.props.status === 'in-progress'
|
||||
}
|
||||
|
||||
calculateProgressionScale = children => {
|
||||
const inProgressIndex = children.findIndex(Steps.findInProgressChild)
|
||||
if (inProgressIndex !== -1) {
|
||||
const successProgresssionX = inProgressIndex / (children.length - 1)
|
||||
return successProgresssionX
|
||||
} else {
|
||||
let completeIndex = 0
|
||||
for (let i = children.length - 1; i !== 0; i--) {
|
||||
if (children[i].props.status === 'complete') {
|
||||
completeIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return completeIndex / (children.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
handlePlacement(numSteps, index) {
|
||||
const step = index + 1
|
||||
|
||||
if (step === 1) {
|
||||
return 'first'
|
||||
} else if (step === numSteps) {
|
||||
return 'last'
|
||||
} else {
|
||||
return 'interior'
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let progressionScale = 0
|
||||
|
||||
let filteredChildren
|
||||
|
||||
if (this.props.children) {
|
||||
filteredChildren = this.props.children.filter(prop => prop !== null)
|
||||
progressionScale = this.calculateProgressionScale(filteredChildren)
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
{...omitProps(this.props, {...Steps.propTypes, ...View.propTypes})}
|
||||
margin={this.props.margin}
|
||||
data-test-id="assignment-2-step-index"
|
||||
as="div"
|
||||
>
|
||||
<div className="progressionContainer" aria-hidden="true">
|
||||
<span className="progression" />
|
||||
<span
|
||||
style={{transform: `scaleX(${progressionScale})`}}
|
||||
className="completeProgression"
|
||||
/>
|
||||
</div>
|
||||
<ol className="steps">
|
||||
{React.Children.map(filteredChildren, (child, index) => (
|
||||
<li
|
||||
className="step"
|
||||
aria-current={child.props.status === 'in-progress' ? 'true' : 'false'}
|
||||
>
|
||||
{safeCloneElement(child, {
|
||||
pinSize: '32px',
|
||||
placement: this.handlePlacement(filteredChildren.length, index)
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Steps
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import I18n from 'i18n!assignments_2_student_header_date_title'
|
||||
|
||||
import React from 'react'
|
||||
import Steps from '../../shared/Steps'
|
||||
import StepItem from '../../shared/Steps/StepItem'
|
||||
|
||||
function StepContainer() {
|
||||
return (
|
||||
<div className="steps-container">
|
||||
<Steps>
|
||||
<StepItem label={I18n.t('Avaible: ')} status="complete" />
|
||||
<StepItem
|
||||
status="in-progress"
|
||||
label={status =>
|
||||
status && status !== 'in-progress' ? I18n.t('Uploaded') : I18n.t('Upload')
|
||||
}
|
||||
/>
|
||||
<StepItem
|
||||
label={status =>
|
||||
status && status !== 'in-progress' ? I18n.t('Submitted') : I18n.t('Submit')
|
||||
}
|
||||
/>
|
||||
<StepItem
|
||||
label={status =>
|
||||
status && status !== 'in-progress' ? I18n.t('Graded') : I18n.t('Not Graded')
|
||||
}
|
||||
/>
|
||||
</Steps>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(StepContainer)
|
|
@ -22,6 +22,7 @@ import Flex, {FlexItem} from '@instructure/ui-layout/lib/components/Flex'
|
|||
import AssignmentGroupModuleNav from './AssignmentGroupModuleNav'
|
||||
import StudentDateTitle from './StudentDateTitle'
|
||||
import PointsDisplay from './PointsDisplay'
|
||||
import StepContainer from './StepContainer'
|
||||
|
||||
function StudentHeader() {
|
||||
return (
|
||||
|
@ -30,7 +31,7 @@ function StudentHeader() {
|
|||
module={{name: 'Egypt Economy Research Module: Week 1', link: 'www.google.com'}}
|
||||
assignmentGroup={{name: 'Research Assignments', link: 'www.yahoo.com'}}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex margin="0 0 xx-large 0">
|
||||
<FlexItem grow>
|
||||
<StudentDateTitle
|
||||
title="Egypt Economy Research"
|
||||
|
@ -41,6 +42,7 @@ function StudentHeader() {
|
|||
<PointsDisplay receivedPoints={null} possiblePoints={32} />
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
<StepContainer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@import "base/environment";
|
||||
@import "pages/assignments2_student/steps.scss";
|
||||
@import "pages/assignments2_student/step_items.scss";
|
||||
@import "pages/assignments2_student/student_header.scss";
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@keyframes pulse {
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.step-item-step {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.step-item-label {
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.pinLayout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.step-item-pin {
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #8B969E;
|
||||
border-radius: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.complete {
|
||||
.step-item-pin {
|
||||
font-size: 0.75rem; /* sets the icon size bc we need smaller than theme can provide */
|
||||
background: #00AC18;
|
||||
}
|
||||
}
|
||||
|
||||
.in-progress {
|
||||
.step-item-label {
|
||||
font-weight: 700;
|
||||
color: #2D3B45;
|
||||
}
|
||||
|
||||
.step-item-pin {
|
||||
background: #FFFFFF;
|
||||
border: 0.125rem solid #00AC18;
|
||||
|
||||
/* if pin is complete, it pulses - should we make this an opt-in prop? */
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: -0.5rem;
|
||||
bottom: -0.5rem;
|
||||
left: -0.5rem; /* stylelint-disable-line property-blacklist */
|
||||
right: -0.5rem; /* stylelint-disable-line property-blacklist */
|
||||
border-width: 0.125rem;
|
||||
border-style: solid;
|
||||
border-color: #00AC18;
|
||||
border-radius: 100%;
|
||||
|
||||
/* set initial properties to animate in the pulse animation */
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
|
||||
/* animation */
|
||||
animation-name: pulse;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.placement--first {
|
||||
.pinLayout {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.step-item-label {
|
||||
text-align: start;
|
||||
}
|
||||
}
|
||||
|
||||
.placement--last {
|
||||
.pinLayout {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.step-item-label {
|
||||
text-align: end;
|
||||
}
|
||||
}
|
||||
|
||||
.placement--interior {
|
||||
.pinLayout {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.step-item-label {
|
||||
text-align: center;
|
||||
margin-inline-start: auto;
|
||||
margin-inline-end: auto;
|
||||
max-width: 50%; /* makes all text labels equal width (first and last are reduced by flex: 0.5 rule above) */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.steps {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step {
|
||||
margin: -32px 0 0;
|
||||
padding: 0;
|
||||
min-width: 0.0625rem;
|
||||
flex: 1;
|
||||
|
||||
&:last-of-type {
|
||||
flex: 0.5;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
flex: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.progressionContainer {
|
||||
position: relative;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.progression {
|
||||
flex: 1;
|
||||
height: 0.0625rem;
|
||||
background: #8B969E;
|
||||
}
|
||||
|
||||
.completeProgression {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 0.125rem;
|
||||
offset-inline-start: 0;
|
||||
top: calc(50% - (0.125rem / 2));
|
||||
background: #00AC18;
|
||||
transition: transform 0.2s;
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
[dir="rtl"] .completeProgression {
|
||||
transform-origin: right center;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.steps-container {
|
||||
margin-bottom: 60px;
|
||||
}
|
|
@ -20,7 +20,10 @@
|
|||
<% if @context.root_account.feature_enabled?(:assignments_2) && value_to_boolean(params[:assignments_2]) %>
|
||||
<% if can_do(@context, @current_user, :read_as_admin) %>
|
||||
<% js_bundle :assignments_2_show_teacher %>
|
||||
|
||||
<% else %>
|
||||
|
||||
<% css_bundle :assignments_2_student %>
|
||||
<% js_bundle :assignments_2_show_student %>
|
||||
<% end %>
|
||||
<div id="assignments_2"></div>
|
||||
|
|
Loading…
Reference in New Issue