إنتقل إلى المحتوى الرئيسي

بناء مدير مهام

المصدر: tests/schemas/09-full-app.orb

هذا التعليمي يبني مدير مهام حقيقي خطوة بخطوة. بنهايته سيكون لديك برنامج يحتوي على:

  • كيان (Entity) Task مع استمرارية
  • سمة دورة حياة (آلة حالة لحالة المهمة)
  • سمة CRUD (قائمة، إنشاء، تعديل، حذف)
  • صفحتان مربوطتان بالسمات
OrderLifecycleFulfillment/orders/track
Orbital Unit = Entity + Traits + Pages

ما الذي نبنيه

/tasks        → TaskListPage  (تصفح، إنشاء، تعديل، حذف المهام)
/tasks/:id → التنقل إليها من القائمة (عرض التفاصيل)

الوحدة المدارية TaskManager لها كيان واحد (Task) وسمتان: واحدة لدورة حياة حالة المهمة، وأخرى لإدارة القائمة.


الخطوة 1 - كيان المهمة (Task Entity)

{
"اسم": "Task",
"استمرارية": "دائم",
"مجموعة": "tasks",
"حقول": [
{
"اسم": "id",
"نوع": "نص",
"مطلوب": true
},
{
"اسم": "title",
"نوع": "نص",
"مطلوب": true
},
{
"اسم": "description",
"نوع": "نص"
},
{
"اسم": "priority",
"نوع": "تعداد",
"قيم": [
"low",
"medium",
"high"
],
"افتراضي": "medium"
},
{
"اسم": "dueDate",
"نوع": "تاريخ"
},
{
"اسم": "assigneeId",
"نوع": "نص"
},
{
"اسم": "projectId",
"نوع": "نص"
}
]
}

persistence: "persistent" يعني أن هذا مخزن في قاعدة البيانات. مفتاح collection يحدد اسم مجموعة/جدول قاعدة البيانات.


الخطوة 2 - سمة دورة الحياة (Lifecycle Trait)

سمة TaskLifecycle تتتبع موقع المهمة في سير العمل: todo → inProgress → review → done.

{
"اسم": "TaskLifecycle",
"كيان_مرتبط": "Task",
"فئة": "interaction",
"آلة_حالة": {
"حالات": [
{
"اسم": "todo",
"أولي": true
},
{
"اسم": "inProgress"
},
{
"اسم": "review"
},
{
"اسم": "done",
"نهائي": true,
"وصف": "Task completed"
}
],
"أحداث": [
{
"مفتاح": "INIT",
"اسم": "Initialize"
},
{
"مفتاح": "START",
"اسم": "Start Task"
},
{
"مفتاح": "SUBMIT_FOR_REVIEW",
"اسم": "Submit for Review"
},
{
"مفتاح": "APPROVE",
"اسم": "Approve"
},
{
"مفتاح": "REJECT",
"اسم": "Request Changes"
},
{
"مفتاح": "COMPLETE",
"اسم": "Complete"
}
],
"انتقالات": [
{
"من": "todo",
"حدث": "INIT",
"إلى": "todo",
"تأثيرات": [
[
"جلب",
"Task"
],
[
"عرض_واجهة",
"main",
{
"نوع": "stats",
"عناصر": [
{
"تسمية": "Todo",
"value": "@كيان.todo"
},
{
"تسمية": "In Progress",
"value": "@كيان.inProgress"
},
{
"تسمية": "Done",
"value": "@كيان.done"
}
]
}
]
]
},
{
"من": "todo",
"حدث": "START",
"إلى": "inProgress"
},
{
"من": "inProgress",
"حدث": "SUBMIT_FOR_REVIEW",
"إلى": "review"
},
{
"من": "review",
"حدث": "APPROVE",
"إلى": "done",
"تأثيرات": [
[
"بث",
"TASK_COMPLETED",
{
"taskId": "@كيان.id",
"projectId": "@كيان.projectId"
}
]
]
},
{
"من": "review",
"حدث": "REJECT",
"إلى": "inProgress"
},
{
"من": "inProgress",
"حدث": "COMPLETE",
"إلى": "done",
"تأثيرات": [
[
"بث",
"TASK_COMPLETED",
{
"taskId": "@كيان.id",
"projectId": "@كيان.projectId"
}
]
]
}
]
}
}

أنماط ملحوظة:

  • الحلقة الذاتية INIT تعرض لوحة stats توضح العدد حسب الحالة
  • isTerminal: true على done يعني أنه لا يُسمح بانتقالات إضافية من تلك الحالة
  • emit تنشر حدثاً عبر الوحدات المدارية (انظر التواصل عبر الوحدات المدارية)

الخطوة 3 - سمة CRUD

سمة TaskCRUD تعالج واجهة إدارة القائمة: عرض القائمة، الإنشاء، التعديل، والحذف.

{
"اسم": "TaskCRUD",
"كيان_مرتبط": "Task",
"فئة": "interaction",
"آلة_حالة": {
"حالات": [
{
"اسم": "listing",
"أولي": true
},
{
"اسم": "creating"
},
{
"اسم": "editing"
}
],
"أحداث": [
{
"مفتاح": "INIT",
"اسم": "Initialize"
},
{
"مفتاح": "VIEW",
"اسم": "View Task",
"حمولة": [
{
"اسم": "id",
"نوع": "نص",
"مطلوب": true
}
]
},
{
"مفتاح": "CREATE",
"اسم": "Create Task"
},
{
"مفتاح": "EDIT",
"اسم": "Edit Task"
},
{
"مفتاح": "SAVE",
"اسم": "Save"
},
{
"مفتاح": "CANCEL",
"اسم": "Cancel"
},
{
"مفتاح": "DELETE",
"اسم": "Delete Task"
}
],
"انتقالات": [
{
"من": "listing",
"حدث": "INIT",
"إلى": "listing",
"تأثيرات": [
[
"جلب",
"Task"
],
[
"عرض_واجهة",
"main",
{
"نوع": "entity-table",
"كيان": "Task",
"columns": [
"title",
"priority",
"dueDate"
],
"itemActions": [
{
"حدث": "VIEW",
"تسمية": "View"
},
{
"حدث": "EDIT",
"تسمية": "Edit"
},
{
"حدث": "DELETE",
"تسمية": "Delete"
}
]
}
]
]
},
{
"من": "listing",
"حدث": "CREATE",
"إلى": "creating",
"تأثيرات": [
[
"عرض_واجهة",
"main",
{
"نوع": "form",
"كيان": "Task"
}
]
]
},
{
"من": "creating",
"حدث": "SAVE",
"إلى": "listing",
"تأثيرات": [
[
"حفظ",
"update",
"Task",
"@كيان"
],
[
"إشعار",
"success",
"Task created"
]
]
},
{
"من": "creating",
"حدث": "CANCEL",
"إلى": "listing"
},
{
"من": "listing",
"حدث": "EDIT",
"إلى": "editing"
},
{
"من": "editing",
"حدث": "SAVE",
"إلى": "listing",
"تأثيرات": [
[
"حفظ",
"update",
"Task",
"@كيان"
]
]
},
{
"من": "editing",
"حدث": "CANCEL",
"إلى": "listing"
},
{
"من": "listing",
"حدث": "DELETE",
"إلى": "listing",
"تأثيرات": [
[
"حفظ",
"delete",
"Task",
"@كيان.id"
],
[
"إشعار",
"info",
"Task deleted"
]
]
},
{
"من": "listing",
"حدث": "VIEW",
"إلى": "listing",
"تأثيرات": [
[
"انتقال",
"/tasks/@payload.id"
]
]
}
]
}
}

ما تفعله آلة الحالة:

  • listing - INIT يعرض الجدول. المستخدم يمكنه VIEW أو CREATE أو EDIT أو DELETE من هنا.
  • creating - ينتقل إلى نموذج؛ SAVE يحفظ ويعود للقائمة، CANCEL يعود
  • editing - نفس نمط creating لكن لسجل موجود
  • VIEW يتنقل إلى صفحة التفاصيل باستخدام id من الحمولة

الحمولة في الأحداث: حدث VIEW يحمل id ليعرف وقت التشغيل أي مهمة تم النقر عليها. يمكن الوصول إليها في التأثيرات بـ @payload.id.


الخطوة 4 - إضافة الصفحات (Pages)

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

التحقق والتشغيل

# التحقق من البرنامج
orb validate schema.orb

# بدء خادم التطوير
orb dev

انتقل إلى http://localhost:3000/tasks لرؤية مدير المهام.


الخطوات التالية