Sõnastik
Teek / Raamistik – Framework
Programmeerimisstruktuur, mis pakub tööriistade ja komponentide komplekti rakenduste loomiseks, lihtsustades arendamisprotsessi.
Svelte – Tööriist veebirakenduste loomiseks
Raamistik kiirete ja kergete veebirakenduste arendamiseks. Erinevalt teistest raamistikest kompileerib Svelte koodi juba ehitusetapis, mis vähendab brauseris töötamise koormust ja kiirendab rakendust.
Sapper – Raamatukogu Svelte jaoks
Svelte laiendus, mis pakub keerukamaid võimalusi rakenduste loomiseks, näiteks marsruutimine, lehe genereerimine ja serveripoolne renderdamine (SSR). Sapperi dokumentatsioon
Pivotal Tracker – Projekti haldamise tööriist
Veebisait projektijuhtimiseks, kus saab planeerida ülesandeid ja jälgida projekti täitmist. Sobib meeskonnatööks ja projekti juhtimiseks algusest lõpuni. Pivotal Trackeri leht
Svelte eelised
Svelte on lihtsam ja kiirem omandada ja kasutada kui teised raamistikud, nagu näiteks React, kuna see vähendab brauseris töötava koodi vajadust ja muudab rakenduse tõhusamaks.
Svelte juhend
Svelte ametlik juhend, mis sisaldab samm-sammult juhiseid nii alustamiseks kui ka keerukamate võimaluste kasutamiseks raamistikus. Link juhendile
Käsud
Sapperi põhja allalaadimine projekti
npx degit “sveltejs/sapper-template#rollup” . --force //peab kaks '-' olema
–force tähendab, et teek on installitud juurkataloogi
Sapper server installeerimine
npm i
Serveri käivitamine
npm run dev
Installatsioonid
npm i bootstrap
npm i jquery
npm i rollup-plugin-copy
npm install node-fetch 2.6.0
npm i body-parser
Minu projekt
Lingid
Projekti seadistamine
Loome GitHub repositooriumi

Integreerime PivotalTracker’is

Kloonime projekti
git clone git@github.com:DotskinMaksim/dotskin-bank-client.git
1. Registreerimine
Loome uue story’i “As a user I can register” ja lisame ülesandeid


Loome uue branch’i “#188295956-As-a-user-I-can-register” ja teeme checkout
Loome failid:

