Skip to content

feat: show logs on ui #198

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 59 commits into from
Apr 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
cc3d9b4
Initial work on file upload lesson.
mikeal Jan 3, 2019
117c701
Fix linter error
terichadbourne Jan 29, 2019
cb0f3af
Merge branch 'code' into file-upload
terichadbourne Jan 29, 2019
d8fa09a
Remove unused properties
terichadbourne Feb 12, 2019
7956414
Add dummy file tutorial lesson
terichadbourne Feb 12, 2019
14c2cb8
Offer multiple boilerplates & update instructions
terichadbourne Feb 12, 2019
627eb39
Update UI for file upload
terichadbourne Feb 13, 2019
5cb9e04
Remove "Step 2" header from non-file exercise box
terichadbourne Feb 13, 2019
b934a1d
Remove unused console logs
terichadbourne Feb 13, 2019
6c50a79
Add file tutorial to homepage and adjust titles
terichadbourne Feb 13, 2019
2cc679f
Appease linter
terichadbourne Feb 13, 2019
f1f16d6
Beautify upload formatting
terichadbourne Feb 13, 2019
9bc44ad
Repair file upload and code submission
terichadbourne Feb 13, 2019
f0d5b70
Change icon and fix formatting for uploaded files
terichadbourne Feb 15, 2019
be14009
Disable submit button in file lesson until upload
terichadbourne Mar 5, 2019
28d4039
Disallow folder upload
terichadbourne Mar 5, 2019
7204e1a
Add 2nd file lesson
terichadbourne Mar 5, 2019
d768208
Improve formatting on disabled button hover
terichadbourne Mar 6, 2019
2c78e7f
Complete files lesson 1 content
terichadbourne Mar 6, 2019
59329d7
Update 2nd file lesson (WIP)
terichadbourne Mar 6, 2019
337e123
More validation flailing
terichadbourne Mar 6, 2019
9071b2c
Update package-lock.json
terichadbourne Mar 7, 2019
4d350c7
Merge branch 'code' into file-upload
terichadbourne Mar 7, 2019
e72a8cf
Restructure initial lesson content
terichadbourne Apr 1, 2019
bb550f5
Merge branch 'code' into file-upload
terichadbourne Apr 1, 2019
190f1eb
Remove old console logs
terichadbourne Apr 1, 2019
64e3626
Remove `code` and `validate` from text lessons
terichadbourne Apr 1, 2019
2d1d381
Merge branch 'code' into file-upload
terichadbourne Apr 1, 2019
ae26690
Update dependencies to fix IPFS import
terichadbourne Apr 1, 2019
8cb8e2b
Fix console logs for file basics lesson 2
terichadbourne Apr 1, 2019
e7405e5
Add a lesson #4 on MFS `write` method
terichadbourne Apr 1, 2019
26d5466
Rename `lessons` dir, create `boilerplates` dir
terichadbourne Apr 2, 2019
8beaa63
Change /lessons references to /tutorials
terichadbourne Apr 2, 2019
ef4a779
Fix validation for MFS Lesson 4
terichadbourne Apr 3, 2019
2b35f36
Rename file tutorial to be about MFS
terichadbourne Apr 3, 2019
3ddc148
Add lesson on `files.ls`
terichadbourne Apr 3, 2019
40cb898
Update validation error message
terichadbourne Apr 3, 2019
3244aa0
chore: sync with code branch
fsdiogo Apr 4, 2019
0f3f156
chore: boilerplates tidy up and path fix
fsdiogo Apr 4, 2019
b94d668
fix: expected result of Lesson 3
fsdiogo Apr 5, 2019
e833e79
chore: some rephrasing to the first mfs lessons
fsdiogo Apr 5, 2019
215e98b
Add lesson on files.mkdir
terichadbourne Apr 9, 2019
711cae4
Sync with code branch
fsdiogo Apr 10, 2019
6a2f2ee
feat: add the ability to override external errors
fsdiogo Apr 11, 2019
1e250f6
Merge branch 'code' into file-upload
fsdiogo Apr 16, 2019
68e8e36
chore: add instructions for overriding errors
fsdiogo Apr 16, 2019
c5aee7e
chore: hide MFS lesson
fsdiogo Apr 16, 2019
23b293a
feat: show logs in UI
fsdiogo Apr 17, 2019
f814ce2
chore: add instructions for this additional step
fsdiogo Apr 17, 2019
bf056cc
feat: add syntax hihglightning
fsdiogo Apr 17, 2019
b9b161c
chore: sycn with code branch
fsdiogo Apr 18, 2019
d69a74b
chore: hide the MFS lessons
fsdiogo Apr 18, 2019
d278995
Delete output.test.log when code is reset
terichadbourne Apr 18, 2019
fe4f405
Update phrasing of step 3 header
terichadbourne Apr 18, 2019
0c91063
chore: revamp instructions
fsdiogo Apr 18, 2019
8100167
Remove Step 3 label if not file upload lesson
terichadbourne Apr 19, 2019
2dcb40d
Update instructions
terichadbourne Apr 22, 2019
e99bf08
fix: links in readme
fsdiogo Apr 22, 2019
7fdbc84
fix: boilerplates
fsdiogo Apr 22, 2019
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
261 changes: 195 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,60 @@ If you're interested in building tutorials, keep reading!

