Preskoči na vsebino

Zgradite upravljalnik nalog

Source: tests/schemas/09-full-app.orb

Ta vadnica korak za korakom gradi pravi upravljalnik nalog. Na koncu boste imeli program z:

  • Entiteto Task s trajnostjo
  • Lastnost zivljenjskega cikla (avtomat stanj za status naloge)
  • Lastnost CRUD (seznam, ustvari, uredi, izbrisi)
  • Dve strani, povezani z lastnostmi
OrderLifecycleFulfillment/orders/track
Orbital Unit = Entity + Traits + Pages

Kaj gradimo

/tasks        → TaskListPage  (browse, create, edit, delete tasks)
/tasks/:id → navigated to from the list (view detail)

The TaskManager orbital has one entity (Task) and two traits: one for the task's status lifecycle, one for managing the list.


Korak 1 — Entiteta Task

{
"ime": "Task",
"trajnost": "trajno",
"zbirka": "tasks",
"polja": [
{
"ime": "id",
"tip": "niz",
"obvezno": true
},
{
"ime": "title",
"tip": "niz",
"obvezno": true
},
{
"ime": "description",
"tip": "niz"
},
{
"ime": "priority",
"tip": "nastevanje",
"vrednosti": [
"low",
"medium",
"high"
],
"privzeto": "medium"
},
{
"ime": "dueDate",
"tip": "datum"
},
{
"ime": "assigneeId",
"tip": "niz"
},
{
"ime": "projectId",
"tip": "niz"
}
]
}

persistence: "persistent" means this is stored in your database. The collection key sets the database collection/table name.


Korak 2 — Lastnost zivljenjskega cikla

The TaskLifecycle trait tracks where a task is in its workflow: todo → inProgress → review → done.

{
"ime": "TaskLifecycle",
"povezanaEntiteta": "Task",
"kategorija": "interaction",
"strojStanj": {
"stanja": [
{
"ime": "todo",
"jeZacetno": true
},
{
"ime": "inProgress"
},
{
"ime": "review"
},
{
"ime": "done",
"jeTerminalno": true,
"opis": "Task completed"
}
],
"dogodki": [
{
"kljuc": "INIT",
"ime": "Initialize"
},
{
"kljuc": "START",
"ime": "Start Task"
},
{
"kljuc": "SUBMIT_FOR_REVIEW",
"ime": "Submit for Review"
},
{
"kljuc": "APPROVE",
"ime": "Approve"
},
{
"kljuc": "REJECT",
"ime": "Request Changes"
},
{
"kljuc": "COMPLETE",
"ime": "Complete"
}
],
"prehodi": [
{
"iz": "todo",
"dogodek": "INIT",
"do": "todo",
"ucinki": [
[
"pridobi",
"Task"
],
[
"izrisi-vmesnik",
"main",
{
"tip": "stats",
"elementi": [
{
"oznaka": "Todo",
"value": "@entiteta.todo"
},
{
"oznaka": "In Progress",
"value": "@entiteta.inProgress"
},
{
"oznaka": "Done",
"value": "@entiteta.done"
}
]
}
]
]
},
{
"iz": "todo",
"dogodek": "START",
"do": "inProgress"
},
{
"iz": "inProgress",
"dogodek": "SUBMIT_FOR_REVIEW",
"do": "review"
},
{
"iz": "review",
"dogodek": "APPROVE",
"do": "done",
"ucinki": [
[
"oddaj",
"TASK_COMPLETED",
{
"taskId": "@entiteta.id",
"projectId": "@entiteta.projectId"
}
]
]
},
{
"iz": "review",
"dogodek": "REJECT",
"do": "inProgress"
},
{
"iz": "inProgress",
"dogodek": "COMPLETE",
"do": "done",
"ucinki": [
[
"oddaj",
"TASK_COMPLETED",
{
"taskId": "@entiteta.id",
"projectId": "@entiteta.projectId"
}
]
]
}
]
}
}

Notable patterns here:

  • The INIT self-loop renders a stats dashboard showing count by status
  • isTerminal: true on done means no further transitions are allowed from that state
  • emit publishes a cross-orbital event (see Cross-Orbital Communication)

Korak 3 — Lastnost CRUD

The TaskCRUD trait handles the list management UI: viewing the list, creating, editing, and deleting tasks.