src -> components ->Nav.svelte
<script>
export let segment; // Muutuja, mis hoiab praegust segmenti
</script>
<style>
nav {
border-bottom: 1px solid rgba(255,62,0,0.1); // Navigeerimise allservas joon
font-weight: 300; // Teksti kaal
padding: 0 1em; // Padjand navigeerimise ümber
}
ul {
margin: 0; // Eemaldab nimekirja välimise marginaali
padding: 0; // Eemaldab nimekirja sisemise padjandi
}
/* clearfix */
ul::after {
content: ''; // Lisab "clearfix" efekti
display: block; // Muudab sisu plokiks
clear: both; // Eemaldab kõik hõljuvad elemendid
}
li {
display: block; // Muudab nimekirja elemendi plokiks
float: left; // Hõljub vasakule
}
[aria-current] {
position: relative; // Seab positsiooni suhteliseks
display: inline-block; // Muudab elemendi inline-blokiks
}
[aria-current]::after {
position: absolute; // Seab positsiooni absoluutselt
content: ''; // Lisab visuaalse elemendi
width: calc(100% - 1em); // Laius 100% minus 1em
height: 2px; // Kõrgus 2px
background-color: rgb(255,62,0); // Taustavärv
display: block; // Muudab sisu plokiks
bottom: -1px; // Positsioneerib allapoole
}
a {
text-decoration: none; // Eemaldab allajoonimise
padding: 1em 0.5em; // Padjand lingi ümber
display: block; // Muudab lingi plokiks
}
</style>
<nav>
<ul>
<li><a aria-current="{segment === 'register' ? 'page' : undefined}" href="register">register</a></li>
</ul>
</nav>
src -> node_modules ->api.js
const base = 'https://js.kristjankivikangur21.thkit.ee/';
// Funktsioon, mis saadab HTTP päringud
async function send({ method, path, data, token }) {
// Kasutatakse fetch'i, olenevalt keskkonnast (brauser või Node.js)
const fetch = process.browser ? window.fetch : require('node-fetch').default;
const opts = { method, headers: {} }; // Päringu valikud
// Kui andmed on olemas, määrame sisu tüübi ja keha
if (data) {
opts.headers['Content-Type'] = 'application/json'; // Määrab sisu tüübi
opts.body = JSON.stringify(data); // Muudab andmed JSON-formaadiks
}
// Kui token on olemas, lisame selle autoriseerimise päisesse
if (token) {
opts.headers['Authorization'] = `Bearer ${token}`; // Lisab Bearer tokeni
}
// Logib URL ja valikud
console.log(`${base}/${path}`);
console.log(opts);
// Saadab päringu ja töötleb vastuse
return fetch(`${base}/${path}`, opts)
.then((r) => r.text()) // Saadab vastuse tekstina
.then((json) => {
try {
// Proovib vastuse JSON'iks konverteerida
return JSON.parse(json);
} catch (err) {
// Tagastab tavalise tekstivastuse, kui JSON konverteerimine ebaõnnestub
return json;
}
});
}
// Funktsioon GET päringu saatmiseks
export function get(path, token) {
return send({ method: 'GET', path, token });
}
// Funktsioon DELETE päringu saatmiseks
export function del(path, token) {
return send({ method: 'DELETE', path, token });
}
// Funktsioon POST päringu saatmiseks
export function post(path, data, token) {
return send({ method: 'POST', path, data, token });
}
// Funktsioon PUT päringu saatmiseks
export function put(path, data, token) {
return send({ method: 'PUT', path, data, token });
}
src -> node_modules ->utils.js
// Funktsioon POST päringu saatmiseks
export function post(endpoint, data) {
return fetch(endpoint, {
method: 'POST', // Päringu meetod on POST
credentials: 'include', // Lisab küpsised ja muud tõendid päringusse
body: JSON.stringify(data || {}), // Muudab andmed JSON-formaadiks või kasutab tühja objekti
headers: {
'Content-Type': 'application/json' // Määrab sisu tüübi
}
}).then((r) => r.json()); // Tagastab vastuse JSON-formaadis
}
src -> server.js
import sirv from 'sirv';
import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
import session from 'express-session';
import sessionFileStore from 'session-file-store'; // npm install session-file-store
const { json } = require('body-parser');
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development'; // Kontrollib, kas keskkond on arenduskeskkond
const FileStore = new sessionFileStore(session); // Faili salvestamine seansi jaoks
// Polka serveri loomine
polka() // Saate kasutada ka Express'i
.use(
compression({ threshold: 0 }), // Kompressioon, et vähendada andmeedastust
json(), // JSON päringute töötlemiseks
session({
secret: 'iiiirrrr', // Suvaline saladus, EI TOHI GitHub'i panna
resave: true, // Salvestab seansi uuesti isegi kui see ei ole muutunud
saveUninitialized: true, // Salvestab algse seansi
cookie: {
maxAge: 31536000 // Küpsise eluaeg (1 aasta)
},
store: new FileStore({
path: `.sessions` // Salvestab seansid määratud teed pidi
})
}),
sirv('static', { dev }), // Statiliste failide serveerimine
sapper.middleware({
session: req => ({
user: req.session && req.session.user // Kasutaja seansi info
})
})
)
.listen(PORT, err => {
if (err) console.log('error', err); // Viga kuulamisel
});
src -> routes-> auth -> register.js
import * as api from 'api.js';
export function post(req, res) {
const user = req.body;
api.post('users', user).then(response=>{
if (response.user) {
req.session.user = response.user;
}
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(response));
});
}
src -> routes-> register.svelte
<script>
import { goto, stores } from '@sapper/app'; // Impordib goto ja stores Sapperi raamatukogust
import { post } from 'utils.js'; // Impordib POST funktsiooni utils.js failist
const { session } = stores(); // Saadab seanssi poest
let username = ''; // Muutuja kasutajanime jaoks
let name = ''; // Muutuja nime jaoks
let password = ''; // Muutuja parooli jaoks
let error = null; // Muutuja vigade jaoks
// Vormide saatmise funktsioon
async function submit(event) {
const response = await post(`auth/register`, {username, name, password}); // Saadab registreerimise andmed API-le
error = response.error; // Salvestab vastuse vigade, kui need on olemas
if (response.id) { // Kui vastuses on kasutaja ID
goto('/'); // Suunab peavalehele
}
}
</script>
<svelte:head>
<title>Sign up • BarBank</title> <!-- Lehe pealkiri -->
</svelte:head>
<div class="auth-page">
<div class="container page">
<div class="row">
<div class="col-md-6 offset-md-3 col-xs-12">
<h1 class="text-xs-center">Sign up</h1> <!-- Registreerimise pealkiri -->
<p class="text-xs-center">
<a href="/login">Have an account?</a> <!-- Link sisselogimiseks -->
</p>
{#if error}
<div class="alert alert-danger" role="alert">{error}</div> <!-- Vigade teade, kui need on olemas -->
{/if}
<form on:submit|preventDefault={submit}> <!-- Vorm, mis ei saada päringut kui submit kutsutakse -->
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" required placeholder="Your username"
bind:value={username}> <!-- Kasutajanime sisend -->
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" required placeholder="Name"
bind:value={name}> <!-- Nime sisend -->
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="password" required placeholder="Password"
bind:value={password}> <!-- Parooli sisend -->
{#if password.length > 1 && password.length < 6 }<sup>
<div class="alert alert-danger" role="alert">Password too short</div> <!-- Teade, kui parool on liiga lühike -->
</sup>{/if}
</fieldset>
<button class="btn btn-lg btn-primary pull-xs-right" disabled="{password.length < 6}">Sign up <!-- Registreerimise nupp -->
</button>
</form>
</div>
</div>
</div>
</div>
Proovime











Kui kõik töötab teeme commit’i
git commit -m 'As a user I can register [Delivers #siin peab olema teie story'i id]'
git push origin main
Teeme merge’i
git checkoout main
git merge '#188295956-As-a-user-I-can-register'
git add .
git commit
git push origin main
Siis kontrollime GitHub’is

2. Sisse logimine
Loome uue story’i “As a user I can log in and out” ja lisame ülesandeid


Loome uue branch’i “#siin peab olema teie story’i id-As-a-user-I-can-log-in-and-out” ja teeme checkout
git branch '#188479647-As-a-user-I-can-log-in-and-out'
git checkout '#188479647-As-a-user-I-can-log-in-and-out'
Loome failid:

src -> routes ->auth -> login.js
import * as api from 'api.js';
export function post(req, res) {
const user = req.body;
api.post('sessions', req.body).then(response => {
if (response.token) req.session.token = response.token;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(response));
});
}
src -> routes ->auth -> logout.js
import * as api from 'api.js'; // API mooduli importimine
export function post(req, res) { // POST meetodi defineerimine
const user = req.body; // Kasutaja andmete saamine päringu kehast
api.del('sessions', req.session.token).then(response => { // Sessiooni kustutamine API kaudu
delete req.session.user; // Kasutaja andmete eemaldamine sessioonist
res.end(JSON.stringify(response)); // Vastuse saatmine kliendile JSON formaadis
});
}
src -> routes ->login.svelte
<script context="module">
export async function preload({ params }, { token }) { // Andmete eelkoormus
if (token) { // Kontrollib, kas token on olemas
this.redirect(302, `/`); // Suunab kasutaja kodulehe peale
}
}
</script>
<script>
import { goto, stores } from '@sapper/app'; // Sapperi moodulite importimine
import { post } from 'utils.js'; // Utility funktsioonide importimine
const { session } = stores(); // Sessiooni andmete saamine
let username = ''; // Muutuja kasutajanime jaoks
let password = ''; // Muutuja parooli jaoks
let error = null; // Muutuja vigade jaoks
async function submit(event) { // Vormide esitamise funktsioon
const response = await post(`auth/login`, {username, password}); // Postitamine sisselogimise andmetega
// TODO käsitleda võrgu vigu
error = response.error; // Vigade salvestamine
if (response.token) { // Kui token on olemas
console.log(response) // Väljasta vastus konsooli
$session.token = response.token; // Salvestab token sessiooni
goto('/'); // Suunab kasutaja kodulehe peale
}
}
</script>
<svelte:head>
<title>Sign in • barBank</title> <!-- Lehe pealkiri -->
</svelte:head>
<div class="auth-page"> <!-- Autentimise leht -->
<div class="container page">
<div class="row">
<div class="col-md-6 offset-md-3 col-xs-12"> <!-- Keskel asuv veerg -->
<h1 class="text-xs-center">Sign In</h1> <!-- Pealkiri -->
<p class="text-xs-center">
<a href="/register">Need an account?</a> <!-- Link registreerimise lehele -->
</p>
{#if error} <!-- Kui on viga -->
<div class="alert alert-danger" role="alert">{error}</div> <!-- Vigade kuvamine -->
{/if}
<form on:submit|preventDefault={submit}> <!-- Vorm esitamine -->
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" required placeholder="Username" bind:value={username}> <!-- Kasutajanime sisestamine -->
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="password" required placeholder="Password" bind:value={password}> <!-- Parooli sisestamine -->
</fieldset>
<button class="btn btn-lg btn-primary pull-xs-right" type="submit"> <!-- Esitamisnupp -->
Sign in
</button>
</form>
</div>
</div>
</div>
</div>
Ja muutame olemasolevaid failid

src -> components ->Nav.svelte
<script>
export let segment; // Segment, mis näitab praegust lehte
import { goto, stores } from '@sapper/app'; // Sapperi moodulite importimine
import { post } from 'utils.js'; // Utility funktsioonide importimine
const { page, session } = stores(); // Lehe ja sessiooni andmete saamine
async function logout() { // Väljalogimise funktsioon
await post(`auth/logout`); // Postitamine väljalogimise teatega
$session.token = null; // Sessiooni tokeni tühjendamine
goto('/'); // Suunab kasutaja kodulehe peale
}
</script>
<style>
nav {
border-bottom: 1px solid rgba(255,62,0,0.1);
font-weight: 300;
padding: 0 1em;
}
ul {
margin: 0;
padding: 0;
}
/* clearfix */
ul::after {
content: '';
display: block;
clear: both;
}
li {
display: block;
float: left;
}
[aria-current] {
position: relative;
display: inline-block;
}
[aria-current]::after {
position: absolute;
content: '';
width: calc(100% - 1em);
height: 2px;
background-color: rgb(255,62,0);
display: block;
bottom: -1px;
}
a {
text-decoration: none;
padding: 1em 0.5em;
display: block;
}
</style>
<nav>
<ul>
{#if $session.token} <!-- Kui sessioonis on token -->
<li><a aria-current="{segment === 'logout' ? 'page' : undefined}" href={"logout"} on:click|preventDefault={logout}>log out</a></li> <!-- Väljalogimise link -->
{:else} <!-- Kui sessioonis pole tokenit -->
<li><a aria-current="{segment === 'login' ? 'page' : undefined}" href="login">log in</a></li> <!-- Sisselogimise link -->
<li><a aria-current="{segment === 'register' ? 'page' : undefined}" href="register">register</a></li> <!-- Registreerimise link -->
{/if}
</ul>
</nav>
src -> server.js
import sirv from 'sirv'; // Importige Sirv moodul staatiliste failide teenindamiseks
import polka from 'polka'; // Importige Polka, kerge serveri raamistik
import compression from 'compression'; // Importige Compression, et suruda kokku vastuseid
import * as sapper from '@sapper/server'; // Importige Sapper serveri moodul
import session from 'express-session'; // Importige Express sessiooni haldamise moodul
import sessionFileStore from 'session-file-store'; // Importige sessiooni failide salvestamise moodul
const { json } = require('body-parser'); // Importige JSON kehade parsimiseks
const { PORT, NODE_ENV } = process.env; // Saage keskkonnamuutujad port ja NODE_ENV
const dev = NODE_ENV === 'development'; // Kontrollige, kas olek on arenduse režiim
const FileStore = new sessionFileStore(session); // Looge uus failide salvestamise sessioonipood
polka() // Võite kasutada ka Expressi
.use(
compression({ threshold: 0 }), // Kasutage andmete kokku surumist
json(), // Kasutage JSON kehade parsimiseks
session({ // Konfigureerige sessioon
secret: 'kamel12hg', // Sessiooni saladus
resave: true, // Säilitage sessioon isegi kui see pole muutunud
saveUninitialized: true, // Salvestage algne sessioon
cookie: {
maxAge: 31536000 // Küpsise maksimaalne kestus (1 aasta)
},
store: new FileStore({ // Määrake sessiooni pood
path: `.sessions` // Failide salvestamise tee
})
}),
sirv('static', { dev }), // Serveeri staatilisi faile arendusrežiimis
sapper.middleware({ // Sapperi vahemenüü
session: req => ({ // Sessiooni andmete tagastamine
user: req.session && req.session.user, // Kasutaja andmed sessioonist
token: req.session && req.session.token // Token sessioonist
})
})
)
.listen(PORT, err => { // Kuulake määratud porti
if (err) console.log('error', err); // Logige vead konsooli
});
Proovime











Kui kõik töötab teeme commit’i
git commit -m 'As a user I can log in and out [Delivers #siin peab olema teie story'i id]'
git push origin main
Teeme merge’i
git checkoout main
git merge '#188479647-As-a-user-I-can-log-in-and-out'
git add .
git commit
git push origin main
Siis kontrollime GitHub’is

3. Kasutaja ülevaade
Loome uue story’i “As a user I see an overview page when I log on” ja lisame ülesandeid


Loome uue branch’i “#siin peab olema teie story’i id-As-a-user-I-see-an-overview-page-when-I-log-on” ja teeme checkout
git branch '#188525805-As-a-user-I-see-an-overview-page-when-I-log-on'
git checkout '#188525805-As-a-user-I-see-an-overview-page-when-I-log-on'
Loome failid:

src -> routes ->auth -> getMyData.js
import * as api from 'api.js'; // Impordib kõik funktsioonid api.js failist
// Ekspordib postifunktsiooni, mis käsitleb HTTP POST päringuid
export function post(req, res) {
// Kutsub API-lt 'users/current' andmeid, kasutades seansi tokenit
api.get('users/current', req.session.token).then(response => {
res.setHeader('Content-Type', 'application/json'); // Seab vastuse päise, et näidata, et vastus on JSON
res.end(JSON.stringify(response)); // Saadetakse JSON-vastus kliendile
});
}
src -> routes ->auth -> getTransactions.js
import * as api from 'api.js'; // Impordib kõik funktsioonid api.js failist
// Ekspordib asünkroonse postifunktsiooni, mis käsitleb HTTP POST päringuid
export async function post(req, res) {
// Kutsub API-lt 'transactions' andmeid, kasutades seansi tokenit
api.get('transactions', req.session.token).then(response => {
res.setHeader('Content-Type', 'application/json'); // Seab vastuse päise, et näidata, et vastus on JSON
res.end(JSON.stringify(response)); // Saadetakse JSON-vastus kliendile
});
}
src -> routes -> overview.svelte
<script context="module">
// Laeb lehe andmed, kontrollib, kas kasutaja on sisse logitud
export async function preload({ params }, { token }) {
if (!token) {
this.redirect(302, `/login`); // Suunab sisselogimise lehele, kui tokenit ei ole
}
}
</script>
<script>
import { post } from "utils.js"; // Impordib postitamise funktsiooni utiliitidest
// Funktsioon, mis toob kasutaja andmed
async function getMyData() {
return await post(`auth/getMyData`).then(r => {
r.funds = r.accounts.reduce((funds, account) => funds + account.balance, 0); // Arvutab kõikide kontode saldod kokku
return r; // Tagastab andmed
});
}
// Funktsioon, mis toob tehingute andmed
async function getTransactions() {
return await post(`auth/getTransactions`); // Tagastab tehingud
}
</script>
{#if process.browser}
{#await getMyData()}
loading... <!-- Andmete laadimine -->
{:then my}
<section>
<p style="font-size:xx-large">{my.name}</p> <!-- Kuvab kasutaja nime -->
</section>
<section>
My funds
<p style="font-size:xx-large; color: {my.funds >= 0 ? 'green' : 'red'}">{my.funds}</p> <!-- Kuvab kasutaja rahalise seisundi rohelise või punase värviga -->
</section>
<section>
<ul>
{#each my.accounts as account}
<li>{account.number} {account.name}</li> <!-- Kuvab iga konto numbri ja nime -->
{/each}
</ul>
</section>
<section>
{#await getTransactions()}
Loading... <!-- Tehingute laadimine -->
{:then transactions}
<table class="table table-striped table-bordered"> <!-- Tehingute tabel -->
<thead>
<tr>
<th>SenderName</th> <!-- Saatja nimi -->
<th>Amount</th> <!-- Summa -->
<th>CreateAt</th> <!-- Loomise kuupäev -->
<th>Status</th> <!-- Staatus -->
</tr>
</thead>
<tbody>
{#each transactions as transaction}
<tr>
<td><b>{transaction.senderName}</b><br>{transaction.explanation}</td> <!-- Kuvab saatja nime ja selgituse -->
<td style="color: {transaction.amount >= 0 ? 'green' : 'red'}">{transaction.amount} {transaction.currency}</td> <!-- Kuvab summa rohelise või punase värviga -->
<td>{transaction.createdAt}</td> <!-- Kuvab loomise kuupäeva -->
<td>{transaction.status}<br>{transaction.statusDetail}</td> <!-- Kuvab tehingu staatuse ja detailsed info -->
</tr>
{/each}
</tbody>
</table>
{/await}
</section>
{/await}
{/if}
Ja muutame olemasolevaid failid

src -> components ->Nav.svelte
<script>
export let segment;
import { goto, stores } from '@sapper/app';
import { post } from 'utils.js';
const { page, session } = stores();
// Log out funktsioon
async function logout() {
// Teeb POST päringu autentsuse väljalogimiseks
await post(`auth/logout`);
// Seab sessiooni tokeni nulliks
$session.token = null;
// Suunab kasutaja peamise lehe juurde
goto('/');
}
</script>
<style>
nav {
border-bottom: 1px solid rgba(255,62,0,0.1);
font-weight: 300;
padding: 0 1em;
}
ul {
margin: 0;
padding: 0;
}
/* clearfix */
ul::after {
content: '';
display: block;
clear: both;
}
li {
display: block;
float: left;
}
[aria-current] {
position: relative;
display: inline-block;
}
[aria-current]::after {
position: absolute;
content: '';
width: calc(100% - 1em);
height: 2px;
background-color: rgb(255,62,0);
display: block;
bottom: -1px;
}
a {
text-decoration: none;
padding: 1em 0.5em;
display: block;
}
</style>
<nav>
<ul>
{#if $session.token}
<li><a aria-current="{segment === 'overview' ? 'page' : undefined}" href="overview">overview</a></li>
<li><a aria-current="{segment === 'logout' ? 'page' : undefined}" href={"logout"} on:click|preventDefault={logout}>log out</a></li>
{:else}
<li><a aria-current="{segment === 'login' ? 'page' : undefined}" href="login">log in</a></li>
<li><a aria-current="{segment === 'register' ? 'page' : undefined}" href="register">register</a></li>
{/if}
</ul>
</nav>
Proovime



Kui kõik töötab teeme commit’i
git commit -m 'As a user I see an overview page when I log on [Delivers #siin peab olema teie story'i id]'
git push origin main
Teeme merge’i
git checkoout main
git merge '#188525805-As-a-user-I-see-an-overview-page-when-I-log-on'
git add .
git commit
git push origin main
Siis kontrollime GitHub’is
