Files
ornekler/web/pano/pano.kbl
T
semih e0e4a0d6c7 KabaLang örnekleri: konsol, masaüstü ve web için dokuz proje
Konsol: fraktal (paralel şeritli 24-bit Mandelbrot/Julia + yakınlaşma),
sudoku (geri izlemeli, canlı animasyon), fatura (JSON → terminal tablosu,
PDF ve Excel).
Masaüstü: hesap makinesi (işlem önceliği, canlı bağlama), odak (Pomodoro),
parola atölyesi (entropi ölçer, SHA-256).
Web: pano (Kanban REST API + SQLite), kisalt (302 yönlendirme, SVG
istatistik), anket (adres başına tek oy, sunucuda çizilen grafik).

Hepsi `kabalang calistir` ile derlenip çalışır; web uygulamaları yalnız
127.0.0.1'i dinler, SQL parametre bağlamalı, HTML çıktısı kaçırılır.
2026-10-03 08:37:47 +03:00

159 lines
7.4 KiB
Plaintext

# ╔══════════════════════════════════════════════════════════════════╗
# ║ PANO — KabaLang ile Kanban görev panosu ║
# ║ ║
# ║ · JSON REST API: GET · POST · PUT · DELETE /api/gorevler ║
# ║ · Kalıcı kayıt: SQLite, her sorgu PARAMETRE BAĞLAMALI ║
# ║ · Ön yüz: arayuz.html (tek sayfa, dış bağımlılık yok) ║
# ╚══════════════════════════════════════════════════════════════════╝
#
# Çalıştır: cd web/pano && kabalang calistir pano.kbl
# Aç: http://127.0.0.1:8471
kullan kaba.web
kullan kaba.json
kullan kaba.veritabani
kullan kaba.sistem
# Panoda yalnız bu üç sütun vardır. Kapalı küme → istemciden gelen
# sütun adı bu listede değilse istek reddedilir.
SUTUNLAR = ["yapilacak", "suruyor", "bitti"]
ONCELIKLER = ["dusuk", "orta", "yuksek"]
db = cevre.al("PANO_DB")
eger db == "":
db = "pano.db"
# ── Veritabanı ──────────────────────────────────────────────────────
fonksiyon hazirla(db):
veritabani.sqlite(db, "CREATE TABLE IF NOT EXISTS gorev(id INTEGER PRIMARY KEY AUTOINCREMENT, baslik TEXT NOT NULL, aciklama TEXT DEFAULT '', sutun TEXT NOT NULL, oncelik TEXT DEFAULT 'orta', olusturma TEXT);")
# İlk açılışta pano boş görünmesin: birkaç örnek kart.
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev") == "0":
ornekler = [
["Giriş ekranını tasarla", "Koyu tema, mobil öncelikli", "bitti", "yuksek"],
["REST API taslağı", "GET · POST · PUT · DELETE uçları", "bitti", "orta"],
["SQLite şeması", "Parametre bağlamalı sorgular", "suruyor", "yuksek"],
["Sürükle-bırak kartlar", "Sütunlar arası taşıma", "suruyor", "orta"],
["Bildirim e-postaları", "Görev atanınca haber ver", "yapilacak", "dusuk"],
["Karanlık/aydınlık tema", "Sistem tercihine uy", "yapilacak", "orta"],
["Yük testi", "1000 eşzamanlı istek", "yapilacak", "yuksek"]
]
dongu o icinde ornekler:
veritabani.sqlite(db, "INSERT INTO gorev(baslik, aciklama, sutun, oncelik, olusturma) VALUES (?, ?, ?, ?, ?)", [o[0], o[1], o[2], o[3], zaman.simdi()])
# Bütün görevleri JSON dizi olarak verir. JSON'u SQLite'ın kendi
# json_object/json_group_array işlevleri kurar → elle kaçış yazmayız.
fonksiyon gorevler_json(db):
sonuc = veritabani.sqlite(db, "SELECT json_group_array(json_object('id', id, 'baslik', baslik, 'aciklama', aciklama, 'sutun', sutun, 'oncelik', oncelik, 'olusturma', olusturma)) FROM (SELECT * FROM gorev ORDER BY id)")
eger sonuc == "":
don "[]"
don sonuc
fonksiyon gorev_json(db, kimlik):
don veritabani.sqlite(db, "SELECT json_object('id', id, 'baslik', baslik, 'aciklama', aciklama, 'sutun', sutun, 'oncelik', oncelik, 'olusturma', olusturma) FROM gorev WHERE id = ?", [kimlik])
# ── Doğrulama ───────────────────────────────────────────────────────
fonksiyon hata_json(ileti, durum):
don web.json(json.uret({"hata": ileti}), durum)
# Kimlik yalnız rakamlardan oluşmalı; "1 OR 1=1" gibi bir değer
# zaten parametre olarak bağlanır, ama anlamsız istek erkenden döner.
fonksiyon kimlik_gecerli(k):
eger k.uzunluk() == 0 veya k.uzunluk() > 9:
don yanlis
dongu i icinde 0..k.uzunluk() - 1:
eger degil "0123456789".icerir(k.dilim(i, 1)):
don yanlis
don dogru
# ── Uçlar ───────────────────────────────────────────────────────────
hazirla(db)
arayuz = dosya.oku("arayuz.html")
eger arayuz == "":
yazdir("⚠ arayuz.html bulunamadı — programı web/pano klasöründen çalıştırın.")
fonksiyon ana_sayfa(_istek):
don web.html(arayuz)
fonksiyon listele(_istek):
don web.json(gorevler_json(db))
fonksiyon olustur(istek):
govde = istek.govde()
eger degil json.gecerli_mi(govde):
don hata_json("gövde geçerli JSON değil", 400)
baslik = json.al(govde, "baslik").kirp()
aciklama = json.al(govde, "aciklama").kirp()
sutun = json.al(govde, "sutun")
oncelik = json.al(govde, "oncelik")
eger baslik == "":
don hata_json("başlık boş olamaz", 422)
eger baslik.uzunluk() > 120:
don hata_json("başlık en çok 120 karakter", 422)
eger sutun == "":
sutun = "yapilacak"
eger oncelik == "":
oncelik = "orta"
eger degil SUTUNLAR.icerir(sutun):
don hata_json("bilinmeyen sütun: " + sutun, 422)
eger degil ONCELIKLER.icerir(oncelik):
don hata_json("bilinmeyen öncelik: " + oncelik, 422)
veritabani.sqlite(db, "INSERT INTO gorev(baslik, aciklama, sutun, oncelik, olusturma) VALUES (?, ?, ?, ?, ?)", [baslik, aciklama, sutun, oncelik, zaman.simdi()])
yeni = veritabani.sqlite(db, "SELECT max(id) FROM gorev")
don web.json(gorev_json(db, yeni), 201)
fonksiyon guncelle(istek):
kimlik = istek.parametre("id")
eger degil kimlik_gecerli(kimlik):
don hata_json("geçersiz kimlik", 400)
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev WHERE id = ?", [kimlik]) == "0":
don hata_json("görev bulunamadı", 404)
govde = istek.govde()
eger degil json.gecerli_mi(govde):
don hata_json("gövde geçerli JSON değil", 400)
# Yalnız gönderilen alanlar güncellenir.
sutun = json.al(govde, "sutun")
eger sutun != "":
eger degil SUTUNLAR.icerir(sutun):
don hata_json("bilinmeyen sütun: " + sutun, 422)
veritabani.sqlite(db, "UPDATE gorev SET sutun = ? WHERE id = ?", [sutun, kimlik])
baslik = json.al(govde, "baslik").kirp()
eger baslik != "":
veritabani.sqlite(db, "UPDATE gorev SET baslik = ? WHERE id = ?", [baslik, kimlik])
oncelik = json.al(govde, "oncelik")
eger oncelik != "":
eger degil ONCELIKLER.icerir(oncelik):
don hata_json("bilinmeyen öncelik: " + oncelik, 422)
veritabani.sqlite(db, "UPDATE gorev SET oncelik = ? WHERE id = ?", [oncelik, kimlik])
don web.json(gorev_json(db, kimlik))
fonksiyon kaldir(istek):
kimlik = istek.parametre("id")
eger degil kimlik_gecerli(kimlik):
don hata_json("geçersiz kimlik", 400)
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev WHERE id = ?", [kimlik]) == "0":
don hata_json("görev bulunamadı", 404)
veritabani.sqlite(db, "DELETE FROM gorev WHERE id = ?", [kimlik])
don web.yanit("", 204)
# Tek iş parçacığı: SQLite'a yazan işleyiciler sırayla koşar.
sunucu = web.sunucu(8471, "127.0.0.1", 1)
sunucu.hatalar_json()
sunucu.govde_siniri(16384)
sunucu.al("/", ana_sayfa)
sunucu.al("/api/gorevler", listele)
sunucu.gonder("/api/gorevler", olustur)
sunucu.guncelle("/api/gorevler/{id}", guncelle)
# DELETE yöntemi `sunucu.kaldir` ile bağlanır
sunucu.kaldir("/api/gorevler/{id}", kaldir)
yazdir("📋 Pano hazır — http://127.0.0.1:8471")
sunucu.basla()