Skip to content

Commit

Permalink
Merge pull request #36786 from code-dot-org/dtl_candidate_47d176a2
Browse files Browse the repository at this point in the history
  • Loading branch information
deploy-code-org committed Sep 16, 2020
2 parents a0be8f1 + 47d176a commit 1812d92
Show file tree
Hide file tree
Showing 47 changed files with 2,306 additions and 323 deletions.
40 changes: 3 additions & 37 deletions .drone.yml
@@ -1,5 +1,6 @@
---
kind: pipeline
type: docker
name: unit

clone:
Expand All @@ -15,24 +16,6 @@ steps:
- git remote set-branches --add origin $DRONE_TARGET_BRANCH
- git fetch --depth 100 origin $DRONE_TARGET_BRANCH

- name: verify-pr
image: wjordan/code-dot-org:2020-09-10
pull: always
commands:
- |
if [ -z "$DRONE_PULL_REQUEST" ]; then
echo "Not a pull request."
exit 0
fi
# Check to see if PR is from fork. If so, exit, as the test run provides access to secrets.
- head_repo=$(curl -s "https://api.github.com/repos/code-dot-org/code-dot-org/pulls/$DRONE_PULL_REQUEST" | jq .head.repo.full_name)
- echo $head_repo
- |
if [ "$head_repo" != '"code-dot-org/code-dot-org"' ]; then
echo "Pull request is from fork $head_repo; exiting."
exit 1
fi
- name: restore-cache
image: plugins/s3-cache
settings:
Expand Down Expand Up @@ -100,6 +83,7 @@ trigger:

---
kind: pipeline
type: docker
name: ui

clone:
Expand All @@ -126,24 +110,6 @@ steps:
- git config user.email "drone-fake-user@code.org"
- git merge origin/$DRONE_TARGET_BRANCH

- name: verify-pr
image: wjordan/code-dot-org:2020-09-10
pull: always
commands:
- |
if [ -z "$DRONE_PULL_REQUEST" ]; then
echo "Not a pull request."
exit 0
fi
# Check to see if PR is from fork. If so, exit, as the test run provides access to secrets.
- head_repo=$(curl -s "https://api.github.com/repos/code-dot-org/code-dot-org/pulls/$DRONE_PULL_REQUEST" | jq .head.repo.full_name)
- echo $head_repo
- |
if [ "$head_repo" != '"code-dot-org/code-dot-org"' ]; then
echo "Pull request is from fork $head_repo; exiting."
exit 1
fi
- name: restore-cache
image: plugins/s3-cache
settings:
Expand Down Expand Up @@ -217,6 +183,6 @@ trigger:
- pull_request
---
kind: signature
hmac: c4b01d2892b7314cb674278450cd30e012f01b3d5289eed1d6a2c933947ec623
hmac: b7621086539d5bc60d621e507bab706cad6f36fdd859d8b1d1b18d9670dbe5c6

...
139 changes: 139 additions & 0 deletions apps/src/lib/levelbuilder/lesson-editor/ActivitiesEditor.jsx
@@ -0,0 +1,139 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import color from '@cdo/apps/util/color';
import ActivityCard from '@cdo/apps/lib/levelbuilder/lesson-editor/ActivityCard';
import Activity from '@cdo/apps/templates/lessonOverview/activities/Activity';
import {connect} from 'react-redux';
import {addActivity} from '@cdo/apps/lib/levelbuilder/lesson-editor/activitiesEditorRedux';

const styles = {
activityEditAndPreview: {
display: 'flex',
flexDirection: 'row'
},
editor: {
width: '50%'
},
preview: {
width: '45%',
marginLeft: 20
},
previewBox: {
border: '1px solid black',
padding: 10
},
addActivity: {
fontSize: 14,
color: 'white',
background: color.cyan,
border: `1px solid ${color.cyan}`,
boxShadow: 'none'
}
};

/*
A GUI for editing activities in a lesson. Shows
the editing fields side by side with a preview of how they will
look in the lesson plan.
*/

class ActivitiesEditor extends Component {
static propTypes = {
//redux
activities: PropTypes.array,
addActivity: PropTypes.func
};

constructor(props) {
super(props);

this.state = {
targetActivitySectionPos: null
};
}

handleAddActivity = () => {
this.props.addActivity(
this.props.activities.length,
this.generateActivityKey()
);
};

generateActivityKey = () => {
let activityNumber = this.props.activities.length + 1;
while (
this.props.activities.some(
activity => activity.key === `activity-${activityNumber}`
)
) {
activityNumber++;
}

return `activity-${activityNumber}`;
};

setTargetActivitySection = targetActivitySectionPos => {
this.setState({targetActivitySectionPos});
};

// To be populated with the bounding client rect of each ActivitySectionCard element.
activitySectionMetrics = {};

setActivitySectionMetrics = (metrics, activitySectionPosition) => {
this.activitySectionMetrics[activitySectionPosition] = metrics;
};

render() {
const {activities} = this.props;

return (
<div>
<div style={styles.activityEditAndPreview}>
<div style={styles.editor}>
{activities.map(activity => {
return (
<ActivityCard
activity={activity}
activitiesCount={activities.length}
key={activity.key}
setActivitySectionMetrics={this.setActivitySectionMetrics}
setTargetActivitySection={this.setTargetActivitySection}
targetActivitySectionPos={this.state.targetActivitySectionPos}
activitySectionMetrics={this.activitySectionMetrics}
/>
);
})}
<button
onMouseDown={this.handleAddActivity}
className="btn"
style={styles.addActivity}
type="button"
>
<i style={{marginRight: 7}} className="fa fa-plus-circle" />
Add Activity
</button>
</div>
<div style={styles.preview}>
<h2>Preview</h2>
<div style={styles.previewBox}>
{activities.map(activity => {
return <Activity activity={activity} key={activity.key} />;
})}
</div>
</div>
</div>
</div>
);
}
}

