Skip to content

Commit 942a728

Browse files
Merge pull request #59 from ProtoSchool/data-structures
[WIP] Data-structures tutorial (closes #57)
2 parents 18e80a9 + 73094bc commit 942a728

File tree

15 files changed

+557
-109
lines changed

15 files changed

+557
-109
lines changed

src/components/Lesson.vue

Lines changed: 134 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,124 @@
11
<template>
22
<div>
3-
<header class="bg-navy pa2 pa3-ns flex items-center justify-around">
4-
<a href='/#/' class="db-ns link flex-auto">
5-
<img src="../images/ps_logo_horiz_white.svg" alt="ProtoSchool" style="height: 80px" class="ml3-ns"/>
6-
</a>
7-
<div class="tr dn db-ns">
8-
<img src="../images/ipfs-illustrations-how-3.svg" alt="" style="height: 50px">
3+
<Header/>
4+
<div class="center mw7 ph2">
5+
<div class="flex-l items-start center mw7 ph2">
6+
<section class="pv3 mt3">
7+
<div class="lh-solid v-mid f4">
8+
<span class="green v-mid"><span class="b">{{workshopShortname}}</span> | Lesson {{lessonNumber}} of {{lessonsInWorkshop}}</span>
9+
<span class="pl1"><img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1.2rem;" class="v-mid"/></span>
10+
</div>
11+
<h1>{{lessonTitle}}</h1>
12+
<div class="lesson-text lh-copy" v-html="parsedText"></div>
13+
</section>
14+
<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%)">
15+
<h2 class="f5 fw2 green mt0 nb1 pt3">Useful concepts</h2>
16+
<div class='f6 lh-copy' v-html="parsedConcepts"></div>
17+
</section>
918
</div>
10-
</header>
19+
<section v-if="exercise" v-bind:class="{expand: expandExercise}" class="exercise pb4 pt3 ph3 ph4-l mb3 mr5 flex flex-column" style="background: #F6F7F9;">
20+
<div class="flex-none">
21+
<h2 class="mt0 mb2 green fw4 fill-current">
22+
<span style='vertical-align:-1px'>
23+
<img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1rem;"/>
24+
<img v-else-if="cachedCode" src="../images/in-progress.svg" alt="complete" style="height: 1rem;"/>
25+
<img v-else src="../images/not-started.svg" alt="not yet started" style="height: 1rem;"/>
26+
</span>
27+
<span class="green ttu f6 pl2 pr1 fw7 v-mid">
28+
<span v-if="lessonPassed">You did it!</span>
29+
<span v-else-if="cachedCode">Keep working.</span>
30+
<span v-else>Try it!</span>
31+
</span>
32+
<span class="green f6 fw5 v-mid">
33+
<span v-if="cachedCode && !lessonPassed">{{cachedStateMsg}}</span>
34+
</span>
35+
<div class="fr">
36+
<button
37+
v-if="expandExercise"
38+
title="go smol"
39+
v-on:click="toggleExpandExercise"
40+
class='b--transparent bg-transparent green hover-green-muted pointer focus-outline'>
41+
<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>
42+
</button>
43+
<button
44+
v-else
45+
v-on:click="toggleExpandExercise"
46+
title='embiggen the exercise'
47+
class='b--transparent bg-transparent charcoal-muted hover-green pointer focus-outline'>
48+
<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>
49+
</button>
1150