## Developing Tutorials

Each **tutorial** in ProtoSchool is made up of multiple **lessons**.

### Run the server locally to preview your work

### Run the server locally

First, check out this repository and run the dev server locally.
First, check out this repository, install dependencies, and run the dev server locally:

```sh
> npm install
> npm run serve
```
You should now be able to preview your work in a web browser at: http://localhost:8080/#/

(Note that you won't be able to see your new lessons until you've updated the appropriate routes and import statements, as described below.)

### Create a directory for your tutorial

Create a new directory within `tutorials` for your tutorial, using your lesson shortname.
Create a new directory for your files within `tutorials`, using your tutorial shortname.

Example (while in `tutorials`):

```sh
> mkdir Tutorial-Shortname
```

### Build your lessons (repeat for each lesson in the tutorial)

Each **tutorial** in ProtoSchool is made up of multiple **lessons**.

Currently there are three lesson formats available, which you may mix and match within your tutorial:
- A standard lesson with a coding exercise (the most common)
- A lesson with a coding exercise that requires a file upload
- A text-only lesson with no code challenge

### Create lesson files (repeat for each lesson in tutorial)
Follow the steps below to create each lesson.

#### Vue file
#### Create lesson files

Depending on which lesson format you've chosen, you'll need to create 2-4 files within your project directory. Check the table below to see which files you need, then read on for instructions on how to create them.

| File | Sample Filename | Standard Lesson with Coding Exercise | Lesson with Coding Exercise and File Upload | Text-Only Lesson
| :--- | :---: | :---: | :---: | :---: |
| A Vue file that provides **required metadata** (e.g. title) for your lesson and, when relevant, the **default code and validation for the exercise**|`01.vue`| Required | Required | Required |
| A markdown file containing the **text of the lesson** (your educational content)|`01.md`| Required | Required | Required |
| A markdown file containing the **text of the assignment shown in the exercise box**|`01-exercise.vue`| Required | Required | Not Used |
| A markdown file containing the **text of the optional useful concepts box**|`01-concepts.md`| Optional | Optional | Optional |

Not familiar with markdown? It's a fairly simple way to style text on the web. [Learn more about markdown formatting here.](https://guides.github.com/features/mastering-markdown/)

Not familiar with Vue? No worries, we'll be providing the details you need to use it within this project. You _will_ need to use some JavaScript, though, as you build your default code and validation.

##### Vue file

Select the appropriate boilerplate Vue file for your lesson from the `tutorials/boilerplates` directory:

- `boilerplate-standard.vue` for a lesson with an exercise which does not require a file upload
- `boilerplate-file-upload.vue` for a lesson with an exercise that requires a file upload
- `boilerplate-standard.vue` for a lesson with a coding excercise which does not require a file upload
- `boilerplate-file-upload.vue` for a lesson with a coding exercise that requires a file upload
- `boilerplate-no-exercise.vue` for a text-only lesson

Copy that boilerplate into your tutorial folder and rename it to the 2-digit number of the lesson.
Expand All @@ -55,11 +78,13 @@ Example (while in `tutorials`):

Replace anything in the boilerplate file that reads "REPLACEME".

If your lesson includes a coding exercise, you'll also use this file to set up your default code and validation, as described later in these instructions.


#### Markdown file
##### Lesson text file

Create a `.md` file alongside your `.vue` and add the markdown formatted text
of the lesson. The name of this file should match the 2-digit lesson number used
Create a `.md` file alongside your `.vue` and add the markdown-formatted text
of the lesson itself (your educational content). The name of this file should match the 2-digit lesson number used
in the corresponding Vue file.

