Skip to content

[WIP] Data-structures tutorial (closes #57) #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jan 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 134 additions & 104 deletions src/components/Lesson.vue
Original file line number Diff line number Diff line change
@@ -1,121 +1,124 @@
<template>
<div>
<header class="bg-navy pa2 pa3-ns flex items-center justify-around">
<a href='/#/' class="db-ns link flex-auto">
<img src="../images/ps_logo_horiz_white.svg" alt="ProtoSchool" style="height: 80px" class="ml3-ns"/>
</a>
<div class="tr dn db-ns">
<img src="../images/ipfs-illustrations-how-3.svg" alt="" style="height: 50px">
<Header/>
<div class="center mw7 ph2">
<div class="flex-l items-start center mw7 ph2">
<section class="pv3 mt3">
<div class="lh-solid v-mid f4">
<span class="green v-mid"><span class="b">{{workshopShortname}}</span> | Lesson {{lessonNumber}} of {{lessonsInWorkshop}}</span>
<span class="pl1"><img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1.2rem;" class="v-mid"/></span>
</div>
<h1>{{lessonTitle}}</h1>
<div class="lesson-text lh-copy" v-html="parsedText"></div>
</section>
<section v-if="concepts" class='dn db-ns ba border-green ph4 ml3 ml5-l mt5 mb3 mr3 measure' style="background: rgba(105, 196, 205, 10%)">
<h2 class="f5 fw2 green mt0 nb1 pt3">Useful concepts</h2>
<div class='f6 lh-copy' v-html="parsedConcepts"></div>
</section>
</div>
</header>
<section v-if="exercise" v-bind:class="{expand: expandExercise}" class="exercise pb4 pt3 ph3 ph4-l mb3 mr5 flex flex-column" style="background: #F6F7F9;">
<div class="flex-none">
<h2 class="mt0 mb2 green fw4 fill-current">
<span style='vertical-align:-1px'>
<img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1rem;"/>
<img v-else-if="cachedCode" src="../images/in-progress.svg" alt="complete" style="height: 1rem;"/>
<img v-else src="../images/not-started.svg" alt="not yet started" style="height: 1rem;"/>
</span>
<span class="green ttu f6 pl2 pr1 fw7 v-mid">
<span v-if="lessonPassed">You did it!</span>
<span v-else-if="cachedCode">Keep working.</span>
<span v-else>Try it!</span>
</span>
<span class="green f6 fw5 v-mid">
<span v-if="cachedCode && !lessonPassed">{{cachedStateMsg}}</span>
</span>
<div class="fr">
<button
v-if="expandExercise"
title="go smol"
v-on:click="toggleExpandExercise"
class='b--transparent bg-transparent green hover-green-muted pointer focus-outline'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 32 32"><path d="M16 4 L28 4 L28 16 L24 12 L20 16 L16 12 L20 8z M4 16 L8 20 L12 16 L16 20 L12 24 L16 28 L4 28z"></path></svg>
</button>
<button
v-else
v-on:click="toggleExpandExercise"
title='embiggen the exercise'
class='b--transparent bg-transparent charcoal-muted hover-green pointer focus-outline'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 32 32"><path d="M16 4 L28 4 L28 16 L24 12 L20 16 L16 12 L20 8z M4 16 L8 20 L12 16 L16 20 L12 24 L16 28 L4 28z"></path></svg>
</button>

<div class="flex-l items-start bt border-aqua bw4">
<section class="pv3 indent-1">
<h1 class="f3 measure-wide">{{lessonTitle}}</h1>
<div class="lh-solid v-mid">
<span class="green v-mid"><span class="b">{{workshopShortname}}</span> | Lesson {{lessonNumber}} of {{lessonsInWorkshop}}</span>
<span class="pl1"><img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1.2rem;" class="v-mid"/></span>
</div>
</h2>
<div v-if="exercise" v-html="parsedExercise" class='lh-copy'></div>
</div>
<div class="lesson-text lh-copy measure-wide" v-html="parsedText"></div>
</section>
<section v-if="concepts" class='dn db-ns ba border-green ph4 ml3 ml5-l mt5 mb3 mr3 measure' style="background: rgba(105, 196, 205, 10%)">
<h2 class="f5 fw2 green mt0 nb1 pt3">Useful concepts</h2>
<div class='f6 lh-copy' v-html="parsedConcepts"></div>
</section>
</div>

<section v-bind:class="{expand: expandExercise}" class="indent-1 exercise pb4 pt3 ph3 ph4-l mb3 mr5 flex flex-column" style="background: #F6F7F9;">
<div class="flex-none">
<h2 class="mt0 mb2 green fw4 fill-current">
<span style='vertical-align:-1px'>
<img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1rem;"/>
<img v-else-if="cachedCode" src="../images/in-progress.svg" alt="complete" style="height: 1rem;"/>
<img v-else src="../images/not-started.svg" alt="not yet started" style="height: 1rem;"/>
</span>
<span class="green ttu f6 pl2 pr1 fw7 v-mid">
<span v-if="lessonPassed">You did it!</span>
<span v-else-if="cachedCode">Keep working.</span>
<span v-else>Try it!</span>
</span>
<span class="green f6 fw5 v-mid">
<span v-if="cachedCode && !lessonPassed">{{cachedStateMsg}}</span>
</span>
<div class="fr">
<button
v-if="expandExercise"
title="go smol"
v-on:click="toggleExpandExercise"
class='b--transparent bg-transparent green hover-green-muted pointer focus-outline'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 32 32"><path d="M16 4 L28 4 L28 16 L24 12 L20 16 L16 12 L20 8z M4 16 L8 20 L12 16 L16 20 L12 24 L16 28 L4 28z"></path></svg>
</button>
<button
v-else
v-on:click="toggleExpandExercise"
title='embiggen the exercise'
class='b--transparent bg-transparent charcoal-muted hover-green pointer focus-outline'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 32 32"><path d="M16 4 L28 4 L28 16 L24 12 L20 16 L16 12 L20 8z M4 16 L8 20 L12 16 L16 20 L12 24 L16 28 L4 28z"></path></svg>
</button>

<div>
<span v-if="cachedCode" v-on:click="resetCode" class="textLink fr pb1">Reset Code</span>
</div>
<div class="bg-white flex-auto" style='height:100%;'>
<MonacoEditor
class="editor"
srcPath="."
:height="editorHeight"
:options="options"
:code="code"
theme="vs"
language="javascript"
@mounted="onMounted"
@codeChange="onCodeChange">
</MonacoEditor>
</div>
<div class='flex-none'>
<div class="pv2">
<div v-if="output.test && this.cachedCode" v-bind="output.test">
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.error">
Error: {{output.test.error.message}}
</div>
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.fail">
{{output.test.fail}}
</div>
<div class="lh-copy pv2 ph3 bg-green white" v-if="output.test.success && lessonPassed">
{{output.test.success}}
<a v-if="output.test.cid"
class="link fw7 underline-hover dib ph2 mh2 white" target='explore-ipld' :href='exploreIpldUrl'>
View in IPLD Explorer
</a>
</div>
</div>
<div class="lh-copy pv2 ph3" v-else>
Update the code to complete the exercise. Click <strong>submit</strong> to check your answer.
</div>
</div>
</h2>
<div v-if="exercise" v-html="parsedExercise" class='lh-copy'></div>
</div>
<div>
<span v-if="cachedCode" v-on:click="resetCode" class="textLink fr pb1">Reset Code</span>
</div>
<div class="bg-white flex-auto" style='height:100%;'>
<MonacoEditor
class="editor"
srcPath="."
:height="editorHeight"
:options="options"
:code="code"
theme="vs"
language="javascript"
@mounted="onMounted"
@codeChange="onCodeChange">
</MonacoEditor>
</div>
<div class='flex-none'>
<div class="pv2">
<div v-if="output.test && this.cachedCode" v-bind="output.test">
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.error">
Error: {{output.test.error.message}}
<div class="pt3 ph2 tr">
<div v-if="((output.test && output.test.success) || lessonPassed) && lessonNumber === lessonsInWorkshop">
<Button v-bind:click="workshopMenu" class="bg-aqua white">More Tutorials</Button>
</div>
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.fail">
{{output.test.fail}}
<div v-else-if="lessonPassed">
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
</div>
<div class="lh-copy pv2 ph3 bg-green white" v-if="output.test.success && lessonPassed">
{{output.test.success}}
<a v-if="output.test.cid"
class="link fw7 underline-hover dib ph2 mh2 white" target='explore-ipld' :href='exploreIpldUrl'>
View in IPLD Explorer
</a>
<div v-else>
<Button v-bind:click="run" class="bg-aqua white">Submit</Button>
</div>
</div>
<div class="lh-copy pv2 ph3" v-else>
Update the code to complete the exercise. Click <strong>submit</strong> to check your answer.
</div>
</div>
<div class="pt3 ph2 tr">
<div v-if="((output.test && output.test.success) || lessonPassed) && lessonNumber === lessonsInWorkshop">
</section>
<section v-else >
<div class="pt3 ph2 tr mb3">
<div v-if="lessonNumber === lessonsInWorkshop">
<Button v-bind:click="workshopMenu" class="bg-aqua white">More Tutorials</Button>
</div>
<div v-else-if="lessonPassed">
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
</div>
<div v-else>
<Button v-bind:click="run" class="bg-green white">Submit</Button>
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
</div>
</div>
</div>
</section>
<section class="indent-1 mb4 mw-900">
<div>
</section>
</div>
<footer class="bg-navy white ph2 ph3-ns mt4 flex items-center justify-around">
<div class="mw7">
<p>Feeling stuck? We'd love to hear what's confusing so we can improve
this lesson. Please <a :href="issueUrl" target="_blank">share your questions and feedback</a>.</p>
</div>
</section>
</footer>
</div>
</template>

Expand All @@ -125,6 +128,7 @@ import Vue from 'vue'
import MonacoEditor from 'vue-monaco-editor'
import Explorer from './Explorer.vue'
import Button from './Button.vue'
import Header from './Header.vue'
const IPFS = require('ipfs')
const CID = require('cids')
const marked = require('marked')
Expand Down Expand Up @@ -181,7 +185,8 @@ export default {
components: {
MonacoEditor,
Explorer,
Button
Button,
Header
},
data: self => {
return {
Expand All @@ -198,7 +203,6 @@ export default {
lessonKey: 'passed' + self.$route.path,
lessonPassed: !!localStorage['passed' + self.$route.path],
lessonTitle: self.$attrs.lessonTitle,
issueUrl: `https://github.com/ipfs-shipyard/proto.school/issues/new?labels=question&title=Question+on+Lesson+${self.$route.path.slice(self.$route.path.lastIndexOf('/') + 1)}:+${self.$attrs.lessonTitle}+(${self.$route.path})&body=Have%20a%20question%20or%20suggestion%20regarding%20a%20ProtoSchool%20lesson%3F%20Please%20use%20this%0Atemplate%20to%20share%20it!%0A%0A1.%20URL%20of%20the%20lesson%20that's%20confusing%3A%0A%20https%3A%2F%2Fproto.school%2F%23${self.$route.path}%0A%0A2.%20What%27s%20confusing%20about%20this%20lesson%3F%0A%0A3.%20What%20additional%20context%20could%20we%20provide%20to%20help%20you%20succeed%3F%0A%0A4.%20What%20other%20feedback%20would%20you%20like%20to%20share%20about%20ProtoSchool%3F%0A`,
output: self.output,
IPFS,
expandExercise: false,
Expand All @@ -221,7 +225,19 @@ export default {
return parseInt(this.$route.path.slice(this.$route.path.lastIndexOf('/') + 1), 10)
},
workshopShortname: function () {
return this.$route.path.charAt(1).toUpperCase() + this.$route.path.slice(2, this.$route.path.lastIndexOf('/'))
let shortname = this.$route.path.charAt(1).toUpperCase() + this.$route.path.slice(2, this.$route.path.lastIndexOf('/'))
// // ADD THIS LATER IF WE DECIDE WE WANT ALL WORDS CAPITALIZED
// if (shortname.includes("-")) {
// let shortnameArray = shortname.split("-")
// let shortnameArrayUpper = shortnameArray.map( word => {
// return (word.charAt(0).toUpperCase() + word.slice(1))
// })
// shortname = shortnameArrayUpper.join(" ")
// }
return shortname.split('-').join(" ")
},
issueUrl: function () {
return `https://github.com/ProtoSchool/protoschool.github.io/issues/new?assignees=&labels=lesson-feedback&template=lesson-feedback.md&title=Lesson+Feedback%3A+${this.workshopShortname}+-+Lesson+${this.lessonNumber}+(${this.lessonTitle})`
},
lessonsInWorkshop: function () {
let basePath = this.$route.path.slice(0, -2)
Expand Down Expand Up @@ -336,13 +352,23 @@ export default {
}
},
next: function () {
Vue.set(this.output, 'test', null)
if (this.exercise) {
Vue.set(this.output, 'test', null)
} else {
localStorage[this.lessonKey] = 'passed'
this.lessonPassed = !!localStorage[this.lessonKey]
}
let current = this.lessonNumber
let next = (parseInt(current) + 1).toString().padStart(2, '0')
this.$router.push({path: next})
},
workshopMenu: function () {
Vue.set(this.output, 'test', null)
if (this.exercise) {
Vue.set(this.output, 'test', null)
} else {
localStorage[this.lessonKey] = 'passed'
this.lessonPassed = !!localStorage[this.lessonKey]
}
this.$router.push({path: '/'})
},
toggleExpandExercise: function () {
Expand Down Expand Up @@ -384,6 +410,10 @@ span.textLink {
text-decoration: underline;
}

footer a {
color: aqua;
}

@media screen and (min-width: 60rem) {
.indent-1 {
margin-left: 93px;
Expand Down
33 changes: 31 additions & 2 deletions src/components/Navigation.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<template>
<section class="flex items-center bg-aqua white pv3"
<div class="bg-aqua w-100">
<nav class="flex items-center bg-aqua white pv3 center tc mw7">
<nav v-if="isLesson" class="flex items-center bg-aqua navy pv3 center tc mw7">
<router-link class="nav-link navy" :to="'/'">Home</router-link> >
<router-link class="nav-link navy" :to="'/tutorials'">Tutorials</router-link> >
<span class="fake-nav-link">{{workshopShortname}}</span>
</nav>
<nav v-else class="flex items-center bg-aqua white pv3 center tc mw7">
<div v-for="link in links">
<router-link v-if="link.path === $route.path"
class="nav-link white" :to="`${link.path}`">{{link.text}}</router-link>
Expand All @@ -19,6 +24,8 @@ export default {
name: 'Navigation',
data: self => {
return {
currentPath: self.$route.path.toString(),
workshopShortname: (self.$route.path.charAt(1).toUpperCase() + self.$route.path.slice(2, self.$route.path.lastIndexOf('/'))).split('-').join(" "),
links: [
{
text: 'Home',
Expand Down Expand Up @@ -46,7 +53,22 @@ export default {
}
]
}
}
},
computed: {
isLesson: function () {
let count = 0
this.links.forEach( link => {
if (link.path === this.currentPath) {
count++
}
})
if (count === 0) {
return true
} else {
return false
}
}
}
}
</script>

Expand All @@ -59,6 +81,13 @@ export default {
margin: 2px 20px;
text-decoration: none;
}
.fake-nav-link {
font-size: 18px;
font-weight: 700;
margin: 2px 20px;
text-decoration: none;
color: white;
}
.nav-link:first {
margin: 2px 20px 2px 0px;
}
Expand Down
Loading