Skip to content

Instantly share code, notes, and snippets.

@bstro
Last active May 25, 2018 18:56
Show Gist options
  • Save bstro/e7f60f710a26f5491f38f2aea05bbba2 to your computer and use it in GitHub Desktop.
Save bstro/e7f60f710a26f5491f38f2aea05bbba2 to your computer and use it in GitHub Desktop.
New Twiddle
import Ember from 'ember';
import computedStyle from 'ember-computed-style';
export default Ember.Component.extend({
classNameBindings: ['type', 'proficiency'],
classNames: ['assessment-timeline-node'],
attributeBindings: ['style'],
style: computedStyle('horizontalPosition'),
horizontalPosition: Ember.computed('x', function() {
return { left: this.get('x') }
}),
type: Ember.computed('assessment.type', function() {
return `assessment-timeline-node-${this.get('assessment.type')}`;
}),
proficiency: Ember.computed('assessment.score', function() {
const proficiency = this.get('assessment.is_proficient');
if (proficiency) return `assessment-timeline-node-proficient`;
return `assessment-timeline-node-not-proficient`;
})
});
import Ember from 'ember';
import Moment from 'moment';
const TIME_UNIT = 'days';
const PADDING = 3;
const data = [
{
"assessment_date": "2018-04-19T00:31:03.153000Z",
"score": 4,
"type": "formative",
"is_proficient": false,
"label": "a"
}, {
"assessment_date": "2017-11-20T09:51:36.035983Z",
"score": 3,
"type": "summative",
"is_proficient": false,
"label": "b"
}, {
"assessment_date": "2018-02-15T09:51:36.035983Z",
"score": 3,
"type": "formative",
"is_proficient": true,
"label": "c"
}, {
"assessment_date": "2018-02-20T09:51:36.035983Z",
"score": 3,
"type": "summative",
"is_proficient": true,
"label": "d"
}, {
"assessment_date": "2018-03-19T17:48:44.820000Z",
"score": 4,
"type": "summative",
"is_proficient": false,
"label": "e"
}
];
function last(arr=[]) {
return arr[arr.length-1]
}
function _groupAssessmentsBySummative(assessments, acc = []) {
let [head, ...tail] = assessments;
if (head.type === "summative") {
return _groupAssessmentsBySummative(tail, acc.concat(head));
}
if (head.type === "formative") {
const last = last(acc);
if (Array.isArray(last)) {
arr[arr.length-1] = last.concat(head); // last.concat(head);
} else {
arr = arr.concat(head);
}
return _groupAssessmentsBySummative(tail, arr);
}
if (tail.length === 0) return acc;
}
export default Ember.Component.extend({
data,
assessments: Ember.computed.reads('data'),
sortedAssessments: Ember.computed.sort('assessments', function(a, b) {
return a.assessment_date > b.assessment_date;
}),
groupedAssessmentsBySummative: Ember.computed('sortedAssessments', function() {
const sortedAssessments = this.get('sortedAssessments');
return _groupAssessmentsBySummative(sortedAssessments);
return sortedAssessments
.filter(assessment => assessment.type === 'summative')
.map(assessment => [assessment]);
}),
startDate: Ember.computed.reads('sortedAssessments.firstObject.assessment_date'),
endDate: Ember.computed.reads('sortedAssessments.lastObject.assessment_date'),
daysSinceMap: Ember.computed('sortedAssessments', 'startDate', function() {
const startDate = Moment(this.get('startDate'));
return this.get('sortedAssessments').map(assessment => {
const assessmentDate = Moment(assessment.assessment_date);
return assessmentDate.diff(startDate, TIME_UNIT);
});
}),
relativePositionMap: Ember.computed('daysSinceMap', function() {
const lastDay = this.get('daysSinceMap.lastObject');
return this.get('daysSinceMap').map(day => `${day / lastDay * 100}%`);
}),
range: Ember.computed.reads('daysSinceMap.lastObject')
});
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle'
});
.assessment-timeline {
position: relative;
width: 100%;
background: #F8F8F8;
border-radius: 12px;
height: 24px;
overflow: hidden;
}
.assessment-timeline-node {
position: absolute;
height: 24px;
width: 24px;
box-sizing: border-box;
border-radius: 12px;
box-shadow: 0 0 0 3px #F8F8F8;
}
.assessment-timeline-node:last-child {
margin-left: -24px;
}
.assessment-timeline-node-proficient {
background-color: green;
border-color: green;
}
.assessment-timeline-node-not-proficient {
background-color: orange;
border-color: orange;
}
.assessment-timeline-node-summative {
border: none;
}
.assessment-timeline-node-formative {
border-width: 4px;
border-style: solid;
background-color: white;
}
<div id="wrapper">
{{assessment-timeline}}
</div>
{{log groupedAssessmentsBySummative}}
<div class="assessment-timeline">
{{#each assessments as |assessment idx|}}
{{assessment-timeline-node
x=(get relativePositionMap idx)
assessment=assessment
daysSinceStart=daysSinceStart
}}
{{/each}}
</div>
{
"version": "0.13.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.16.2",
"ember-template-compiler": "2.16.2",
"ember-testing": "2.16.2"
},
"addons": {
"ember-data": "2.16.3",
"ember-moment": "latest",
"ember-computed-style": "latest"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment