الصفحات (Pages)
كيف تعمل الصفحات في بنية Orb - التوجيه، ربط السمات، الفتحات، والتنقل.
ذو صلة:
نظرة عامة
في Orb، الصفحة (Page) هي مسار يجمع السمات لعرض واجهة المستخدم. التركيبة الأساسية هي:
Orbital = Entity + Traits + Pages
بينما تحدد الكيانات البيانات والسمات السلوك، تحدد الصفحات أين يتفاعل المستخدمون مع النظام. الصفحات مدفوعة بالسمات - لا تحتوي على واجهة مستخدم مباشرة، بل تشير إلى سمات تملأ تأثيرات render-ui الخاصة بها الصفحة.
تعريف الصفحة (Page)
تُعرَّف الصفحة (Page) في برنامج .orb بالبنية التالية:
{
"اسم": "TaskListPage",
"مسار": "/tasks",
"نوع_العرض": "list",
"الكيان_الأساسي": "Task",
"سمات": [
{
"مرجع": "TaskBrowser",
"كيان_مرتبط": "Task"
},
{
"مرجع": "FilterPanel",
"كيان_مرتبط": "Task"
}
]
}
خصائص الصفحة
| الخاصية | مطلوبة | الوصف |
|---|---|---|
name | نعم | معرِّف بصيغة PascalCase (مثال: TaskListPage) |
path | نعم | مسار URL يبدأ بـ / |
viewType | لا | تلميح دلالي: list، detail، create، edit، dashboard، custom |
primaryEntity | لا | الكيان الأساسي الذي تعمل عليه هذه الصفحة |
traits | نعم | مصفوفة مراجع السمات التي تقود الواجهة |
isInitial | لا | ما إذا كانت هذه صفحة نقطة الدخول |
المسارات وأنماط المسارات
مسارات الصفحات تحدد مسارات URL لتطبيقك.
قواعد المسارات
- يجب أن تبدأ بـ
/ - الأحرف الصالحة: حروف، أرقام، شرطات، شرطات سفلية، نقطتان، شرطات مائلة
- يجب أن تكون فريدة عبر جميع الصفحات في البرنامج
المسارات الثابتة
مسارات بسيطة بدون أجزاء ديناميكية:
{ "path": "/tasks" }
{ "path": "/dashboard" }
{ "path": "/settings/profile" }
الأجزاء الديناميكية
استخدم صيغة النقطتين للمعاملات الديناميكية:
{ "path": "/tasks/:id" }
{ "path": "/users/:userId/tasks/:taskId" }
{ "path": "/projects/:projectId/members/:memberId" }
تُستخرج الأجزاء الديناميكية وتكون متاحة في:
- حمولات الأحداث (
@payload.id) - تأثيرات التنقل
- عمليات البحث عن الكيانات
أمثلة المسارات
| المسار | الوصف |
|---|---|
/tasks | صفحة قائمة المهام |
/tasks/:id | تفاصيل مهمة واحدة |
/tasks/create | إنشاء مهمة جديدة |
/tasks/:id/edit | تعديل مهمة موجودة |
/users/:id/profile | ملف المستخدم |
/dashboard | عرض لوحة المعلومات |
أنواع العرض (View Types)
أنواع العرض هي تلميحات دلالية حول غرض الصفحة:
| النوع | الغرض | الأنماط النموذجية |
|---|---|---|
list | عرض مجموعة كيانات | entity-table، entity-cards، entity-list |
detail | عرض كيان واحد | entity-detail، stats |
create | إنشاء كيان جديد | form |
edit | تعديل كيان موجود | form |
dashboard | نظرة عامة بأقسام متعددة | dashboard-grid، stats |
custom | تخطيط مخصص | أي أنماط |
مهم: أنواع العرض لا تقيّد الواجهة. العرض الفعلي يُتحكم به عبر تأثيرات render-ui في السمات. أنواع العرض هي بيانات وصفية لأجل:
- التوثيق
- تلميحات توليد الكود
- بناء هيكل الواجهة
ربط الصفحة بالسمة
الصفحات تشير إلى السمات التي توفر سلوكها وواجهتها.
مراجع السمات
{
"صفحات": [
{
"اسم": "TaskListPage",
"مسار": "/tasks",
"سمات": [
{
"مرجع": "TaskBrowser",
"كيان_مرتبط": "Task"
},
{
"مرجع": "QuickActions",
"كيان_مرتبط": "Task",
"تكوين": {
"showCreate": true
}
}
]
}
]
}
بنية PageTraitRef
| الخاصية | مطلوبة | الوصف |
|---|---|---|
ref | نعم | اسم السمة أو مسارها (مثال: "TaskBrowser"، "Std.traits.CRUD") |
linkedEntity | لا | الكيان الذي تعمل عليه هذه السمة |
config | لا | إعدادات خاصة بالسمة |
سمات متعددة لكل صفحة
يمكن للصفحة أن تحتوي على سمات متعددة، كل منها تساهم بواجهة في فتحات مختلفة:
{
"اسم": "DashboardPage",
"مسار": "/dashboard",
"سمات": [
{
"مرجع": "StatsSummary",
"كيان_مرتبط": "Analytics"
},
{
"مرجع": "RecentActivity",
"كيان_مرتبط": "Activity"
},
{
"مرجع": "QuickActions",
"كيان_مرتبط": "Task"
}
]
}
كل تأثير render-ui في السمة يستهدف فتحات محددة.
linkedEntity على السمات
خاصية linkedEntity تربط السمة بكيان محدد:
{
"مرجع": "StatusManager",
"كيان_مرتبط": "Task"
}
هذا يعني:
- ربط
@entityفي السمة يُحل إلى بياناتTask - تأثيرات مثل
persistتعمل على مجموعةTask - آلة حالة السمة تدير نسخ
Task
انظر ربط السمة بالكيان للتفاصيل.
الكيان الأساسي (Primary Entity)
خاصية primaryEntity تشير إلى الكيان الرئيسي الذي تعمل عليه الصفحة:
{
"اسم": "TaskDetailPage",
"مسار": "/tasks/:id",
"الكيان_الأساسي": "Task",
"سمات": [
{
"مرجع": "TaskViewer"
},
{
"مرجع": "CommentList",
"كيان_مرتبط": "Comment"
}
]
}
الاستخدام:
- الكيان الافتراضي للسمات بدون
linkedEntityصريح - التحقق من وجود الكيان
- تلميحات توليد الكود
- ليس مطلوباً إذا حددت جميع السمات كيانها صراحة
الفتحات وعرض واجهة المستخدم
السمات تعرض واجهة المستخدم عبر تأثيرات render-ui التي تستهدف الفتحات (Slots) - مناطق مسماة في الصفحة.
الفتحات المتاحة
| الفتحة | الغرض |
|---|---|
main | منطقة المحتوى الأساسي |
sidebar | لوحة جانبية |
modal | طبقة نافذة منبثقة |
drawer | لوحة درج |
overlay | طبقة ملء الشاشة |
center | محتوى مركزي |
toast | إشعارات مؤقتة |
hud-top | HUD علوي (واجهة الألعاب) |
hud-bottom | HUD سفلي (واجهة الألعاب) |
floating | عنصر عائم |
system | مكونات نظام غير مرئية |
تأثير render-ui
السمات تملأ الفتحات باستخدام تأثير render-ui:
[
"عرض_واجهة",
"main",
{
"نوع": "entity-table",
"كيان": "Task",
"columns": [
"title",
"status",
"dueDate"
],
"itemActions": [
{
"حدث": "VIEW",
"تسمية": "View"
},
{
"حدث": "EDIT",
"تسمية": "Edit"
}
]
}
]
مسار الفتحات
┌─────────────────────────────────────────────────────────────┐
│ Page: TaskListPage │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Slot: main │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ Pattern: entity-table (from TaskBrowser) │ │ │
│ │ │ - Columns: title, status, dueDate │ │ │
│ │ │ - Actions: VIEW, EDIT │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Slot: sidebar │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ Pattern: filter-panel (from FilterPanel) │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
عمليات عرض متعددة لنفس الفتحة
إذا عرضت سمات متعددة في نفس الفتحة، تتراكم (الأحدث تستبدل أو تُضاف حسب نوع النمط):
// السمة A
["render-ui", "main", { "type": "stats", ... }]
// السمة B (لاحقاً في الصفحة)
["render-ui", "main", { "type": "entity-table", ... }]
التنقل (Navigation)
التنقل بين الصفحات يُعالج عبر تأثير navigate في السمات.
تأثير navigate
[
"انتقال",
"/tasks/:id",
{
"معرف": "@حمولة.taskId"
}
]
الصيغة: ["navigate", path, params?]
| الوسيط | الوصف |
|---|---|
path | مسار الصفحة المستهدفة (يمكن أن يتضمن أجزاء ديناميكية) |
params | كائن اختياري لملء الأجزاء الديناميكية |
أمثلة التنقل
تنقل بسيط:
[
"انتقال",
"/dashboard"
]
مع معرِّف الكيان:
[
"انتقال",
"/tasks/@entity.id"
]
مع الحمولة:
[
"انتقال",
"/tasks/:id",
{
"معرف": "@حمولة.taskId"
}
]
مسار متداخل:
[
"انتقال",
"/users/:userId/tasks/:taskId",
{
"userId": "@كيان.assigneeId",
"taskId": "@كيان.id"
}
]
التنقل في الانتقالات
التنقل عادة يحدث بعد تغييرات الحالة:
{
"من": "editing",
"إلى": "saved",
"حدث": "SAVE",
"تأثيرات": [
[
"حفظ",
"update",
"Task",
"@كيان.id",
"@حمولة"
],
[
"إشعار",
"Task saved!",
"success"
],
[
"انتقال",
"/tasks/@entity.id"
]
]
}
انظر التأثيرات لمزيد من التفاصيل.
الصفحة الأولية (Initial Page)
حدد صفحة كنقطة دخول باستخدام isInitial:
{
"اسم": "HomePage",
"مسار": "/",
"أولي": true,
"سمات": [
{
"مرجع": "WelcomeBanner"
}
]
}
السلوك:
- التطبيق يحمّل هذه الصفحة أولاً
- إعادة التوجيه من الجذر (
/) تذهب إلى هنا - صفحة واحدة فقط يجب تحديدها كأولية لكل وحدة مدارية
التحقق من الصفحة (Page Validation)
تُتحقق الصفحات في وقت التصريف بهذه القواعد:
الحقول المطلوبة
name- يجب أن يكون بصيغة PascalCasepath- يجب أن يبدأ بـ/، أحرف صالحة فقطtraits- يجب أن تحتوي على مرجع سمة واحد على الأقل
أخطاء التحقق
| الخطأ | الوصف |
|---|---|
PageMissingName | اسم الصفحة مطلوب |
PageMissingPath | مسار الصفحة مطلوب |
PageInvalidPath | المسار لا يطابق النمط |
PageEmptyTraits | مصفوفة السمات لا يمكن أن تكون فارغة |
PageInvalidTraitRef | السمة المشار إليها غير موجودة |
PageInvalidViewType | viewType ليس في القائمة الصالحة |
PageDuplicatePath | صفحة أخرى تستخدم نفس المسار |
مثال كامل
مثال صفحة كاملة مع سمات متعددة:
مدار TaskManagement {
كيان Task {
id : نص!
title : نص!
status : نص
assigneeId : نص
}
سمة TaskBrowser -> Task {
أولي: idle
حالة idle {
تهيئة -> viewing
(جلب Task { })
(عرض_واجهة main { type: "entity-table", entity: "Task", fields: ["title", "status", "assigneeId"], columns: ["title", "status", "assigneeId"], itemActions: [{ event: "VIEW", label: "View" }] })
}
حالة viewing {
VIEW -> viewing
(انتقال "/tasks/@payload.id" { id: "@entity.id" })
}
}
سمة TaskViewer -> Task {
أولي: loading
حالة loading {
تهيئة -> viewing
(جلب Task { id: "@payload.id" })
(عرض_واجهة main { type: "detail-panel", entity: "Task", fields: ["title", "status", "assigneeId"] })
}
حالة viewing {
EDIT -> viewing
(انتقال "/tasks/@entity.id/edit")
BACK -> viewing
(انتقال "/tasks" { id: "@entity.id" })
}
}
صفحة "/tasks" -> TaskBrowser
صفحة "/tasks/:id" -> TaskViewer
}
المبادئ الأساسية
-
الصفحات مدفوعة بالسمات - الصفحات حاويات لمراجع السمات. الواجهة تنبثق من تأثيرات
render-uiفي السمات، وليس من تعريفات الصفحات. -
بنية الفتحات - الواجهة تتدفق عبر فتحات موحدة (
main،sidebar،modal)، مما يمكّن تركيب التخطيطات بدون تعليمات ثابتة. -
المسار كعقد - مسار الصفحة هو الواجهة الأساسية، يحدد عنوان URL الذي يتنقل إليه المستخدمون.
-
ربط الكيان الصريح -
linkedEntityعلى مراجع السمات يجعل علاقات الكيانات صريحة. -
لا حالة للصفحة - الصفحات تركيبية بحتة. كل الحالة تعيش في آلات حالة السمات.
-
التنقل مدفوع بالتأثيرات - التنقل هو تأثير يُحفَّز بانتقالات السمات، وليس خاصية صفحة.
ملخص
يوفر نظام الصفحات في Orb:
- التوجيه - تنقل مبني على المسارات مع أجزاء ديناميكية
- تركيب السمات - سمات متعددة لكل صفحة، كل منها تساهم بواجهة
- الفتحات - مناطق مسماة لوضع الواجهة (main، sidebar، modal، إلخ.)
- أنواع العرض - تلميحات دلالية لغرض الصفحة (list، detail، dashboard)
- التنقل - توجيه مدفوع بالتأثيرات بين الصفحات
- ربط الكيان - علاقات كيان صريحة عبر
linkedEntity - التحقق - المُصرِّف يفرض تفرد المسارات ووجود السمات
الصفحات هي طبقة التوجيه والتركيب - تحدد أين يذهب المستخدمون، بينما السمات تحدد ماذا يحدث والكيانات تحدد ما هي البيانات المتضمنة.