# Web-ohjelmointi
** Janne Peiponen
## 1.9.2021
Asensin node.js osallistuin slackiin ja tutustuttiin luennolla codeacademyyn. Aloitin blogin tekemisen ja palautin tehdyksi kurssin moodlees slack-osallistumisen.
En ole vielä tehnyt codeacademya, jota varten minun tulee ensiksi vielä rekisteröityä.
Github on entuudestaan tuttua, ja sitä varten en ole vielä tehnyt mitään kurssin osalta.
Sinällään kiva, että päästään opiskelmaan tarkeemin html ja css, olen kokeillut tehdä niikkä itsenäisesti aiemmin.
Asensin visual studion.
## 8.9.2021
Luennolla opiskelimme html ja Css. hyvää kertausta minulle, tavallaan tuttua entuudestaan, mutta kertaus tekee hyvää.
Visual Studio Codessa oli aluksi hankaluuksia nimetä tiedosto index.html, mutta sain luennolla tehtyä kaiken.
## 13.9.2021
Itseopiskelua HTML- ja CSS, kävin läpi moodlen tehtävät. Hyvää kertausta ja pidin erityisesti 1. linkistä, jossa käytiin läpi asteittain keskeisiä piirteitä HTML:stä. Tein myös HTML- ja CSS moodlen tehtävän ja palautin sen moodleen.
Hankalaa oli aluksi tajuta, kuinka saan tehtyä menu-ylävalikon, jota klikkaamalla myös vaihtuu sivun tiedot. Katsoin videon youtubesta ja poimin siitä nopeasti kuinka se tulisi tehdä.
## 18.9.2021
Opiskelin itsenäisesti javascriptistä annetuista linkeistä ja tein sieltä löytyviä tehtäviä. noin 3h itseopiskelua
## 19.9.2021
Tein junassa matkalla joensuuhun palindromi- tehtävää, mielestäni charAt() avulla voin verrata stringiä kummastakin päästä käsin. En ole vielä onnistunut tekemään toimivaa koodia, mutta hyvä pohja.
## 20.9.2021
Sain valmiiksi palindromi-tehtävän, hieman turhauttavaa, kun tuli undefinated typing error. Pidin tauon ja sen jälkeen ratkaisu tuli nopeasti mieleeni. Eli palindromi toimii ja palautin sen. Kohta alan tekemään puhelinluettelo-tehtävää, kunhan päivän algorytmi-luento loppuu.
Puhelinluettelon tekeminen meni nopeasti eli alan kehittyä. Javascriptiin siirtyminen Javasta olikin oletettua helpompaa, tosin välillä tuntui, etten osaa mitään. Mutta, mieli muuttuu nopeasti positiiviseksi, kun tulee onnistumisia. Tähän on hyvä päättää päivä eli sain kaikki viikko tehtävät tehtyä ja ajallaan.
## 24.9.2021
Tein Urheilija- ja Henkilö-luokat valmiiksi, javascriptissä on paljon samaa kuin Javassa niin osa oli helpompaa omaksua. Joitain poikkeuksiahan näissä on, kuten ei tarvitse luokan mukaan nimetä tiedostoa ja tekisi mieli sanoa, että Javascriptissä tarvitsee kirjoittaa vähemmän koodia kuin Javassa.
## 30.9.2021
Kävin tämän viikkoisen luentoa omaan rauhalliseen tahtiin ja sain tehtyä asioita kätevästi
- Laitoin gitlabiin Urheilija1.js tiedoston visual studion kautta
- Kutsuin luennoitsijan HackMD
- Kutsuin luennoitsijan myös gitlabiin
Täysyin uutena tuli JSON ja REST, tosin kuullut niistä jotain, mutta ei ole käytännön kokemusta muuten.
REST ymmärrettyä, sillä voi lisätä, poistaa, muokata tai lukea palvelimelta tietoa, sovelluksen kautta.
JSON sitten mitä REST 4-käskyä näyttävät koodia, joka näyttää paljon javascriptin olio:lle annettua tietoa,
mutta saa käyttää vain "" ja sitä laitetaan esim
### JSON
{"nimi":"Janne"}
String laitetaan hipsuihin, mutta integer ja boolean tai null esim. ei.
### REST palauttaa HTML-koodit, jotka ovat numerollisia ja kertoo onnistuiko esim. tai tuliko jotain vikaa
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status lainattua: "HTTP response status codes
Informational responses ( 100 – 199 )
Successful responses ( 200 – 299 )
Redirects ( 300 – 399 )
Client errors ( 400 – 499 )
Server errors ( 500 – 599 )"
### package.json tekeminen
Luennolla teimme package.json, jonka sai tehtyä kun kirjoitti terminaaliin:
npm init
Seuraavaksi enteriä, tosin author kohtaan omat puumerkit... noihin voi laittaa lisää tietoa jos olisi halunnut.
ansensimme myös express eli terminaaliin
npm i express
-- package.json tuli lisämaininta seuraava: "dependencies": {
"express": "^4.17.1"
}
#### Myös package-lock.json tiedosto luotiin asennuksen myötä.
#### gitignore.
tiedostolla estetään, mitä ei laiteta gittiin...
nyt esim. node_modules sisältää paljon tietoa, jota ei tarvitse viedä
Niin sen siirtminen estetään, kun gitignoreen kirjoitetaan
/node_modules
tarkempaa tietoa Express tietojen hakemista oliolle: https://devdocs.io/express/
Serverin sulkeminen terminaalissa ctrl c
#### Nodemon asennus
npm install -g nodemon
Nodemon osaa uudelleen käynnistää solmun, jos vaikkapa kirjoitan uutta koodia. Eli terminaalissa Näkyy:
[nodemon] restarting due to changes...
[nodemon] restarting due to changes...
[nodemon] starting `node .\app.js`
Eli minun ei tarvitse aina sulkea ja uudelleen käynnistää sovellusta vaan nodemon hoitaa sen puolestani
#### Postman asennus
https://www.postman.com/downloads/
Postmanissa ongelma
Content type pitäisi olla json, mutta en edes näe kyseistä kohtaa header-valikosta.
Ratkesi, kun vaihdoin BODY - osioita ->json oikealta nuolivalikosta.
#### npm install body-parser
asennusta varsen ctrl c, jotta voidaan terminaaliin kirjoittaa kyseinen
### 8.10.2021 Sanakirjan tekemistä
Nyt tuntuu astetta haastavalta. Huomaan, että luennon seuraaminen ja sen tekeminen vaikeutui, koska ohjelmisto herjasi jotain. Mitä en osannut korjata, ja en ole oikein varma mistä moinen johtuu. Aiemmin toiminut koodi ei toimikaan ja valittaa seuraavaa minulle:
vents.js:377
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE: address already in use :::3001
at Server.setupListenHandle [as _listen2] (net.js:1320:16)
at listenInCluster (net.js:1368:12)
at Server.listen (net.js:1454:7)
at Function.listen (C:\web\sanakirjaluento\node_modules\express\lib\application.js:618:24)
Koita sitten ratkoa mitä teen väärin, jotenkin se sitten alkoi toimimaan kun vaihdoin localhost takaisin 3000. Mutta
en vielä aina ymmärrä miksei se voisi olla jokin muu.
## Ongelma
Error: listen EADDRINUSE: address already in use
eli ilmeisesti, ohjelmisto ei sulje tuota porttia ja se on silti päällä...
#### Ratkaisu
pysäytetään ctrl C, mutta en silti saa sitä ohjelmistoa toimimaan. selaimessa kyllä mäkyy localhost 3000/words kautta ne sanat.
Uskoakseni tein virheen siinä, kun aukaisin aina debuggauksen jälkeen uuden terminaalin. Eli sitä ei kannata tehdä vaan käyttää jos olemassa olevaa.
Jquery tuli luennolla myös uutena, joten tästähän sitä alkaa taas oppimaan
CORS myös uutta, ja kaiken tämän sisäistämiseen menee varmasti aikaa...
## 11.10.2021 Sanakirjan tekoa
Sain tehtyä get sanan. Tuntui hieman oudolta aloittaa tehtävän tekeminen, mutta päättelin, että kannattaa käyttää taulukkoa ja
array find() hyväksi, niin siitä se sitten alkoi luistaa. Sain oikean rivin löydettyä nopeasti, mutta aikaa meni oivaltamiseen
kuinka saan palautettua vain englanninkielisen sanan. Jossa onnistuin lopulta ja itseluottamus kasvoi.
## 12.10.2021 Sanakirjan tekoa
Sain tehtyä myös Post. Aikaa meni varmaankin 4A tekemiseen noin 7-8h. Tuntui lopulta helpommalta kuin ajattelin, vaikka nyt tuli uutta asiaa. Tosin aiemmat luennot kyllä valmistivat hyvin tämän tehtävän tekemiseen. Appendfile pelasti minut lopulta,
koska sillä saan lisättyä aiemman tiedoston loppuun rivin. Aluksi koitin writefilesync, mutta se ylikirjoittaa aiemman tilalle.
## 15.10.2021
Käyn luentoa taas omaan rauhalliseen tahtiin, joka on osoittautunut hyväksi ratkaisuksi, voin pysähdellä ja miettiä.
Sain tehtyä luennolla näytetyt esimerkin ajax:n käytöstä ja siinä olevaa JQuerya niin, että post käyttöliittymästä voi
tallentaa onnistuneesti tiedostoon. Suuri helpotus, että backend toimii frontendin kanssa, ja se luo itseluottamusta siihen,
että osaan tehdä jotain oikein.
Tavallaan, erikoista, kun kuuntelen luentoa niin pidän paljon taukoja ja kokeilen taustalla kaikenlaista. Paremmin jää muistiin, mutta aikaa menee kaksinkertaisesti kuin luento kestää.
#### https://api.jquery.com/jquery.ajax/
#### https://api.jquery.com/jQuery.get/#jQuery-get-url-data-success-dataType
Linkkejä, joista on get käyttöliittymisen tekemisessä.
## 31.10.2021 tehtävä 5
Olen tehnyt nyt delete ja post toiminnot tietokantaan eli mariadb + backend. Tuntuu haastavammalta kuin kuvittelin ainakin päivittämisen osalta, mietin mikä olisi järkevin tapa toteuttaa sitä. Myös get vaikuttaa haastavalta.
Toisaalta 1. vuoden opinnoista on paljon hyötyä, kun on tullut tehtyä mariadb vastaavaa.
Periaatteessa kaikki toimivat seuraavan kaavan mukaan.
1. luodaan tietokanta
2. otetaan yhteystietokantaan
3. tehdään kysely tietokantaan
4. Suljetaan yhteys tietokantaan, ja silloin mariadb saa tiedot.
## 1.11.2021 puhelinluettelon backend viimeistely
Sain toimimaan myäs get kaikki henkilöt ja get vain yksi henkilö. Myös päivittäminen toimii.
Tuli tosin tyhmä olo, kun koitin pitkään korjata jo toimivaa koodia. Mutta sitten hoksasin, että yksi kauttaviiva oli unohtunut laittaa... Tästähän se maailma taas avartuu kirkkaamin.
## 2.11.2021
React tutustumista, kuullut aiemmin ja olen halunnut oppia siitä enemmän. Hyvä, että käydään luennolla läpi sitä, tosin
taas paljon uutta ja tuntuu alussa vaikealta omaksua, mutta kyllä ne sieltä kuitenkin mieleen jäävät.
## 6.11.2021
Kertausta javascriptistä ennen Reactia,
eli moodlen linkkejä käyn läpi ja opettelen niitä.
## 7.11.2021
Kuuntelen laiskanläksynä viikon luentoa.
## 8.11.2021
https://www.digitalocean.com/community/tutorials/how-to-call-web-apis-with-the-useeffect-hook-in-react
teen tuota eteen päin, hitaasti mutta varmasti.
Meni pitkään, kun saanut node.js commandpromptilla toimimaan package-json ja nodemodules asennusta.
Mutta, kun menin Visual studio codeen niin sain sitä kautta tehtyä, tosin tein sitä ennen package.json tiedoston valmiiksi.
npm install --save-dev json-server <- aiheutti häiriötä eli ei ajanut sitä ja ei näkynyt tiedostot.
Meni myös yllättän pitkään hoksata miksi listalla ei näkynyt db.json tietoja
Eli tein virheen siinä, että minulla ei ollut
### npm run api tuossa restapi1 päällä
ja jos sitä ollut tehnyt niin ei näkynyt db tietoja, kun tein
### npm start hook1frontti
eli kaikki lopulta hyvin, mutta ylipitkään säädin tätä.
## 9.11.2021 hook1frontti jatkuu
Sain listan tehtyä niin, että listalle ilmestyy uusi tuote jos painan F5, mutta kun jatkoin ohjetta eteenpäin niin ratkesi.
Eli hook useRef avulla saa päivittymään listan näkymän ajantasalle.
## 13.11.2021
Käyn keskiviikon luentoa.
Huomaan, että alan pikku hiljaa kehittyä ja on hyvä, kun kurssilla käydään useamman kerran läpi samoja asioita. Nyt voi kiinniittää enemmän huomiota yksityiskohtiin, kuten status(200) tarkoittaa OK:ta
**npm install --save express mysql** <--- taas ongelmia, ei asentanut node_modulesia ja package-lock.json, eli olin tehnyt kansion jos olemassa olevaan kansioon, jossa on noita muita web-ohjelmointi kurssin töitäni.
Kokeilen tehdä uuden kansion ja sitä kauttaa asentaa... jospa se toimisi silloin paremmin.
asentaa express ja mysql:n
Työ tekijäänsä opetti, ja nyt se asensi oikein. tein tosin taas codessa, mutta luulen ymmärtäväni, että se ehkä on asentanut noita aiemminkin mutta eri kohtaan...
nodemon .\index.js <-- .\taitaa aukaista kaikki edeltävät.. luulisin, että pelkkä indexjs toimii myös.
## 14.11.2021
Opin uutta, että function => (error, results, fields) niin fields on kenttien tiedot esim. mysql:stä eli mitä taulukossa on määritelty ennen kuin siihen on syötetty mitään tietoa.
}
**npx create-react-app avaakansio_ui luo react käyttöliittymän ja sitä varten alihakemiston nimeltä yhteystiedot_ui
Extension ES7 React pikalyhenteiä hooksien tekoon löytyy prefix hookista ja tab näppäin...
ohjeistuksen mukaan tehtiin rcc tab -> loi tällaisen:
import React, { Component } from 'react'
export default class puhelintieto extends Component {
render() {
return (
<div>
</div>
)
}
}
## 17.11.
Kävin luennolla ja koitin tehdä perässä.. ei aivan onnistunut, nyt tuli kovaan tahtiin asiaa ja tuntuu, siltä että REACT:ssa on tullut paljon päivtyksiä ja vanhat asiat eivät enää toimi niin kuin ennen.
## 20.11
Käyn puhelinluettelo luentoa uudestaan läpi ja koitan korjata koodautani toimivammaksi, se toimii jo niin, että näkyy jo tällaista

