-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into fix-markdown-alignment
- Loading branch information
Showing
18 changed files
with
890 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const log = require('../log/clog'); | ||
const maxQuestions = 100; // number of questions per page | ||
const pageNum = 1; // pagination | ||
|
||
export default function loadDeckQuality(context, payload, done) { | ||
log.info(context); | ||
context.dispatch('UPDATE_MODULE_TYPE_SUCCESS', {moduleType: 'quality'}); | ||
|
||
// questions are also evaluated in the quality check, so let's fetch them | ||
payload.params.maxQ = payload.params.maxQ === undefined || parseInt(payload.params.maxQ) === 'NaN' ? maxQuestions : payload.params.maxQ; | ||
payload.params.pageNum = payload.params.pageNum === undefined || parseInt(payload.params.pageNum) === 'NaN' ? pageNum : payload.params.pageNum; | ||
|
||
context.service.read('questions.list', payload, {timeout: 20 * 1000}, (err, res) => { | ||
if (err) { | ||
log.error(context, {filepath: __filename}); | ||
context.executeAction(serviceUnavailable, payload, done); | ||
} else { | ||
context.dispatch('LOAD_CONTENT_QUESTIONS_SUCCESS', res); | ||
} | ||
|
||
done(); | ||
}); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
components/Deck/ContentModulesPanel/QualityPanel/CheckDescriptiveNames.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { connectToStores } from 'fluxible-addons-react'; | ||
import DeckViewStore from '../../../../stores/DeckViewStore'; | ||
import { FormattedMessage, defineMessages } from 'react-intl'; | ||
import { Accordion, Icon, Label, Message, List } from 'semantic-ui-react'; | ||
|
||
class CheckDescriptiveNames extends React.Component { | ||
constructor() { | ||
super(); | ||
|
||
this.state = { | ||
errors: [], | ||
}; | ||
|
||
this.maxWords = 10; | ||
this.minWords = 3; | ||
this.maxLength = 50; | ||
} | ||
|
||
componentDidMount() { | ||
this.runValidation(); | ||
} | ||
|
||
// rerun the validation when the decks are updated | ||
componentDidUpdate(prevProps) { | ||
if (this.props.DeckViewStore !== prevProps.DeckViewStore) { | ||
this.runValidation(); | ||
} | ||
} | ||
|
||
validateTitle = (title) => { | ||
if (!title) { | ||
return false; | ||
} | ||
const wordsAmount = title.split(' ').length; | ||
|
||
// check the amount of words in the title | ||
if (wordsAmount < this.minWords || wordsAmount > this.maxWords) { | ||
return false; | ||
} | ||
|
||
// check the amount of characters | ||
if (wordsAmount.length > this.maxLength) { | ||
return false; | ||
} | ||
|
||
return true; | ||
}; | ||
|
||
runValidation = () => { | ||
const deckTitle = this.props.DeckViewStore.deckData.title; | ||
let errors = []; | ||
|
||
if (!this.validateTitle(deckTitle)) { | ||
errors.push({ | ||
title: 'Deck title: ' + deckTitle, | ||
description: 'Deck title is not descriptive, change the name', | ||
}); | ||
} | ||
|
||
const slides = this.props.DeckViewStore.slidesData.children; | ||
|
||
if (slides && slides.length > 0) { | ||
for (const slide of slides) { | ||
if (!this.validateTitle(slide.title)) { | ||
errors.push({ | ||
title: 'Slide title: ' + slide.title, | ||
description: 'Slide name is not descriptive, change the name', | ||
}); | ||
} | ||
} | ||
} | ||
|
||
|
||
this.setState({ | ||
errors, | ||
}); | ||
}; | ||
|
||
render() { | ||
return ( | ||
<> | ||
<Accordion.Title active={this.props.activeIndex === this.props.index} index={this.props.index} onClick={this.props.handleClick}> | ||
<Icon name='dropdown' /> | ||
Short and descriptive names{' '} | ||
<Label color={this.state.errors.length > 0 ? 'red' : 'green'} horizontal> | ||
{this.state.errors.length > 0 ? this.state.errors.length + ' issues' : 'All good'} | ||
</Label> | ||
</Accordion.Title> | ||
<Accordion.Content active={this.props.activeIndex === this.props.index}> | ||
<Message color='blue'>Both the deck name and slide names should be short and descriptive</Message> | ||
<List divided relaxed> | ||
{this.state.errors.map((error, index) => ( | ||
<List.Item key={index}> | ||
<List.Icon name='file' size='large' verticalAlign='middle' /> | ||
<List.Content> | ||
<List.Header>{error.title}</List.Header> | ||
<List.Description>{error.description}</List.Description> | ||
</List.Content> | ||
</List.Item> | ||
))} | ||
</List> | ||
</Accordion.Content> | ||
</> | ||
); | ||
} | ||
} | ||
|
||
CheckDescriptiveNames.contextTypes = { | ||
intl: PropTypes.object.isRequired, | ||
}; | ||
|
||
CheckDescriptiveNames = connectToStores(CheckDescriptiveNames, [DeckViewStore], (context, props) => { | ||
return { | ||
DeckViewStore: context.getStore(DeckViewStore).getState(), | ||
}; | ||
}); | ||
|
||
export default CheckDescriptiveNames; |
76 changes: 76 additions & 0 deletions
76
components/Deck/ContentModulesPanel/QualityPanel/CheckHierarchicalDesign.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { connectToStores } from 'fluxible-addons-react'; | ||
import DeckViewStore from '../../../../stores/DeckViewStore'; | ||
import { FormattedMessage, defineMessages } from 'react-intl'; | ||
import { Accordion, Icon, Label, Message, List } from 'semantic-ui-react'; | ||
|
||
class CheckHierarchicalDesign extends React.Component { | ||
constructor() { | ||
super(); | ||
|
||
this.state = { | ||
error: false, | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
this.runValidation(); | ||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
if (this.props.DeckViewStore !== prevProps.DeckViewStore) { | ||
this.runValidation(); | ||
} | ||
} | ||
|
||
runValidation = () => { | ||
const contentItems = this.props.DeckViewStore.deckData.contentItems; | ||
let foundDeck = false; | ||
|
||
if (contentItems && contentItems.length > 0) { | ||
for (const item of contentItems) { | ||
if (item.kind === 'deck') { | ||
foundDeck = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
this.setState({ | ||
error: !foundDeck, | ||
}); | ||
}; | ||
|
||
render() { | ||
return ( | ||
<> | ||
<Accordion.Title active={this.props.activeIndex === this.props.index} index={this.props.index} onClick={this.props.handleClick}> | ||
<Icon name='dropdown' /> | ||
Hierarchical design{' '} | ||
<Label color={this.state.error ? 'red' : 'green'} horizontal> | ||
{this.state.error ? '1 issue' : 'All good'} | ||
</Label> | ||
</Accordion.Title> | ||
<Accordion.Content active={this.props.activeIndex === this.props.index}> | ||
<Message color='blue'>It is good practice to use subdecks to create a hierarchy in the slide structure</Message> | ||
<List divided relaxed> | ||
{this.state.error && <Message color='red'>No subdecks found, add a subdeck to improve the slide structure</Message>} | ||
</List> | ||
</Accordion.Content> | ||
</> | ||
); | ||
} | ||
} | ||
|
||
CheckHierarchicalDesign.contextTypes = { | ||
intl: PropTypes.object.isRequired, | ||
}; | ||
|
||
CheckHierarchicalDesign = connectToStores(CheckHierarchicalDesign, [DeckViewStore], (context, props) => { | ||
return { | ||
DeckViewStore: context.getStore(DeckViewStore).getState(), | ||
}; | ||
}); | ||
|
||
export default CheckHierarchicalDesign; |
Oops, something went wrong.