Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1 1
So using the workout classes 2
2
that we just implemented, 3
3
let's now finally implement the feature 4
4
of creating a new workout from our user interface. 5
5
And to start, let's take a look at our flowchart here. 6
6
And so basically, this here is the action 7
7
that we're interested in now 8
8
so when the user submits a new workout. 9
9
And so we already added this new workout method here 10
10
as an event handler function for that event. 11
11
And so what we want to happen now 12
12
is to basically render the workout on the map, 13
13
render the workout on the list 14
14
and then this part here, we're gonna leave for later. 15
15
So this one is the high level overview 16
16
of what needs to happen. 17
17
But actually, there's a lot more things involved 18
18
than just these immediate actions 19
19
that we see on the user interface. 20
20
So actually, we're gonna leave the rendering here 21
21
for the next video, 22
22
because as I just said, 23
23
there's actually a lot of other stuff 24
24
that we have to do, now right? 25
25
So as you see, we are back here at looking at the flowchart 26
26
because now we are back to being interested 27
27
what we actually need to implement, 28
28
and not how to implement it, right? 29
29
So the architecture here, again, 30
30
is about how we implement it. 31
31
And so it contains all of these different methods 32
32
and these low level details, 33
33
while the flowchart here 34
34
is really more of a high level overview 35
35
of what we want to implement. 36
36
And so for now, we don't need the architecture anymore, 37
37
because we already put everything into the code 38
38
that we had here. 39
39
Now, if you're really curious 40
40
and want to spoil the experience, 41
41
basically until the end of the section, 42
42
then you can already take a look 43
43
at the final architecture here 44
44
but I'm not gonna do that. 45
45
So I just want to now keep building 46
46
the rest of the application as we go, okay? 47
47
But anyway, since this is so high level here, 48
48
let's actually go to the working demo application 49
49
and see what exactly happens. 50
50
So let's reload here. 51
51
And so let's click just somewhere. 52
52
And then you see, as we already know, the form opens, 53
53
then we can input some data here 54
54
and then our application needs to get this data, 55
55
it needs to check if the data actually makes sense. 56
56
And then we need to create a new object 57
57
for this workout and render it right here 58
58
and also on the map, of course. 59
59
And then finally, after all that the form is also hidden. 60
60
So everything I just said is gonna happen 61
61
whenever we hit enter here. 62
62
So you see, of course, the marker was created, 63
63
it was rendered here, 64
64
all the input data had to be checked, 65
65
and a new running object was created. 66
66
So for example, if we add another one, 67
67
but without any data, 68
68
then we are gonna get this alert. 69
69
Or the same if we input any data 70
70
that doesn't make much sense. 71
71
For example, a negative number for the cadence, 72
72
which is of course impossible. 73
73
And so again, we get this error here. 74
74
So input validation is an important part 75
75
of creating any application that works with user inputs. 76
76
And so let's now actually work on the function 77
77
that is responsible for doing all of this. 78
78
And for starters, I will basically document 79
79
everything that we need to do here using comments. 80
80
So first, we need to get data 81
81
from the form, then we need to check 82
82
if data is valid, 83
83
then if it's running, 84
84
so if the activity running, then create running object. 85
85
And if the activity is cycling, 86
86
then of course, create a cycling object. 87
87
Then add the new object to the work out array. 88
88
And so, yeah, instead of activity, 89
89
let's actually call it work out here. 90
90
Then we want to render, 91
91
workout on map as a marker 92
92
and finally, we want to render 93
93
the new workout on the list. 94
94
And finally also, we want to then hide the form 95
95
and clear the input fields. 96
96
So you see there's gonna be a lot of work. 97
97
Let's put this one for now at least here, 98
98
even though it's not gonna really work like this. 99
99
But okay, so with this, we now have all the steps lined out 100
100
and so let's get started. 101
101
And we're gonna start by getting the data from the forum 102
102
and starting with the type, 103
103
and type is already stored at the variable input type. 104
104
So that's all the way up here. 105
105
Let's bring that down, actually. 106
106
And we could even add these elements here 107
107
basically as fields also inside of the application. 108
108
But in this case, I prefer not to do that 109
109
because then every time that we wanted to reference 110
110
one of these elements, 111
111
then we would always have to use like this .inputDistance, 112
112
or duration, and so on and so forth. 113
113
And I just don't really like that. 114
114
But anyway, let's not take the values of input type, 115
115
distance, duration, cadence and elevation. 116
116
And these two here are not that straightforward 117
117
but let's see that in a minute. 118
118
So inputType.value. 119
119
And so input type is actually a select element. 120
120
But still, we get the value using the value property. 121
121
Let me just show that to you. 122
122
And so, yeah, here it is. 123
123
And so each option has this value. 124
124
And so for running, the value is running 125
125
with the lowercase r, and for cycling the same, okay? 126
126
And so again, the value will be 127
127
whatever of these two is selected, 128
128
and then we get this value here. 129
129
And so that will be important in a minute. 130
130
But anyway, let's not take the distance. 131
131
So that's inputDistance.value 132
132
and remember that this always comes as strings 133
133
and so let's convert that immediately to a number. 134
134
Then the duration. 135
135
Let's do the same here, inputDuration.value. 136
136
Now about the cadence and the elevation gain, 137
137
we actually don't want to get them 138
138
here right in the beginning. 139
139
But the cadence, we only want to get 140
140
if it is a running workout. 141
141
And the elevation gain, 142
142
we only want to get if it is a cycling workout, 143
143
because that will then make it easier for us 144
144
to validate the data. 145
145
But more about that in a second. 146
146
So for now, let's actually check 147
147
what kind of workout we are dealing with. 148
148
And so all we have to do is to check the type. 149
149
And if it's running, 150
150
then we want to get the cadence. 151
151
So let's call that cadences as well 152
152
and convert inputCadence.value to a number. 153
153
But if we are dealing with cycling, 154
154
then we want the elevation gain. 155
155
So let's called this one 156
156
elevation and here it's also called input elevation. 157
157
Now okay, and so now let's check if the data is valid. 158
158
And so we will not do that 159
159
inside of each of these if statements. 160
160
Now you might have noticed 161
161
that I actually created two separate if statements here 162
162
instead of an if else statement. 163
163
And that's just something that you will see more and more 164
164
in modern JavaScript. 165
165
So the if else is not really that much used anymore. 166
166
And I think that actually it looks a lot cleaner like this 167
167
so to simply have two if statements. 168
168
So anyway, let's not check if the data is valid. 169
169
And what does it mean for the data to be valid? 170
170
Well, first of all, each of them should be a number, right? 171
171
And so let's do that. 172
172
And here again, we will actually use a guard clause. 173
173
So again, what a guard clause means 174
174
is that we will basically check for the opposite 175
175
of what we are originally interested in 176
176
and if that opposite is true, 177
177
then we simply return the function immediately. 178
178
And so once again, 179
179
this is a trait of more modern JavaScript. 180
180
So kind of a trend that you will see in modern JavaScript. 181
181
But anyway, let me show you what I mean here. 182
182
So if the distance is not a number, 183
183
and remember that for that, we use a Number.isFinite. 184
184
So if the distance here is not a number, 185
185
then we want to return immediately. 186
186
So we want to return 187
187
and then we can also do some other code here. 188
188
So let's create an alert. 189
189
So inputs have to be positive numbers. 190
190
And so for now we check for numbers 191
191
but we didn't yet check for positive. 192
192
But let's leave that for a second. 193
193
So we should already be able to test out 194
194
if this if here is gonna work. 195
195
So let's just see if our map appears here. 196
196
And let's try to reload here. 197
197
And for some reason, sometimes 198
198
this takes a really long time. 199
199
So sometimes while I was developing this application, 200
200
I waited up to like two or three minutes 201
201
and I don't know why that happens. 202
202
But yeah, I hope that never happens for you. 203
203
But in case you see long waiting times, 204
204
that might be normal, all right? 205
205
But now here it is. 206
206
And so let's input some invalid distance. 207
207
So like just any letter, 208
208
and then we get inputs have to be positive numbers. 209
209
So that is already working. 210
210
And now we just need to do the same with the other inputs. 211
211
So we want the same for the distance. 212
212
So Number.isFinite. 213
213
So actually, for duration 214
214
and then the same thing for Number.isFinite cadence, okay? 215
215
Now, this is actually not correct, 216
216
because we don't want the and but instead, we want or. 217
217
So this one here should happen 218
218
whenever one of these three here is not a number 219
219
and not when all of them are invalid numbers, right? 220
220
And so that's exactly what or means. 221
221
So if this one is an invalid number, 222
222
or this one, or this one, then we can get this alert. 223
223
And so the reason why we did this checking here 224
224
inside of this if block 225
225
is because if we did the same out here, 226
226
then we would also want to check for the elevation, right? 227
227
But as we know already, 228
228
only one of the cadence and elevation 229
229
can be defined at the same time, 230
230
they cannot both be defined at the same time. 231
231
And so performing this check 232
232
would then be a little bit more difficult. 233
233
So now we can go ahead and do the same thing down here. 234
234
So in the cycling part, 235
235
but let's actually refactor this code here already. 236
236
And basically create a small function, 237
237
which takes a number of arguments, 238
238
and will then validate if all of them 239
239
are numbers or not, okay? 240
240
So basically, we wanted to work like this 241
241
but we wanted to write this 242
242
in a more clear and more beautiful 243
243
so to say, way, all right? 244
244
So let's create a very simple helper function here. 245
245
And let me call it validInputs. 246
246
So a very simple arrow function 247
247
and this can take an arbitrary number of inputs. 248
248
And remember that when we use rest parameters like this, 249
249
then we get an array. 250
250
So inputs is an array 251
251
and we now want to loop over this array, 252
252
and basically check if all of them are positive. 253
253
Now there's actually already a predefined method 254
254
in JavaScript, that is very helpful for that. 255
255
So remember that we have a nice little method called every. 256
256
And so let's use it here. 257
257
And then I will quickly explain what it does. 258
258
So the current input, 259
259
and then Number.IsFinite, the current input. 260
260
So basically, this will loop over the array, 261
261
and then each of them, 262
262
it will check whether the number is finite or not. 263
263
And then in the end, the every method 264
264
will only return true if this value here 265
265
was true for all of them. 266
266
So for all elements in the array. 267
267
But if only one of these values here was not finite, 268
268
so if the result here was false 269
269
for one of the elements of the array, 270
270
then every will return false. 271
271
And so that will then be the return value 272
272
of this arrow function, right? 273
273
And so then here, we can replace all of this. 274
274
And let's actually just comment it out. 275
275
We cannot say if not validInputs, 276
276
and then pass in the three that we're interested in. 277
277
So distance, duration, and cadence. 278
278
And again, here we are inverting the condition, right? 279
279
So if all of these are numbers, 280
280
then this here will become true, right? 281
281
But whenever this is not true, 282
282
then that's the case where we want to return 283
283
from the function and show this alert Window, all right? 284
284
So let's copy this 285
285
and do the same here for the elevation like this. 286
286
And here, I will get rid of the comments. 287
287
And so this is the first check. 288
288
But in fact, we also want to test 289
289
if the numbers are positive, 290
290
because otherwise, they don't make much sense. 291
291
So let's reload here again. 292
292
So right now, if I put a letter in any of these, 293
293
then it's not gonna work, right? 294
294
But if I put in a negative number of steps, 295
295
then this is perfectly acceptable 296
296
and we already get the marker here printed to the map. 297
297
But in fact, we don't want this to be acceptable. 298
298
So negative values should not be allowed 299
299
for any of these three. 300
300
But in the cycling, it should be allowed 301
301
for the elevation gain. 302
302
So here, we can, of course have a negative number, 303
303
which happens when we go basically down a mountain, right? 304
304
So that's simple as well, 305
305
all you have to do is to check if these three values here 306
306
are greater than zero, and the same for these two, 307
307
but not for the elevation, okay? 308
308
And so actually, to make this really cool, 309
309
I will create another small helper function like this one. 310
310
And it might be a good habit for you as well 311
311
to get used to these small helper functions. 312
312
So they're especially nice in these situations 313
313
for testing complex conditions. 314
314
So instead of writing all of this, 315
315
and plus checking now for positive numbers, 316
316
we can simply export that into one or two functions, 317
317
which then do the job for us. 318
318
So here, I'm gonna create a function called all positive, 319
319
and this one is gonna be almost the same 320
320
as the previous one. 321
321
So it takes in an arbitrary amount of inputs. 322
322
And then we will only return true if all of them 323
323
are greater than zero. 324
324
And so here the every method is very useful again. 325
325
So input, and then here, we need some condition 326
326
that returns true or false. 327
327
And so that's input greater than zero. 328
328
And so let's not use that here. 329
329
And so we want basically, 330
330
if all of the inputs are not valid, 331
331
or if there is basically any number that is not positive. 332
332
So if not all positive 333
333
distance, duration, and cadence, all right? 334
334
So in this case, we then want to get this alert 335
335
and now here, let's do the same for the cycling. 336
336
But here, we are only interested in distance and duration, 337
337
because again, the elevation might very well be negative. 338
338
So this is a little bit complex validation 339
339
but that's no problem at all. 340
340
That's why I spent some time here on this validation 341
341
without any problem. 342
342
Now, it would have been a little bit easier 343
343
if we didn't have these different values 344
344
of elevation and cadence for the two different workouts. 345
345
But we do have it and yeah, 346
346
so we have to solve that problem. 347
347
And so I think it works really nice like this. 348
348
Let me just check it out here one more time now 349
349
with these negative values. 350
350
So if we have a negative distance, 351
351
then now indeed, we get the alert to accept for cycling. 352
352
So let's remove that one, and two, two 353
353
and two here minus two, but that still works. 354
354
And so clearly, our validation logic here is just fine. 355
355
Great, so next up, let's see what we have to do. 356
356
So actually, we still have to finish these ones. 357
357
So if the workout is running, 358
358
then create a running object 359
359
and otherwise, create a cycling object, now right? 360
360
And then afterwards, push that object to the workout array. 361
361
So add it to the array 362
362
and for that, we're gonna use the push method as always. 363
363
So let's start with this one here, 364
364
right after this guard clause, all right? 365
365
And so here, let's say, work out, should be a new running. 366
366
And now let's see what we need for running. 367
367
Or actually, we can probably just hover this 368
368
and indeed, here we have two coordinates, 369
369
distance, duration and cadence, all right. 370
370
So where do we get the coordinates from? 371
371
Well, we already know from the marker 372
372
that they are right here. 373
373
So in this.MapEvent.latitudelongitude. 374
374
So we notice because we already used this data before 375
375
to render a marker on the map. 376
376
So let's get this one and paste it here 377
377
as the first argument. 378
378
But actually, this here is now gonna be an object. 379
379
So we know that because here we use destructuring, 380
380
to get the latitude and longitude out of that object. 381
381
But up here, we said, 382
382
so in the class definition, 383
383
that indeed we want an array, right? 384
384
So let's simply get this code from here, to up there. 385
385
So here, and so basically create 386
386
the latitude and longitude variables here 387
387
based on this object. 388
388
And so then here, we can define an array with.data. 389
389
So lat and launch. 390
390
So we already have our array of the coordinates 391
391
just as expected. 392
392
And then all we need is distance, duration and cadence. 393
393
And then we can take this.activities, 394
394
and I think we didn't even create that one yet. 395
395
So that's up here. 396
396
And now again, we could do it right here like this. 397
397
So basically, the more classical way. 398
398
So this.workouts would be an empty array. 399
399
But again, in this project, 400
400
I chose to already use the class fields specification. 401
401
And so this will become part 402
402
of standard JavaScript very soon. 403
403
And so therefore, I can create a class field like this 404
404
and I can even make it private, just like the other two. 405
405
But this time, I actually already initialized it here 406
406
to a new empty array. 407
407
And so now we can take that. 408
408
So here in new workout, we can say this.workouts.push 409
409
this new workout. 410
410
Now, we are gonna do 411
411
basically the exact same thing down here. 412
412
And so this here is something that always needs to happen. 413
413
So in both cases, and so let's not repeat that, 414
414
and instead, put it down here. 415
415
But then we have the problem that this workout variable 416
416
is defined here in this block scope, right? 417
417
And so because of the scope chain, as we already know, 418
418
this workout variable will then not be available outside 419
419
of this block, right? 420
420
But we want it outside of the block. 421
421
So right here, and so therefore, 422
422
we put it right here outside. 423
423
So let's work out. 424
424
And then here, we simply redefine that. 425
425
And then let's simply take this 426
426
and put it here again. 427
427
But this time, of course, with a cycling, 428
428
and then still the coordinates, distance, duration, 429
429
but here the elevation, all right? 430
430
The next step here is to actually render the workout 431
431
on the map, all right? 432
432
But before we do that, let's actually take a quick look 433
433
at the console, and see our work out there. 434
434
And so with that, we can already check 435
435
if all of this that we have up here 436
436
is already working, right? 437
437
Okay, so let's wait for the map. 438
438
And now let's click here and add a running. 439
439
So five, and 25 with 170. 440
440
And indeed, here we get our running object. 441
441
So it has the coordinates 442
442
and so this worked and of course, 443
443
it has has all the other data as well. 444
444
This ID is now corrected, as you see. 445
445
And also the pace is calculated here, 446
446
based on this input data, right? 447
447
And so Indeed, the most complicated part 448
448
of adding a new workout is already completed. 449
449
So that's beautiful. 450
450
Let's just try the same with cycling. 451
451
Let's say 10 kilometers, 452
452
in 10 minutes with 30 meters. 453
453
Now, and I didn't even click anywhere on the map. 454
454
Okay, and so that clearly means 455
455
that we are still missing a step, which is to hide the form. 456
456
But anyway, it simply took the coordinates from earlier 457
457
and then it added all the correct data here as well. 458
458
So indeed, it is now a cycling object, 459
459
while before it was a running object. 460
460
Let's just do that again here, 461
461
but this time with clicking, 462
462
so that I can show you something. 463
463
All right so it still says workout 464
464
and we're gonna fix that in the next video. 465
465
But for now, what I want is the cycling, 466
466
actually to have this orange border. 467
467
So just like this one. 468
468
All right, so orange is for cycling and green for running. 469
469
And so let's quickly do that. 470
470
So in our CSS, I think I showed you earlier 471
471
that we have running pop up and cycling pop up. 472
472
And these two values here are essentially simply the value 473
473
of the input type. 474
474
So this one here. 475
475
And so here, we can simply do a template literal 476
476
and then plug in the type here. 477
477
And now actually, let's also export this here 478
478
to its own method to make this add workout method here, 479
479
a little bit cleaner, all right. 480
480
So let's add down here, renderWorkoutMarker. 481
481
Let's grab this code here. 482
482
And so now all we need to do 483
483
is to call this.renderWorkoutMarker. 484
484
And here, we need to pass in the workout object 485
485
because otherwise, it's not gonna work. 486
486
I mean, right now, we don't even need to workout yet 487
487
but later, we will. 488
488
So we want to display some kind of data about the workout 489
489
And so let's pass it in. 490
490
So work out there. 491
491
And here, let's actually call it work out as well. 492
492
And so here, instead of displaying this, 493
493
let's simply display workout.distance. 494
494
Okay, just for now, 495
495
just so we are actually using the workout 496
496
here in this method, okay? 497
497
You see that we are also using 498
498
the this keyword in this method 499
499
but actually, that's no problem in this case 500
500
because here, we are actually calling this one here 501
501
as a method of the this keyword. 502
502
And besides that, we are also calling it ourselves. 503
503
So it's not a callback function 504
504
of any other function in JavaScript. 505
505
And so therefore, the this keyword in this method here 506
506
will still be the current object. 507
507
And so no need to using bind in this case. 508
508
And so finally, the last step is to actually render 509
509
the workout on the list. 510
510
And this one, I'm gonna leave for the next lecture, 511
511
because this one is gonna take a little bit of time 512
512
in order to format all the HTML correctly. 513
513
So let's give this one a save. 514
514
And so besides that, this one is basically complete. 515
515
And so let's quickly check it out one more time, 516
516
just to see the cycling pop up. 517
517
So let's see right there, 518
518
cycling 10, 10, 10 values don't matter. 519
519
Oh, and here, we do actually have an error, 520
520
which says that latitude is not defined. 521
521
And so indeed, here it is not defined. 522
522
So instead, this coordinate should of course, 523
523
come from the workout itself. 524
524
And so that itself is already a reason enough 525
525
to pass in the workout argument here into this function. 526
526
So now it becomes very important for the first time 527
527
to have some data in the actual workout object. 528
528
Because here we do need that 529
529
in order to tell JavaScript 530
530
or actually in order to tell leaflet 531
531
where to display this marker, okay? 532
532
So it's the data that's coming directly from the workout. 533
533
And so now this should work. 534
534
Or maybe it shouldn't. 535
535
So I'm looking at this variable here. 536
536
And right now the type is, of course, 537
537
also no longer defined, right? 538
538
So we get to type here from this one. 539
539
But of course, this type variable 540
540
is not gonna be available right here. 541
541
So how do we fix that? 542
542
Well, ideally, we should get the information, 543
543
whether the current workout is of running, 544
544
or of cycling, right from the workout object. 545
545
And actually, that's a pretty good idea. 546
546
And so let's add that value 547
547
to the cycling and to the running. 548
548
However, it doesn't make much sense to always pass that in. 549
549
So we already know that running 550
550
is always gonna be running 551
551
and cycling is always gonna be cycling. 552
552
And so we can simply add, basically, that type right here. 553
553
And so let's do that. 554
554
So again, we are defining a field here. 555
555
So cycling, and so this value type 556
556
will now be a property that's gonna be available 557
557
on all the instances. 558
558
Okay, so again, this would be the same thing 559
559
as doing this.type equals cycling like this, okay? 560
560
And now the same for running like this, all right? 561
561
And then, so now we can use that here 562
562
and we will actually also need that in some other places. 563
563
And so this is indeed a good thing to have. 564
564
So workout.type, and so now 565
565
this will whether it be running or cycling. 566
566
So let's test that now with cycling. 567
567
So cycling, and then 568
568
and we get another error. 569
569
Okay, so it failed to execute appendChild on node, 570
570
for some reason. 571
571
But let's go back to that in a second. 572
572
For now, I just want to see if actually, the type is there 573
573
and indeed it is. 574
574
So that's great already. 575
575
Now let's just go back and see 576
576
why this error here is happening. 577
577
Well, there is no appendChild method anywhere here. 578
578
Let's just set this here to something else. 579
579
But that's probably not the problem anyway. 580
580
So probably I shouldn't have changed anything 581
581
because now the error message here will be gone 582
582
and then I cannot read these, 583
583
the stack trace there, 584
584
which is what we call to that list of errors. 585
585
Oh, but now it actually worked, all right. 586
586
So the problem there was 587
587
that we were actually probably passing in some value 588
588
that was not a string 589
589
and so therefore, for some reason, 590
590
leaflet created some problem there. 591
591
But anyway, we will take care of this string here 592
592
in the next video. 593
593
For now, I just want to create just a running one here. 594
594
And so this time, it turns out to be green. 595
595
And so indeed, here the type is now running. 596
596
All right, so this was a very long video. 597
597
And so let's finish it here. 598
598
And as I already said in the next one, 599
599
we will then finally render the workout 600
600
also here on this sidebar.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.