# ╔══════════════════════════════════════════════════════════════════╗ # ║ 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. # Barındıran ortam (ör. Online IDE) portu PORT ortam değişkeniyle verir. port = 8471 port_ortam = cevre.al("PORT") eger port_ortam != "": port = sayi(port_ortam) sunucu = web.sunucu(port, "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:" + metin(port)) sunucu.basla()