Example:
Expand All @@ -68,17 +93,168 @@ Example:
tutorials/Tutorial-Shortname/01.md
```

#### Exercise file (skip for text-only lessons)

Create a second `.md` file alongside your `.vue` and add the markdown formatted text that provides the assignment text for the exercise box. The name of this file should match the 2-digit lesson number used previously, with `-exercise` appended.
##### Exercise text file (skip for text-only lessons)

If your lesson includes a coding exercise, create a second `.md` file and add the markdown-formatted text that provides the assignment text for the exercise box. The name of this file should match the 2-digit lesson number used previously, with `-exercise` appended.

Example:

```
tutorials/Tutorial-Shortname/01-exercise.md
```
##### Useful concepts text file (optional)

Ocassionally you may want to add a _useful concepts_ box defining key terminology, if this can't easily be done in-line. If you'd like to do this, create another `.md` file that provides the text for that _useful concepts_ box. The name of this file should match the 2-digit lesson number used previously, with `-concepts` appended. (This step is optional.)

Example:

```
tutorials/Tutorial-Shortname/01-concepts.md
```

#### Build code challenges and validation in your Vue file (skip for text-only lessons)

If you are creating a lesson with a code challenge (whether or not it requires file upload), you'll need to provide default code and set up validation in the lesson's Vue file. The basic template you need to accomplish this is provided in the boilerplate file you selected earlier.

#### Provide the starting code for your exercise

`code` is a string property. The value you set for `code` in your Vue file will
be used to populate the code
editor when the user first visits the page. (If you forget to set this, a default
will be used, but your exercise won't be very useful!)

```js
const code = `const run = async () => {
/* your code here */
}
return run
`
```
Your default `code` will always have this exterior `run` function, inside of which
your user creates their own code. The code your user writes will almost always
include returning a value from the interior function.

As you decide what starting code to provide for each lesson, think about how you
can isolate the action the user needs to take to a single step, representing the
concept they've learned in this particular lesson.

In practice, most lessons build off of previous ones, and code is repeated and
built on between exercies. You will often need to pre-populate in your lesson the
correct solution to a previous lesson or lessons, so that the current exercise can
test adding only the most recent method taught.

You should also think about how you might provide support for programming language
challenges and limit the assignment to executing methods that practice your lesson
content.

Remember that you can add comments to your default code to orient the user, such as:
```js
// your code goes here
```

### Update routes and import statements in `main.js`

#### Validate the user's submitted code

Feedback is key to a positive learning experience. As the author of a tutorial, you'll need to give careful thought both to how you'll verify that your user has submitted successful code and to what mistakes they might make along the way. It's your responsibility to anticipate challenges and provide helpful clues accordingly.

To do this, you'll use the `validate` function found in the boilerplate, which takes this format:

`validate(result, ipfs)`


When the sample code area is evaluated, it must return a function, usually an
async function. The result of that function is passed to your validation
function as `result`.

Each time the user's code is evaluated, they get a new, clean, IPFS instance.
That instance is passed as the second argument, `ipfs`.

You may want to use both the `result` and `ipfs` values when building conditional statements to evalute the success or failure of the user's code submission. If needed, check out this primer on [using conditionals in JavaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/conditionals).

Your `validate` function must return an object with one of two properties: `fail` or
`success`. Each property should be used to give a detailed message (as a string) either congratulating the user or explaining *why*
the sample code failed in order to help the user along.

```js
const validate = async (result, ipfs) => {
if (!result) {
return { fail: 'You forgot to return a result :)' }
} else if (result) {
return { success: 'Happy Message!'}
} else {
return { fail: 'Sad but useful message :('}
}
}
```
Be sure to include conditionals that will catch common mistakes and provide useful clues.

If the object returned by your `validate` function the has the property `fail`, the message string you've provided will be shown highlighted in red, and the user will have the opportunity to update and resubmit their code. If it has the property `success`, the user will se the success message highlighted in green, and the "Submit" button will change into a "Next" button allowing them to advance to the next lesson.

##### Override external error messages (optional)

As you test your code, you may notice that you see error messages appear that are different from the ones you provided in your `validate` function. These might include syntax errors noted by our embedded code editor or errors returned by the IPFS API, both of which appear by default. Syntax errors can be very helpful for your user, and other errors might help you identify common errors you hadn't thought of.

If you'd like to replace a specific error message returned automatically with a moire user-friendly message created by you, add the attribute
`:overrideErrors="true"` to the Lesson (or FileLesson) component at the start of your Vue file like so:

```js
<Lesson // or FileLesson
:overrideErrors="true"
...
/>
```

Within the `validate` function, add cases for the specific error messages
you need to override, as in this example:

```js
} else if (result && result.error.message === 'No child name passed to addLink') {
// Forgot the file name and just used a directory as the path
return { fail: 'Uh oh. It looks like you created a folder instead of a file. Did you forget to include a filename in your path?' }
}
```

You'll also need to add the following lines below your custom validation so that
external error messages you haven't specifically overridden will continue to be shown to the user to aid in troubleshooting:

```js
// Output the default error if we haven't caught any
return { error: result.error }
```

Note that most tutorial lessons will _not_ require the overriding of external
errors. If you have questions about whether to use this optional feature, please reach
out to the project maintainers for guidance.

##### Display results to the user (optional)

When the user submits their code successfully, they'll receive a success message you've provided in your `validate` function (see above). If you'd like to also show some data to the user to help them understand the results of their code, it's possible to add an additional step after code submission.

In the `validate` function, when returning either a *fail* or a *success*, add `log` and `logDesc` (optional) keys with values, as in this example:

```js
const ipfsFiles = ipfs.files.ls('/foo')