12-
<div class="flex-l items-start bt border-aqua bw4">
13-
<section class="pv3 indent-1">
14-
<h1 class="f3 measure-wide">{{lessonTitle}}</h1>
15-
<div class="lh-solid v-mid">
16-
<span class="green v-mid"><span class="b">{{workshopShortname}}</span> | Lesson {{lessonNumber}} of {{lessonsInWorkshop}}</span>
17-
<span class="pl1"><img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1.2rem;" class="v-mid"/></span>
51+
</div>
52+
</h2>
53+
<div v-if="exercise" v-html="parsedExercise" class='lh-copy'></div>
1854
</div>
19-
<div class="lesson-text lh-copy measure-wide" v-html="parsedText"></div>
20-
</section>
21-
<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%)">
22-
<h2 class="f5 fw2 green mt0 nb1 pt3">Useful concepts</h2>
23-
<div class='f6 lh-copy' v-html="parsedConcepts"></div>
24-
</section>
25-
</div>
26-
27-
<section v-bind:class="{expand: expandExercise}" class="indent-1 exercise pb4 pt3 ph3 ph4-l mb3 mr5 flex flex-column" style="background: #F6F7F9;">
28-
<div class="flex-none">
29-
<h2 class="mt0 mb2 green fw4 fill-current">
30-
<span style='vertical-align:-1px'>
31-
<img v-if="lessonPassed" src="../images/complete.svg" alt="complete" style="height: 1rem;"/>
32-
<img v-else-if="cachedCode" src="../images/in-progress.svg" alt="complete" style="height: 1rem;"/>
33-
<img v-else src="../images/not-started.svg" alt="not yet started" style="height: 1rem;"/>
34-
</span>
35-
<span class="green ttu f6 pl2 pr1 fw7 v-mid">
36-
<span v-if="lessonPassed">You did it!</span>
37-
<span v-else-if="cachedCode">Keep working.</span>
38-
<span v-else>Try it!</span>
39-
</span>
40-
<span class="green f6 fw5 v-mid">
41-
<span v-if="cachedCode && !lessonPassed">{{cachedStateMsg}}</span>
42-
</span>
43-
<div class="fr">
44-
<button
45-
v-if="expandExercise"
46-
title="go smol"
47-
v-on:click="toggleExpandExercise"
48-
class='b--transparent bg-transparent green hover-green-muted pointer focus-outline'>
49-
<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>
50-
</button>
51-
<button
52-
v-else
53-
v-on:click="toggleExpandExercise"
54-
title='embiggen the exercise'
55-
class='b--transparent bg-transparent charcoal-muted hover-green pointer focus-outline'>
56-
<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>
57-
</button>
58-
55+
<div>
56+
<span v-if="cachedCode" v-on:click="resetCode" class="textLink fr pb1">Reset Code</span>
57+
</div>
58+
<div class="bg-white flex-auto" style='height:100%;'>
59+
<MonacoEditor
60+
class="editor"
61+
srcPath="."
62+
:height="editorHeight"
63+
:options="options"
64+
:code="code"
65+
theme="vs"
66+
language="javascript"
67+
@mounted="onMounted"
68+
@codeChange="onCodeChange">
69+
</MonacoEditor>
70+
</div>
71+
<div class='flex-none'>
72+
<div class="pv2">
73+
<div v-if="output.test && this.cachedCode" v-bind="output.test">
74+
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.error">
75+
Error: {{output.test.error.message}}
76+
</div>
77+
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.fail">
78+
{{output.test.fail}}
79+
</div>
80+
<div class="lh-copy pv2 ph3 bg-green white" v-if="output.test.success && lessonPassed">
81+
{{output.test.success}}
82+
<a v-if="output.test.cid"
83+
class="link fw7 underline-hover dib ph2 mh2 white" target='explore-ipld' :href='exploreIpldUrl'>
84+
View in IPLD Explorer
85+
</a>
86+
</div>
87+
</div>
88+
<div class="lh-copy pv2 ph3" v-else>
89+
Update the code to complete the exercise. Click <strong>submit</strong> to check your answer.
90+
</div>
5991
</div>
60-
</h2>
61-
<div v-if="exercise" v-html="parsedExercise" class='lh-copy'></div>
62-
</div>
63-
<div>
64-
<span v-if="cachedCode" v-on:click="resetCode" class="textLink fr pb1">Reset Code</span>
65-
</div>
66-
<div class="bg-white flex-auto" style='height:100%;'>
67-
<MonacoEditor
68-
class="editor"
69-
srcPath="."
70-
:height="editorHeight"
71-
:options="options"
72-
:code="code"
73-
theme="vs"
74-
language="javascript"
75-
@mounted="onMounted"
76-
@codeChange="onCodeChange">
77-
</MonacoEditor>
78-
</div>
79-
<div class='flex-none'>
80-
<div class="pv2">
81-
<div v-if="output.test && this.cachedCode" v-bind="output.test">
82-
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.error">
83-
Error: {{output.test.error.message}}
92+
<div class="pt3 ph2 tr">
93+
<div v-if="((output.test && output.test.success) || lessonPassed) && lessonNumber === lessonsInWorkshop">
94+
<Button v-bind:click="workshopMenu" class="bg-aqua white">More Tutorials</Button>
8495
</div>
85-
<div class="lh-copy pv2 ph3 bg-red white" v-if="output.test.fail">
86-
{{output.test.fail}}
96+
<div v-else-if="lessonPassed">
97+
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
8798
</div>
88-
<div class="lh-copy pv2 ph3 bg-green white" v-if="output.test.success && lessonPassed">
89-
{{output.test.success}}
90-
<a v-if="output.test.cid"
91-
class="link fw7 underline-hover dib ph2 mh2 white" target='explore-ipld' :href='exploreIpldUrl'>
92-
View in IPLD Explorer
93-
</a>
99+
<div v-else>
100+
<Button v-bind:click="run" class="bg-aqua white">Submit</Button>
94101
</div>
95102
</div>
96-
<div class="lh-copy pv2 ph3" v-else>
97-
Update the code to complete the exercise. Click <strong>submit</strong> to check your answer.
98-
</div>
99103
</div>
100-
<div class="pt3 ph2 tr">
101-
<div v-if="((output.test && output.test.success) || lessonPassed) && lessonNumber === lessonsInWorkshop">
104+
</section>
105+
<section v-else >
106+
<div class="pt3 ph2 tr mb3">
107+
<div v-if="lessonNumber === lessonsInWorkshop">
102108
<Button v-bind:click="workshopMenu" class="bg-aqua white">More Tutorials</Button>
103109
</div>
104-
<div v-else-if="lessonPassed">
105-
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
106-
</div>
107110
<div v-else>
108-
<Button v-bind:click="run" class="bg-green white">Submit</Button>
111+
<Button v-bind:click="next" class="bg-aqua white">Next</Button>
109112
</div>
110113
</div>
111-
</div>
112-
</section>
113-
<section class="indent-1 mb4 mw-900">
114-
<div>
114+
</section>
115+
</div>
116+
<footer class="bg-navy white ph2 ph3-ns mt4 flex items-center justify-around">
117+
<div class="mw7">
115118
<p>Feeling stuck? We'd love to hear what's confusing so we can improve
116119
this lesson. Please <a :href="issueUrl" target="_blank">share your questions and feedback</a>.</p>
117120
</div>
118-
</section>
121+
</footer>
119122
</div>
120123
</template>
121124