export const UnconnectedActivitiesEditor = ActivitiesEditor;

export default connect(
state => ({
activities: state.activities
}),
{
addActivity
}
)(ActivitiesEditor);
167 changes: 167 additions & 0 deletions apps/src/lib/levelbuilder/lesson-editor/ActivitiesEditor.story.jsx
@@ -0,0 +1,167 @@
import React from 'react';
import ActivitiesEditor from '@cdo/apps/lib/levelbuilder/lesson-editor/ActivitiesEditor';
import {createStoreWithReducers, registerReducers} from '@cdo/apps/redux';
import reducers, {
init
} from '@cdo/apps/lib/levelbuilder/lesson-editor/activitiesEditorRedux';
import {Provider} from 'react-redux';

const activities = [
{
key: 'activity-1',
displayName: 'Main Activity',
position: 1,
time: 20,
activitySections: [
{
key: 'section-3',
position: 1,
displayName: 'Making programs',
remarks: true,
slide: false,
levels: [],
text:
'Today we are going to be looking at some sample apps to explore their purpose and function.',
tips: []
},
{
key: 'section-1',
position: 2,
displayName: '',
remarks: false,
slide: true,
levels: [],
text: 'In this activity you will be learning about making activities.',
tips: [
{
key: 'tip-1',
type: 'teachingTip',
markdown:
'After students are finished writing in their journals, discuss as a class or collect the journals to review student answers. \n- An input could be a user clicking a button or tapping the screen. \n- An output could be an image displayed or a sound played'
}
]
},
{
tips: [],
key: 'progression-1',
position: 3,
displayName: 'Programming Progression',
remarks: false,
slide: false,
text: 'This progression teaches you programming!',
levels: [
{
status: 'not started',
url: 'https://levelbuilder-studio.code.org/levels/598/edit',
name: 'Level 1',
icon: 'fa-desktop',
isUnplugged: false,
levelNumber: 1,
isCurrentLevel: false,
isConceptLevel: true,
sublevels: [],
position: 1,
activeId: 1,
ids: [1],
kind: 'puzzle',
skin: null,
videoKey: null,
concepts: '',
conceptDifficulty: '',
named: false,
assessment: false,
challenge: false
},
{
status: 'not started',
url: 'https://levelbuilder-studio.code.org/levels/598/edit',
icon: 'fa-desktop',
name: 'Level 2',
isUnplugged: false,
levelNumber: 2,
isCurrentLevel: false,
isConceptLevel: false,
sublevels: [],
position: 2,
activeId: 2,
ids: [2, 3],
kind: 'assessment',
skin: null,
videoKey: null,
concepts: '',
conceptDifficulty: '',
named: false,
assessment: true,
challenge: false
}
]
},
{
key: 'section-2',
displayName: 'Discussion',
position: 4,
remarks: false,
slide: false,
levels: [],
text:
'**Prompt:** With a partner, discuss the following and note down in your journal:\n - How does the user interact with the app?\n - What is the overall purpose of this app?\n - Who is the target audience?\n\n**Share Out:** As a class, discuss student answers to the discussion questions.',
tips: [
{
key: 'tip-2',
type: 'discussionGoal',
markdown: 'Make sure to get to the point'
},
{
key: 'tip-3',
type: 'assessmentOpportunity',
markdown: 'Are students getting it?'
}
]
}
]
},
{
key: 'activity-2',
displayName: '',
time: 0,
position: 2,
activitySections: [
{
key: 'section-1',
text: '',
displayName: '',
remarks: false,
slide: false,
tips: [],
levels: [],
position: 1
}
]
}
];

const levelKeyList = {
1: 'Level 1',
2: 'Level 2 - 1',
3: 'Level 2 - 2',
4: 'blockly:Studio:playlab_1'
};

const createStore = () => {
registerReducers({...reducers});
const store = createStoreWithReducers();
store.dispatch(init(activities, levelKeyList));
return store;
};
export default storybook => {
storybook.storiesOf('ActivitiesEditor', module).addStoryTable([
{
name: 'ActivitiesEditor',
story: () => (
<Provider store={createStore()}>
<ActivitiesEditor />
</Provider>
)
}
]);
};

0 comments on commit 1812d92

Please sign in to comment.