if (result === 'foo') {
return { success: 'Happy Message!' }
} else if (result === 'bar') {
return {
success: 'You did it!',
logDesc: 'Check out the data now stored in your IPFS instance:', // A description of the data you're displaying
log: ipfsFiles // The data you want the user to see
}
} else {
return { fail: 'Sad but useful message :(' }
}
```

When you use this option, a new section will appear below the exercise box, showing your `logDesc` message followed by the `log` data.


#### Update routes and import statements in `src/main.js`

To ensure your lessons appear on the website (and in your local preview), you'll need to add routes and import statements for each lesson in `src/main.js`

First, import each of your lesson components:

Expand Down Expand Up @@ -131,7 +307,9 @@ your third lesson will display the following under the lesson title:
Notice how multi-word lesson shortnames are treated here. In filepaths, they are lowercase and hyphenated (e.g. `/data-structures/01`). In component names they are upper camel case (smushed together with the first letter of each word capitalized, e.g. `LessonDataStructures01`).


### Add your tutorial to `tutorials.json` and `courses.json`
#### Add your tutorial to `tutorials.json` and `courses.json`

Although the step above ensures that your lessons are available at specific URLs on the website, you'll also need to ensure that your tutorial appears in our course listings.

In `static/tutorials.json`, add a new key for your tutorial (for example, `tutorialShortname` as shown in the example below) and fill in the appropriate values:

Expand Down Expand Up @@ -169,55 +347,6 @@ In `static/courses.json`, add the tutorial key to the `all` array so it will app
The project maintainers will take care of making any updates needed to ensure your project is featured in any relevant course listings.


## Boilerplate Explained

```javascript
import Lesson from '../Lesson'
import text from './REPLACEME.md'

const validate = async (result, ipfs) => {
if (result) {
return {'success': 'Happy Message!'}
} else {
return {'fail': 'Sad but useful message :('}
}
}

// const code = `const run = async () => {}
// return run
// `

export default {
components: {
Lesson
},
data: () => {
return {
text, validate//, code
}
}
}
```

### validate(result, ipfs)

When the sample code area is evaluated, it must return a function, usually an
async function. The result of that function is passed to your validation
function as `result`.

Each time the user's code is evaluated they get a new, clean, IPFS instance.
That instance is passed as the second argument, `ipfs`.

Validate must return an object with one of two properties: `fail` or
`success`. Each property should be used to give a detailed message of *why*
the sample code failed in order to help the user along.

### code

Code is a string property. It's the sample code used to populate the code
editor. If not set there's a default, used in the first lesson, that is used
instead.

## License

ProtoSchool is licensed under the Apache-2.0 and MIT licenses. See [LICENSE.md](https://github.com/protoschool/protoschool.github.io/blob/master/LICENSE.md) for further detail.
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"shallow-equal": "^1.0.0",
"tachyons": "^4.11.1",
"vue": "^2.5.16",
"vue-highlightjs": "^1.3.3",
"vue-monaco-editor": "0.0.19",
"vue-router": "^3.0.1"
},
Expand Down
1 change: 0 additions & 1 deletion src/components/File-Lesson.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const run = async (files) => {
}

return run

`

export default {
Expand Down
Loading