Skip to content

Commit

Permalink
Merge branch 'main' into sdc-tools-sprint3and4
Browse files Browse the repository at this point in the history
  • Loading branch information
SallyMcGrath authored Feb 2, 2025
2 parents 70abc83 + 3f09fa1 commit ab96743
Show file tree
Hide file tree
Showing 34 changed files with 920 additions and 266 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Curriculum Platform
# Common Curriculum Platform
[![DPG Badge](https://img.shields.io/badge/Verified-DPG-3333AB?logo=data:image/svg%2bxml;base64,PHN2ZyB3aWR0aD0iMzEiIGhlaWdodD0iMzMiIHZpZXdCb3g9IjAgMCAzMSAzMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0LjIwMDggMjEuMzY3OEwxMC4xNzM2IDE4LjAxMjRMMTEuNTIxOSAxNi40MDAzTDEzLjk5MjggMTguNDU5TDE5LjYyNjkgMTIuMjExMUwyMS4xOTA5IDEzLjYxNkwxNC4yMDA4IDIxLjM2NzhaTTI0LjYyNDEgOS4zNTEyN0wyNC44MDcxIDMuMDcyOTdMMTguODgxIDUuMTg2NjJMMTUuMzMxNCAtMi4zMzA4MmUtMDVMMTEuNzgyMSA1LjE4NjYyTDUuODU2MDEgMy4wNzI5N0w2LjAzOTA2IDkuMzUxMjdMMCAxMS4xMTc3TDMuODQ1MjEgMTYuMDg5NUwwIDIxLjA2MTJMNi4wMzkwNiAyMi44Mjc3TDUuODU2MDEgMjkuMTA2TDExLjc4MjEgMjYuOTkyM0wxNS4zMzE0IDMyLjE3OUwxOC44ODEgMjYuOTkyM0wyNC44MDcxIDI5LjEwNkwyNC42MjQxIDIyLjgyNzdMMzAuNjYzMSAyMS4wNjEyTDI2LjgxNzYgMTYuMDg5NUwzMC42NjMxIDExLjExNzdMMjQuNjI0MSA5LjM1MTI3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==)](https://digitalpublicgoods.net/r/code-your-future)


> [!TIP]
> Our curriculum in action: https://curriculum.codeyourfuture.io
> Our curriculum in action: https://curriculum.codeyourfuture.io
> Curriculum platform docs: https://common.codeyourfuture.io
## What is this?
Expand Down
84 changes: 0 additions & 84 deletions common-content/en/module/js3/asynchrony/index.md

This file was deleted.

36 changes: 7 additions & 29 deletions common-content/en/module/js3/capturing-events/index.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
+++
title = 'Capturing the user event'

time = 15
time = 20
emoji= '🦻🏻'
[objectives]
1='Add an event listener to a user input'
[build]
render = 'never'
list = 'local'
publishResources = false

+++

We've introduced our state, and our render works for different values of that state. But users of our website can't change the `searchTerm` state themselves. We need to introduce a way for them to change the `searchTerm` state via the UI.
Expand All @@ -26,33 +24,13 @@ function handleSearchInput(event) {
}
```

When the "input" event fires, our handler function will run. Inside the handler we can access the updated input value: `const searchTerm = event.target.value;`

So our key steps are:

1. Add an input event listener to the search box
2. In the handler, get `value` of input element
3. Set the new state based on this value.
4. Call our `render` function again.

{{<note type="warning" title="One thing at a time!">}}
But we're not going to do all of these at once! Stop and implement just the first two steps (adding the event listener, and getting the value), and `console.log` the search term.

{{</note>}}

We will make sure this works before we try to change the UI. Why? If we try to add the event listener and something _doesn't_ work, we will only have a little bit of code to debug.

If we tried to solve the whole problem (updating the UI) and something didn't work, we would have a _lot_ of code to debug, which is harder!

We've now demonstrated that we can capture search text on every keystroke:
These listeners wait for specific events to occur, and when they do, they trigger a callback function we've defined. This gives us a way to make our code respond to user actions rather than running all at once.

```js
const searchBox = document.getElementById("search");
const search = document.getElementById("search");
search.addEventListener("input", handleInput);
```

searchBox.addEventListener("input", handleSearchInput);
When we call `addEventListener`, it doesn't immediately execute the `handleInput` function. Instead, it sets up a listener that will run this function later. Event listeners are part of the web browser's Event API. But event listeners themselves aren't part of the core JavaScript language! When you create an event listener, you're making a request to a Web API to handle this functionality for you. In this pattern, the callback function (`handleInput`) only executes when a user types. These callback functions need to execute in response to user interactions. This lets us tell the browser exactly what actions to take once a particular event occurs.

function handleSearchInput(event) {
const searchTerm = event.target.value;
console.log(searchTerm);
}
```
Callback functions are essential for handling user interactions in web browsers. They allow our code to execute in response to an event. The browser listens for events and executes our callback functions at the right time. It is our job to define what should happen when those events occur.
31 changes: 31 additions & 0 deletions common-content/en/module/js3/re-rendering/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,37 @@ emoji= '🔁'

+++

When the "input" event fires, our handler function will run. Inside the handler we can access the updated input value: `const searchTerm = event.target.value;`

So our key steps are:

1. Add an input event listener to the search box.
2. In the handler, get the `value` of input element.
3. Set the new state based on this value.
4. Call our `render` function again.

{{<note type="warning" title="One thing at a time!">}}
But we're not going to do all of these at once! Stop and implement just the first two steps (adding the event listener, and getting the value), and `console.log` the search term.

{{</note>}}

We will make sure this works before we try to change the UI. Why? If we try to add the event listener and something _doesn't_ work, we will only have a little bit of code to debug.

If we tried to solve the whole problem (updating the UI) and something didn't work, we would have a _lot_ of code to debug, which is harder!

We've now demonstrated that we can capture search text on every keystroke:

```js
const searchBox = document.getElementById("search");

searchBox.addEventListener("input", handleSearchInput);

function handleSearchInput(event) {
const searchTerm = event.target.value;
console.log(searchTerm);
}
```

Now that we've shown we can log the search text, we can set the new value of the `searchTerm` state, and re-render the page.

We should have a page like this:
Expand Down
43 changes: 43 additions & 0 deletions common-content/en/module/js3/synchronous-execution/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
+++
title = 'Synchronous execution'

time = 10
emoji= ''
[objectives]
1="Define asynchrony"
2="Explain how synchronous execution works"
[build]
render = 'never'
list = 'local'
publishResources = false
+++

We can handle latency using {{<tooltip title="asynchronous execution">}}Asynchronous execution is running code in a different order than it was written.{{</tooltip>}} To understand asynchrony we first need to be clear about {{<tooltip title="synchronous execution">}}Synchronous execution is running code in the order it is written.{{</tooltip>}}.

We have written a lot of JavaScript programs that execute sequentially. This means that each line of code is run in order, one after the other.
{{<columns>}}

#### For example:

```js
console.log("first");
console.log("second");
console.log("third");
```

<--->

#### Outputs:

```console
first
second
third
```

{{</columns>}}
Each line of code is run in order. This is synchronous execution. We do this because JavaScript is {{<tooltip title="single threaded">}}
A single thread can do one thing at a time. JavaScript is a single threaded language.
{{</tooltip>}}.

When we call a function, the function will run to completion before the next line of code is executed. But what if we need to wait for something to happen? What if we need to wait for our data to arrive before we can show it? In this case, we can use **asynchronous execution**.
52 changes: 39 additions & 13 deletions common-content/en/module/js3/using-fetch/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,43 @@ emoji= '🌐'
render = 'never'
list = 'local'
publishResources = false

+++

So now we have these pieces of our giant concept map
So now we have these pieces of our giant concept map:

1. 📤 We know that we can send a request using `fetch()`
2. 🐕 We know that `fetch` is a 💻 client-side 🧰 Web API that requires an HTTP connection
3. 🗓️ We know that sending requests over a network takes time
4. 🧵 We know that we should not stop our program to wait for data
5. 🪃 We know that we can use Promises to manage asynchronous operations

But we still don’t know how to use `fetch` to get data from a server side API.

1. 📤 we know that we can send a request using `fetch()`
1. 🐕 we know that `fetch` is a 💻 client side 🧰 Web API
1. 🗓️ we know that sending requests over a network takes time
1. 🧵 we know that we should not stop our program to wait for data
1. 🪃 we know that we can use callbacks to manage events
### Loading html files

But we still don’t know how to use `fetch` to get data from a server side API. Let’s find this out now.
When you double-click an HTML file in your file explorer to open it directly in your browser, you're using what's called the "file protocol" or "file scheme." In your browser's URL bar, you'll see something like:

Let's pick our film display exercise back up. Before we had a list of films hard-coded in our `state`. We're going to replace the films array with data fetched from a server.
```
file:///Users/username/projects/my-website/index.html
```

The `file://` prefix indicates that your browser is reading the file directly from your computer's filesystem, without going through a web server. While this approach might seem convenient for simple HTML files, it will prevent us from using `fetch`.

### Web Server Access: The HTTP Protocol

Another approach involves using a local development server. You can create one using tools like [Python's built-in server](https://realpython.com/python-http-server/) or [npm's http-server](https://www.npmjs.com/package/http-server). These tools create a web server on your computer that serves your files using the HTTP protocol. Your browser will then access the files through a URL like:

```
http://localhost:8000/index.html
```

The `http://` prefix shows that you're accessing the file through a proper web server, even though that server is running on your own computer.

You need to be using `http://` (or `https://`) _not_ `file://` in order to use `fetch`.

## Using `fetch`

Previously, we had a list of films hard-coded in our `state`. Now, let's continue using our concept map to fetch data from a server.

```js
// Begin with an empty state
Expand All @@ -36,15 +59,18 @@ const endpoint = "https://programming.codeyourfuture.io/dummy-apis/films.json";
const fetchFilms = async () => {
const response = await fetch(endpoint);
return await response.json();
}; // Our async function returns a Promise
};

fetchFilms().then((films) => {
// When the fetchFilms Promise resolves, this callback will be called.
state.films = films;
render();
});
```

`fetch` returns a `Promise`; the `Promise` fulfils itself with a response; the response contains our data.
{{<note type="remember" title="Serving files locally">}}
Remember: If you see an error message about fetch not being allowed from `file://` URLs, that's your signal to serve your files through a local development server instead of opening them directly in the browser.
{{</note>}}

fetch returns a Promise; the Promise fulfils itself with a response; the response contains our data.

Next we will dig into `Promise`s, `async`, `await`, and `then`, and complete our concept map.
Next, we'll dig into `Promise`s, `async`, `await`, and `then` in more detail to complete our concept map.
2 changes: 1 addition & 1 deletion common-content/en/module/piscine/kickoff/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ It's important that software works and the people can use it

## 🎯 Goal:

You will be split randomly into groups of 3-4.
You will be split randomly into groups of 2-4.

{{<note type="activity" title="Kickoff">}}

Expand Down
56 changes: 56 additions & 0 deletions common-content/en/module/piscine/practice-break-down/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
+++
title = "Practice breaking down a requirement"
time = 60
objectives = [
"Break down a requirement into approachable tasks.",
"Coordinate multiple team members in executing tasks in parallel.",
]
[build]
render = "never"
list = "local"
publishResources = false
+++

In team projects, it's important that we break large tasks down into small tasks.

It's also important that we can coordinate across our team. This requires having shared understanding of who will do what, and how the work we do will interact.

Finally, it's important that we arrange tasks so your team isn't blocking yourselves, so you'll want to find ways of working on tasks in parallel.

We will practice this together on the two of the requirements of the project:

- Selecting a user must display the agenda for the relevant user (see manual testing below)
- Submitting the form adds a new topic to revise for the relevant user only

To complete these requirements we'd need to build most of the project! So we'll focus on simplified versions of these requirements:

- When the page loads, display one revision date for one topic from in User 1's stored agenda
- When clicking a button, store {{<tooltip title="hard-coded">}}Hard-coding refers to when developers directly write values or data into code, often replacing variables or user input with static values.{{</tooltip>}} data for User 1's agenda

To complete the full requirements, you can build on the tasks we decide on today.

{{<note type="exercise" title="Breaking down tasks">}}

1. Set a timer for {{<timer>}}5{{</timer>}}
2. Individually, write down all the tasks that would be needed to complete the simplified requirements above
3. After the timer is up, go around the group and discuss the tasks you came up with. One of the volunteers should write the tasks on a whiteboard
4. Volunteers, discuss any that you think might be missing or that might need breaking down further

{{</note>}}

Looking ahead to your coursework for the next week, one of your tasks will be to [Refine a ticket](https://github.com/CodeYourFuture/The-Piscine/issues/6).

{{<note type="exercise" title="Refining tickets">}}

1. Everyone read the [Refine a ticket coursework task](https://github.com/CodeYourFuture/The-Piscine/issues/6), for {{<timer>}}3{{</timer>}} minutes.
2. Get into pairs. Each pair should then pick 2 of the tasks from the whiteboard (it doesn't matter if multiple pairs do the same task). Spend {{<timer>}}10{{</timer>}} minutes refining your tickets in your pairs. Make sure you work through **all** of the workflow points.
3. Go around each pair in the group. The pair should pick 1 of their tasks and say what they think the priority, estimate, schedule and type of work the task is, and if there is anything they would need to know before starting the ticket. (Hint: the last point is **important**! Don't skip it!)
4. As a group, pick a task (or two, depending on time) that needs more information. Spend {{<timer>}}10{{</timer>}} minutes discussing what actions you could take to ensure everyone has what they need to complete this task?

{{</note>}}

{{/*
TODO: The Piscine is meant to be pure evaluation with no teaching.
Ideally ITP would provide this experience so we wouldn't need to teach it in the Piscine.
But right now ITP doesn't teach these skills, so we fill that gap so we're not testing people on things they don't know.
*/}}
11 changes: 10 additions & 1 deletion common-theme/layouts/_default/day-plan.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@
<time-stamper start-time="{{$startTime}}">
<div class="c-block__series c-block__series--timeline">
{{ if ne .Params.noRegister true }}
{{ partial "register-attendance.html" (dict "course" site.Title "module" $.Page.CurrentSection.Parent.Title "day" $.Page.CurrentSection.Title) }}
{{ $moduleSection := $.Page.CurrentSection }}
{{/* Most of our modules have two levels of hierarchy - course > module > sprint. But some go straight course > sprint or module > sprint - allow opting into this with a param. */}}
{{ $parentsToTraverseToModule := $moduleSection.Params.parentsToTraverseToModule }}
{{ if eq $parentsToTraverseToModule nil }}
{{ $parentsToTraverseToModule = 1 }}
{{ end }}
{{ range seq $parentsToTraverseToModule }}
{{ $moduleSection = $moduleSection.Parent }}
{{ end }}
{{ partial "register-attendance.html" (dict "course" site.Title "module" $moduleSection.Title "day" $.Page.CurrentSection.Title) }}
{{ end }}
{{ range $index, $block := .Params.blocks }}

Expand Down
Loading

0 comments on commit ab96743

Please sign in to comment.