diff --git a/crud/data-preparation/users.json b/crud/data-preparation/users.json new file mode 100644 index 0000000..82a0056 --- /dev/null +++ b/crud/data-preparation/users.json @@ -0,0 +1,232 @@ +[ + { + "id": 1, + "name": "Leanne Graham", + "username": "Bret", + "email": "Sincere@april.biz", + "address": { + "street": "Kulas Light", + "suite": "Apt. 556", + "city": "Gwenborough", + "zipcode": "92998-3874", + "geo": { + "lat": "-37.3159", + "lng": "81.1496" + } + }, + "phone": "1-770-736-8031 x56442", + "website": "hildegard.org", + "company": { + "name": "Romaguera-Crona", + "catchPhrase": "Multi-layered client-server neural-net", + "bs": "harness real-time e-markets" + } + }, + { + "id": 2, + "name": "Ervin Howell", + "username": "Antonette", + "email": "Shanna@melissa.tv", + "address": { + "street": "Victor Plains", + "suite": "Suite 879", + "city": "Wisokyburgh", + "zipcode": "90566-7771", + "geo": { + "lat": "-43.9509", + "lng": "-34.4618" + } + }, + "phone": "010-692-6593 x09125", + "website": "anastasia.net", + "company": { + "name": "Deckow-Crist", + "catchPhrase": "Proactive didactic contingency", + "bs": "synergize scalable supply-chains" + } + }, + { + "id": 3, + "name": "Clementine Bauch", + "username": "Samantha", + "email": "Nathan@yesenia.net", + "address": { + "street": "Douglas Extension", + "suite": "Suite 847", + "city": "McKenziehaven", + "zipcode": "59590-4157", + "geo": { + "lat": "-68.6102", + "lng": "-47.0653" + } + }, + "phone": "1-463-123-4447", + "website": "ramiro.info", + "company": { + "name": "Romaguera-Jacobson", + "catchPhrase": "Face to face bifurcated interface", + "bs": "e-enable strategic applications" + } + }, + { + "id": 4, + "name": "Patricia Lebsack", + "username": "Karianne", + "email": "Julianne.OConner@kory.org", + "address": { + "street": "Hoeger Mall", + "suite": "Apt. 692", + "city": "South Elvis", + "zipcode": "53919-4257", + "geo": { + "lat": "29.4572", + "lng": "-164.2990" + } + }, + "phone": "493-170-9623 x156", + "website": "kale.biz", + "company": { + "name": "Robel-Corkery", + "catchPhrase": "Multi-tiered zero tolerance productivity", + "bs": "transition cutting-edge web services" + } + }, + { + "id": 5, + "name": "Chelsey Dietrich", + "username": "Kamren", + "email": "Lucio_Hettinger@annie.ca", + "address": { + "street": "Skiles Walks", + "suite": "Suite 351", + "city": "Roscoeview", + "zipcode": "33263", + "geo": { + "lat": "-31.8129", + "lng": "62.5342" + } + }, + "phone": "(254)954-1289", + "website": "demarco.info", + "company": { + "name": "Keebler LLC", + "catchPhrase": "User-centric fault-tolerant solution", + "bs": "revolutionize end-to-end systems" + } + }, + { + "id": 6, + "name": "Mrs. Dennis Schulist", + "username": "Leopoldo_Corkery", + "email": "Karley_Dach@jasper.info", + "address": { + "street": "Norberto Crossing", + "suite": "Apt. 950", + "city": "South Christy", + "zipcode": "23505-1337", + "geo": { + "lat": "-71.4197", + "lng": "71.7478" + } + }, + "phone": "1-477-935-8478 x6430", + "website": "ola.org", + "company": { + "name": "Considine-Lockman", + "catchPhrase": "Synchronised bottom-line interface", + "bs": "e-enable innovative applications" + } + }, + { + "id": 7, + "name": "Kurtis Weissnat", + "username": "Elwyn.Skiles", + "email": "Telly.Hoeger@billy.biz", + "address": { + "street": "Rex Trail", + "suite": "Suite 280", + "city": "Howemouth", + "zipcode": "58804-1099", + "geo": { + "lat": "24.8918", + "lng": "21.8984" + } + }, + "phone": "210.067.6132", + "website": "elvis.io", + "company": { + "name": "Johns Group", + "catchPhrase": "Configurable multimedia task-force", + "bs": "generate enterprise e-tailers" + } + }, + { + "id": 8, + "name": "Nicholas Runolfsdottir V", + "username": "Maxime_Nienow", + "email": "Sherwood@rosamond.me", + "address": { + "street": "Ellsworth Summit", + "suite": "Suite 729", + "city": "Aliyaview", + "zipcode": "45169", + "geo": { + "lat": "-14.3990", + "lng": "-120.7677" + } + }, + "phone": "586.493.6943 x140", + "website": "jacynthe.com", + "company": { + "name": "Abernathy Group", + "catchPhrase": "Implemented secondary concept", + "bs": "e-enable extensible e-tailers" + } + }, + { + "id": 9, + "name": "Glenna Reichert", + "username": "Delphine", + "email": "Chaim_McDermott@dana.io", + "address": { + "street": "Dayna Park", + "suite": "Suite 449", + "city": "Bartholomebury", + "zipcode": "76495-3109", + "geo": { + "lat": "24.6463", + "lng": "-168.8889" + } + }, + "phone": "(775)976-6794 x41206", + "website": "conrad.com", + "company": { + "name": "Yost and Sons", + "catchPhrase": "Switchable contextually-based project", + "bs": "aggregate real-time technologies" + } + }, + { + "id": 10, + "name": "Clementina DuBuque", + "username": "Moriah.Stanton", + "email": "Rey.Padberg@karina.biz", + "address": { + "street": "Kattie Turnpike", + "suite": "Suite 198", + "city": "Lebsackbury", + "zipcode": "31428-2261", + "geo": { + "lat": "-38.2386", + "lng": "57.2232" + } + }, + "phone": "024-648-3804", + "website": "ambrose.net", + "company": { + "name": "Hoeger LLC", + "catchPhrase": "Centralized empowering task-force", + "bs": "target end-to-end models" + } + } +] diff --git a/crud/data-preparation/users_import.sql b/crud/data-preparation/users_import.sql new file mode 100644 index 0000000..8864104 --- /dev/null +++ b/crud/data-preparation/users_import.sql @@ -0,0 +1,101 @@ +-- SQLite script to create tables and import JSON data +-- Usage: sqlite3 database.db < script.sql + +-- Enable foreign key constraints +PRAGMA foreign_keys = ON; + +-- Drop tables if they exist (for clean re-runs) +DROP TABLE IF EXISTS user; +DROP TABLE IF EXISTS address; +DROP TABLE IF EXISTS company; + +-- Create company table +CREATE TABLE company ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + catch_phrase TEXT, + bs TEXT +); + +-- Create address table +CREATE TABLE address ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + street TEXT NOT NULL, + suite TEXT, + city TEXT NOT NULL, + zipcode TEXT, + lat TEXT, + lng TEXT +); + +-- Create user table +CREATE TABLE user ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + username TEXT UNIQUE NOT NULL, + email TEXT UNIQUE NOT NULL, + address_id INTEGER NOT NULL, + phone TEXT, + website TEXT, + company_id INTEGER NOT NULL, + FOREIGN KEY (address_id) REFERENCES address(id) ON DELETE CASCADE, + FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE +); + +-- Create indexes for better query performance +CREATE INDEX idx_user_username ON user(username); +CREATE INDEX idx_user_email ON user(email); +CREATE INDEX idx_user_address ON user(address_id); +CREATE INDEX idx_user_company ON user(company_id); + +-- Import data using JSON functions +-- Insert companies +INSERT INTO company (name, catch_phrase, bs) +SELECT DISTINCT + json_extract(value, '$.company.name'), + json_extract(value, '$.company.catchPhrase'), + json_extract(value, '$.company.bs') +FROM json_each(readfile('users.json')); + +-- Insert addresses +INSERT INTO address (street, suite, city, zipcode, lat, lng) +SELECT + json_extract(value, '$.address.street'), + json_extract(value, '$.address.suite'), + json_extract(value, '$.address.city'), + json_extract(value, '$.address.zipcode'), + json_extract(value, '$.address.geo.lat'), + json_extract(value, '$.address.geo.lng') +FROM json_each(readfile('users.json')); + +-- Insert users with foreign key references +INSERT INTO user (id, name, username, email, address_id, phone, website, company_id) +SELECT + json_extract(value, '$.id'), + json_extract(value, '$.name'), + json_extract(value, '$.username'), + json_extract(value, '$.email'), + (SELECT a.id FROM address a + WHERE a.street = json_extract(value, '$.address.street') + AND a.city = json_extract(value, '$.address.city') + LIMIT 1), + json_extract(value, '$.phone'), + json_extract(value, '$.website'), + (SELECT c.id FROM company c + WHERE c.name = json_extract(value, '$.company.name') + LIMIT 1) +FROM json_each(readfile('users.json')); + +-- Display summary +SELECT 'Data import completed successfully!' as status; +SELECT 'Total users: ' || COUNT(*) as summary FROM user; +SELECT 'Total addresses: ' || COUNT(*) as summary FROM address; +SELECT 'Total companies: ' || COUNT(*) as summary FROM company; + +-- Show sample data +SELECT 'Sample data from user table:' as info; +SELECT u.id, u.name, u.email, c.name as company, a.city +FROM user u +JOIN company c ON u.company_id = c.id +JOIN address a ON u.address_id = a.id +LIMIT 5; \ No newline at end of file diff --git a/hypermedia/1-example/display-record1.html b/hypermedia/1-example/display-record1.html index c768945..b0c04cd 100644 --- a/hypermedia/1-example/display-record1.html +++ b/hypermedia/1-example/display-record1.html @@ -35,6 +35,6 @@ diff --git a/hypermedia/1-example/display-record2.html b/hypermedia/1-example/display-record2.html index 6d3bb5e..48b6c33 100644 --- a/hypermedia/1-example/display-record2.html +++ b/hypermedia/1-example/display-record2.html @@ -35,6 +35,6 @@ \ No newline at end of file diff --git a/hypermedia/1-example/display-record3.html b/hypermedia/1-example/display-record3.html index 2032c17..18124d3 100644 --- a/hypermedia/1-example/display-record3.html +++ b/hypermedia/1-example/display-record3.html @@ -35,6 +35,6 @@ \ No newline at end of file diff --git a/hypermedia/2-example/recordx.json b/hypermedia/2-example/recordx.json deleted file mode 100644 index f7eba27..0000000 --- a/hypermedia/2-example/recordx.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "username": "SofiaChen", - "email": "sofia.c@cloudnet.org", - "street": "Maple Avenue", - "suite": "Suite 210", - "city": "Oakridge", - "zipcode": "45678-9012", - "phone": "555-987-6543 x2156", - "website": "sofiachen.dev" - } diff --git a/slides/datastar/slides.md b/slides/datastar/slides.md index c895ebe..76027fe 100644 --- a/slides/datastar/slides.md +++ b/slides/datastar/slides.md @@ -170,7 +170,6 @@ Features: - Generic Data Handling. - High-Level CRUD Operations. - Fluent Transaction API. -- Database Introspection. - Abstraction and Safety. - Utility Functions. @@ -221,12 +220,39 @@ class: default ADR, core+plugins, Signals, Ideomorph, Core-Engine, Plug-ins, SSE, You have to control the backend, Templating, HTMX, Hypermedia, Hateoas, Locality of behaviour, -Declarative vs. Imperative, DS conforms strictly to the specs. +Declarative vs. Imperative, DS conforms strictly to the web's specs. -Quote Gillian Delany: +--- +class: default +--- -The problem is Datastar is actually a backend agnostic backend framework with a 10 Kb shim. There has never been anything like it in practice. So it is hard to explain. +# Learn Some Templating System: +
+| Concept | Example | Meaning | +| ----------------- | ---------------------------------------- | -------------------------- | +| **Interpolation** | `{{ name }}` | Insert value of `name` | +| **Loop** | `{% for item in items %}...{% endfor %}` | Repeat block for each item | +| **Condition** | `{% if logged_in %}Welcome{% endif %}` | Conditional rendering | +| **Include** | `{% include 'header.html' %}` | Reuse a subtemplate | +| **Escaping** | `{{{ raw_html }}}` or `{{& raw_html}}` | Control HTML escaping | + + +--- +class: default +--- + +# Templating and Hypermedia: + + +| | Templating | Hypermedia as the Engine of Application State | +| --------- | ------------------------ | ------------------------------------------ | +| Input | Data | Data + available transitions | +| Output | Document (HTML) | Document representing a state with actions | +| Function | Bind data to structure | Bind state transitions to structure | +| Goal | Present information | Drive navigation and state evolution | +| Mechanism | Placeholder substitution | Link/form embedding | +| Example | `{{.Title}}` → “Article” | `Edit` | ---