tosin tulee vielä virheilmoituksia ja koitan miettiä mistä ne johtuvat
#### Router
tuosta katsoin videon : https://www.youtube.com/watch?v=aZGzwEjZrXc
eli Router avulla saadaa ylävalikko, josta voi sitten klikata sivuja auki.
asenna npm i react-router-dom
app.js alkuun lisätään: import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
#### Axios
asenna: npm i axios
sen avulla luodaan tietokantayhteys mysql
GlobalState.js alkuun laitetaan: import axios from "axios";
MuokkaaPuihelintieto alussa on myös: import axios from "axios";
#### api
oikeastaan tuoota Axiosta opiskellessa tuli vihdoin sellainen ahaa elämys tuosta express:stä, jolla teimme kurssin alussa apin eli axios ajaa samaa asiaa eli on välikäsi webselaimella tehdyn haun ja serverillä olevan tietokannan välillä.
#### Muokkaa ja Poista
tein luennon ohjeen mukaan, mutta muokkaa ja poista eivät toimi,huomasin, että index.js on con eikä conn osasssa ja muutin ne conn. tämän jälkee en enää näe noita tietoja sivulla.
HARMILLISTA!

## Urheilija II tehtävä
20.11.2021 alan tekemään
teen HeidiSQL tietokannan nimeltä urheilijat
teen seuraavanlaisen taulun:
CREATE TABLE urheilija (
id int(11) NOT NULL AUTO_INCREMENT,
nimi varchar(50),
syntymavuosi DATE,
paino int(4),
linkki varchar(50),
laji varchar(50),
saavutukset varchar(150),
PRIMARY KEY(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

laitoin tällaiset tiedot:
INSERT INTO urheilija (id, nimi, syntymavuosi, paino, linkki, laji, saavutukset) VALUES
(1, 'Teemu Flash Selanne', '1970-07-03', 89, 'https://fi.wikipedia.org/wiki/Teemu_Sel%C3%A4nne#/media/Tiedosto:Teemu_Selanne_on_the_ice_November_2010.jpg', 'jaakiekko', 'Stanley Cup 2006'),
(2, 'Saku Koivu', '1974-11-23', 82, 'https://fi.wikipedia.org/wiki/Saku_Koivu#/media/Tiedosto:Sakukoivu_halifax2008.png', 'jaakiekko', 'Torino 2006 Hopeaa'),
(3, 'Jere Lehtinen', '1973-06-24', 89, 'https://fi.wikipedia.org/wiki/Jere_Lehtinen#/media/Tiedosto:Jere_Lehtinen_(Dallas).JPG)', 'jaakiekko', 'Stanley Cup 1999');
SELECT * FROM urheilija;
Näyttäisi toimivan oikein

#### Urheilija2
tein git web-ohjelmointi kansioon urheilija2 ja sinne kansion restapi
#### restapi
aukaisin visual studio coden ja laitan terminaaliin seuraavat:
npm init –y
npm install --save express mysql
huom! npm init -y ei taida onnistua joten, kokeilen:
npm init
sain sillä tehtyä package.json

Seuraavaksi kokeilen asentaa: npm install --save express mysql
näytti onnistuvan:

Luon seuraavaksi index.js tiedoston ja alan tekemään sinne siältöä.
laitoin sisältöä tuosta puhelinluettelon teosta, nyt index.js ei ole connection.end, joka oli aiemmassa ohjeessa missä tehtiin mysql jne.
asensin: npm install --save-dev nodemon
testasin toimiiko koodi tähän mennessä eli yhteys mysql ja visual studion välillä.
OK

Suoritin komennolla nodemon index.js
eli voin edetä seuraavaan kohtaan.
## 21.11. Urheilijat 2 backend
testasin POSTMAN:lla saanko kaikki urheilijat get -metodilla. toimii:

Toimii myös jos hakee pelkällä ID:llä

Urheilijan lisääminen myös toimi:

ja päivitetty taulu näkyy mysql:ssa

Urheilijan poistaminen toimii myös

antaa virhettä, kun yritän muokata.
huono koodi:
app.put("/urheilijat/:id", (req, res) => {
const id = Number(req.params.id);
//const id = req.params.id;
const updatedUser = req.body;
conn.query(
"UPDATE urheilija SET ? WHERE id = ?;",
[updatedUser, req.params.id],
function (error, results) {
if (error) throw error;
conn.query("SELECT * FROM urheilija WHERE id=?", id, (err, rows) => {
if (err) throw err;
res.end(JSON.stringify(rows[0]));
});
}
);
});
Kokeilen muokata koodia nii, että se toimisi paremmin.
löytyi ratkaisu, eli muutin [updatedUser, id] -kohdan.
nyt toimii postamnilla myös muokkaus!

postmanista:

ja mysql serverillä näkyy muutos myös

#### BACKEND toimii nyt oikein urheilijat2 tehtävästä
Tehty ensimmäiset vaatimukset eli:
Suunnittele ja toteuta express.js-kirjaston avulla REST-rajapinta,
toteuta datan haku,lisäys, poisto ja päivitys mariadb-tietokantaan.
#### Tietokannassa on myös
Tietokannassa oltava:
Nimet (etunimi, sukunimi, kutsumanimi),
Syntymävuosi (Date)
Paino (number)
www-linkki kuvaan,
Laji
Saavutukset
tässä mysql skripti:
CREATE TABLE urheilija (
id int(11) NOT NULL AUTO_INCREMENT,
nimi varchar(50),
syntymavuosi DATE,
paino int(4),
linkki VARCHAR(200),
laji varchar(50),
saavutukset varchar(150),
PRIMARY KEY(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO urheilija (id, nimi, syntymavuosi, paino, linkki, laji, saavutukset) VALUES
(1, 'Teemu Flash Selanne', '1970-07-03', 89, 'https://fi.wikipedia.org/wiki/Teemu_Sel%C3%A4nne#/media/Tiedosto:Teemu_Selanne_on_the_ice_November_2010.jpg', 'jaakiekko', 'Stanley Cup 2006'),
(2, 'Saku Koivu', '1974-11-23', 82, 'https://fi.wikipedia.org/wiki/Saku_Koivu#/media/Tiedosto:Sakukoivu_halifax2008.png', 'jaakiekko', 'Torino 2006 Hopeaa'),
(3, 'Jere Lehtinen', '1973-06-24', 89, 'https://fi.wikipedia.org/wiki/Jere_Lehtinen#/media/Tiedosto:Jere_Lehtinen_(Dallas).JPG)', 'jaakiekko', 'Stanley Cup 1999');
SELECT * FROM urheilija;
CREATE OR REPLACE USER 'janne'@'localhost' IDENTIFIED BY '*********ennäytä';
GRANT SELECT,INSERT,UPDATE,DELETE ON urheilija TO 'janne'@'localhost';
#### Reactin toteutus
2) Toteuta React:lla käyttöliittymä, jonka avulla voit lukea sekä lisätä, päivittää ja poistaa urheilijoita tietokantaan käyttäen vaiheen 1 backendiä. (5 pistettä)
aukaisen urheilijat2 kansion, jossa on restapi, aukaisen terminaalin ja laitan tämän: npm install -g create-react-app

seuraavaksi asennan: npx create-react-app urheilijat_ui
Asennuksen jälkeen:

-> näkyy tuo Reactin alkulogo kun kokeilin
1. cd urheilijat_ui
2. npm start
kokeilin toimiiko restapi eli restapi> node index.js ja serveri toimii edelleen.
#### Bootstrap
Täysin uusi aihe minulle, joten katsoin youtubesta videon, jossa havanoidaan sitä. Eli ymmärsin näin, että web-sivu osaa sen avulla mukauttaa sivua erikokoiselta näytöylä esim. lääpärilä aina älypuhelimenkin näytölle ilman, että kokonaisuus katoaa.
https://www.youtube.com/watch?v=yalxT0PEx8c
Asensin: npm install bootstrap
antoi jotain erroria, en ole varma pitääkö siitä huolestua

lisäsin app.js tämän importin: import "bootstrap/dist/css/bootstrap.min.css";
## yritän käydä lento läpi uudelleen
https://javascript.plainenglish.io/how-to-use-react-context-api-with-functional-component-472f1d5e0851
kerrotaan jotain noista context liittyvästä sisällöstä.
## urheilijantiedot.js
## Reititys
asensin: asenna npm i react-router-dom

lisäsin app.js tämän: import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
## Axios
asensin: npm i axios
pitää imporata sitä vielä

## 24.11. Teen urheilija 2 tehtävää
Luennolla vinkattiin videosta, jossa kerrotaan context käytöstä ja koitan sitä kautta hahmottaa asiaa. En halauisi vain kopioida tehtyä työtä vaan oikeasti ymmärtää mitä teen.
## 28.11.2021
Sain tehtyä Urheilijat2 tehtävän niin, että react käyttöliittymä toimii.
Onnistumsia: Lisääminen, poistaminen ja tietojen näkeminen
Muokkaamista en ole vielä tehnyt, voisin kokeilla sen tekemistä myöhemmin. Mutta nyt menen juhlimaan onnistumista!

linkki gitlabiin: https://gitlab.com/jannepeiponenweb/web-ohjelmointi/-/tree/main/Urheilija2
Muokkaaminen toimii.
## 29.11-30.11
Tein e-porfolioni valmiiksi, tosin ongelmia tulee kun koitan laittaa sen gitlabiin. Antaa herjaa jostain ulommasta git repositoriosta.
Palautin tehdyn e-portfolion, ratkasin ongelman tekemällä downloading sen sijaan. Eli ei kannata ottaa jatkossa reposta copya jos aikoo lähettää sen toiseen gittiin.
Muokkailin portfoliosta kuvia sopivammiksi ja lisäilin palaute ja tieto-osiota omanlaisekseen. Kuvasin porfolio osioiden otsikoita ja leipätekstiä sellaiseksi, että se täyttäisi vaadittavia vaatimuksia eli kuvailin mitä tein jne.
Tässä on vielä sen linkki gitlabiin: https://gitlab.com/jannepeiponenweb/web-ohjelmointi/-/tree/main/portfolio/startbootstrap-freelancer-master