{
"ime": "TaskCRUD",
"povezanaEntiteta": "Task",
"kategorija": "interaction",
"strojStanj": {
"stanja": [
{
"ime": "listing",
"jeZacetno": true
},
{
"ime": "creating"
},
{
"ime": "editing"
}
],
"dogodki": [
{
"kljuc": "INIT",
"ime": "Initialize"
},
{
"kljuc": "VIEW",
"ime": "View Task",
"podatki": [
{
"ime": "id",
"tip": "niz",
"obvezno": true
}
]
},
{
"kljuc": "CREATE",
"ime": "Create Task"
},
{
"kljuc": "EDIT",
"ime": "Edit Task"
},
{
"kljuc": "SAVE",
"ime": "Save"
},
{
"kljuc": "CANCEL",
"ime": "Cancel"
},
{
"kljuc": "DELETE",
"ime": "Delete Task"
}
],
"prehodi": [
{
"iz": "listing",
"dogodek": "INIT",
"do": "listing",
"ucinki": [
[
"pridobi",
"Task"
],
[
"izrisi-vmesnik",
"main",
{
"tip": "entity-table",
"entiteta": "Task",
"columns": [
"title",
"priority",
"dueDate"
],
"itemActions": [
{
"dogodek": "VIEW",
"oznaka": "View"
},
{
"dogodek": "EDIT",
"oznaka": "Edit"
},
{
"dogodek": "DELETE",
"oznaka": "Delete"
}
]
}
]
]
},
{
"iz": "listing",
"dogodek": "CREATE",
"do": "creating",
"ucinki": [
[
"izrisi-vmesnik",
"main",
{
"tip": "form",
"entiteta": "Task"
}
]
]
},
{
"iz": "creating",
"dogodek": "SAVE",
"do": "listing",
"ucinki": [
[
"shrani",
"update",
"Task",
"@entiteta"
],
[
"obvesti",
"success",
"Task created"
]
]
},
{
"iz": "creating",
"dogodek": "CANCEL",
"do": "listing"
},
{
"iz": "listing",
"dogodek": "EDIT",
"do": "editing"
},
{
"iz": "editing",
"dogodek": "SAVE",
"do": "listing",
"ucinki": [
[
"shrani",
"update",
"Task",
"@entiteta"
]
]
},
{
"iz": "editing",
"dogodek": "CANCEL",
"do": "listing"
},
{
"iz": "listing",
"dogodek": "DELETE",
"do": "listing",
"ucinki": [
[
"shrani",
"delete",
"Task",
"@entiteta.id"
],
[
"obvesti",
"info",
"Task deleted"
]
]
},
{
"iz": "listing",
"dogodek": "VIEW",
"do": "listing",
"ucinki": [
[
"pojdi",
"/tasks/@payload.id"
]
]
}
]
}
}

What the state machine does:

  • listing — INIT renders the table. User can VIEW, CREATE, EDIT, or DELETE from here.
  • creating — transitions to a form; SAVE persists and returns to listing, CANCEL goes back
  • editing — same pattern as creating but for an existing record
  • VIEW navigates to a detail page using the payload's id

Payload on events: The VIEW event carries an id so the runtime knows which task was clicked. Access it in effects with @payload.id.


Korak 4 — Dodajte strani

"pages": [
{
"name": "TaskListPage",
"path": "/tasks",
"traits": [
{ "ref": "TaskCRUD", "linkedEntity": "Task" }
]
}
]

The lifecycle trait (TaskLifecycle) doesn't need its own page here — it's wired to the same data and its events are triggered programmatically. The list page uses TaskCRUD, which manages the browsing experience.


Celoten program

orbitala TaskManager {
entiteta Task [trajno: tasks] {
id : niz!
title : niz!
description : niz
priority : niz
dueDate : datumCas
assigneeId : niz
projectId : niz
}
znacilnost TaskLifecycle -> Task [interakcija] {
zacetno: todo
stanje todo {
ZACETEK -> todo
(pridobi Task)
(izrisi-vmesnik main { type: "stats", entity: "Task", title: "Task Overview" })
START -> inProgress
}
stanje inProgress {
SUBMIT_FOR_REVIEW -> review
COMPLETE -> done
(shrani update Task @entiteta)
(obvesti success "Task completed!")
}
stanje review {
APPROVE -> done
(shrani update Task @entiteta)
(obvesti success "Task approved!")
REJECT -> inProgress
}
stanje done {}
}
znacilnost TaskCRUD -> Task [interakcija] {
zacetno: listing
stanje listing {
ZACETEK -> listing
(pridobi Task)
(izrisi-vmesnik main { type: "entity-table", entity: "Task", fields: ["title", "priority", "dueDate"], columns: ["title", "priority", "dueDate"], itemActions: [{ event: "VIEW", label: "View" }, { event: "EDIT", label: "Edit" }, { event: "DELETE", label: "Delete" }] })
CREATE -> creating
(izrisi-vmesnik main { type: "form", entity: "Task", fields: ["title", "description", "priority", "dueDate"] })
EDIT -> editing
DELETE -> listing
(shrani delete Task @entiteta.id)
(obvesti info "Task deleted")
VIEW -> listing
(pojdi "/tasks/@payload.id")
}
stanje creating {
SAVE -> listing
(shrani update Task @entiteta)
(obvesti success "Task created")
CANCEL -> listing
}
stanje editing {
SAVE -> listing
(shrani update Task @entiteta)
CANCEL -> listing
}
}
stran "/tasks" -> TaskCRUD
}

Preverite in zazenite

# Validate the schema
orb validate schema.orb

# Start the dev server
orb dev

Navigate to http://localhost:3000/tasks to see your task manager.


Naslednji koraki