@@ -125,6 +128,7 @@ import Vue from 'vue'
125128
import MonacoEditor from 'vue-monaco-editor'
126129
import Explorer from './Explorer.vue'
127130
import Button from './Button.vue'
131+
import Header from './Header.vue'
128132
const IPFS = require('ipfs')
129133
const CID = require('cids')
130134
const marked = require('marked')
@@ -181,7 +185,8 @@ export default {
181185
components: {
182186
MonacoEditor,
183187
Explorer,
184-
Button
188+
Button,
189+
Header
185190
},
186191
data: self => {
187192
return {
@@ -198,7 +203,6 @@ export default {
198203
lessonKey: 'passed' + self.$route.path,
199204
lessonPassed: !!localStorage['passed' + self.$route.path],
200205
lessonTitle: self.$attrs.lessonTitle,
201-
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`,
202206
output: self.output,
203207
IPFS,
204208
expandExercise: false,
@@ -221,7 +225,19 @@ export default {
221225
return parseInt(this.$route.path.slice(this.$route.path.lastIndexOf('/') + 1), 10)
222226
},
223227
workshopShortname: function () {
224-
return this.$route.path.charAt(1).toUpperCase() + this.$route.path.slice(2, this.$route.path.lastIndexOf('/'))
228+
let shortname = this.$route.path.charAt(1).toUpperCase() + this.$route.path.slice(2, this.$route.path.lastIndexOf('/'))
229+
// // ADD THIS LATER IF WE DECIDE WE WANT ALL WORDS CAPITALIZED
230+
// if (shortname.includes("-")) {
231+
// let shortnameArray = shortname.split("-")
232+
// let shortnameArrayUpper = shortnameArray.map( word => {
233+
// return (word.charAt(0).toUpperCase() + word.slice(1))
234+
// })
235+
// shortname = shortnameArrayUpper.join(" ")
236+
// }
237+
return shortname.split('-').join(" ")
238+
},
239+
issueUrl: function () {
240+
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})`
225241
},
226242
lessonsInWorkshop: function () {
227243
let basePath = this.$route.path.slice(0, -2)
@@ -336,13 +352,23 @@ export default {
336352
}
337353
},
338354
next: function () {
339-
Vue.set(this.output, 'test', null)
355+
if (this.exercise) {
356+
Vue.set(this.output, 'test', null)
357+
} else {
358+
localStorage[this.lessonKey] = 'passed'
359+
this.lessonPassed = !!localStorage[this.lessonKey]
360+
}
340361
let current = this.lessonNumber
341362
let next = (parseInt(current) + 1).toString().padStart(2, '0')
342363
this.$router.push({path: next})
343364
},
344365
workshopMenu: function () {
345-
Vue.set(this.output, 'test', null)
366+
if (this.exercise) {
367+
Vue.set(this.output, 'test', null)
368+
} else {
369+
localStorage[this.lessonKey] = 'passed'
370+
this.lessonPassed = !!localStorage[this.lessonKey]
371+
}
346372
this.$router.push({path: '/'})
347373
},
348374
toggleExpandExercise: function () {
@@ -384,6 +410,10 @@ span.textLink {
384410
text-decoration: underline;
385411
}
386412
413+
footer a {
414+
color: aqua;
415+
}
416+
387417
@media screen and (min-width: 60rem) {
388418
.indent-1 {
389419
margin-left: 93px;

src/components/Navigation.vue

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
<template>
22
<section class="flex items-center bg-aqua white pv3"
33
<div class="bg-aqua w-100">
4-
<nav class="flex items-center bg-aqua white pv3 center tc mw7">
4+
<nav v-if="isLesson" class="flex items-center bg-aqua navy pv3 center tc mw7">
5+
<router-link class="nav-link navy" :to="'/'">Home</router-link> >
6+
<router-link class="nav-link navy" :to="'/tutorials'">Tutorials</router-link> >
7+
<span class="fake-nav-link">{{workshopShortname}}</span>
8+
</nav>
9+
<nav v-else class="flex items-center bg-aqua white pv3 center tc mw7">
510
<div v-for="link in links">
611
<router-link v-if="link.path === $route.path"
712
class="nav-link white" :to="`${link.path}`">{{link.text}}</router-link>
@@ -19,6 +24,8 @@ export default {
1924
name: 'Navigation',
2025
data: self => {
2126
return {
27+
currentPath: self.$route.path.toString(),
28+
workshopShortname: (self.$route.path.charAt(1).toUpperCase() + self.$route.path.slice(2, self.$route.path.lastIndexOf('/'))).split('-').join(" "),
2229
links: [
2330
{
2431
text: 'Home',
@@ -46,7 +53,22 @@ export default {
4653
}
4754
]
4855
}
49-
}
56+
},
57+
computed: {
58+
isLesson: function () {
59+
let count = 0
60+
this.links.forEach( link => {
61+
if (link.path === this.currentPath) {
62+
count++
63+
}
64+
})
65+
if (count === 0) {
66+
return true
67+
} else {
68+
return false
69+
}
70+
}
71+
}
5072
}
5173
</script>
5274

@@ -59,6 +81,13 @@ export default {
5981
margin: 2px 20px;
6082
text-decoration: none;
6183
}
84+
.fake-nav-link {
85+
font-size: 18px;
86+
font-weight: 700;
87+
margin: 2px 20px;
88+
text-decoration: none;
89+
color: white;
90+
}
6291
.nav-link:first {
6392
margin: 2px 20px 2px 0px;
6493
}

0 commit comments

Comments
 (0)