تطبيق تجريبي واحد زائد واحد لتطوير البرمجيات الشعار
العرض 03

طبقة الواجهة
UI + App/ButtonClicked

المحرّك الذي يحوّل الكيان إلى شاشة إدارة كاملة — ودالة واحدة في جانب الخادم لكل صفحة.

‏TableMakerEx<T> — شاشة إدارة عامة

// 1. فئة الجدول (DemoApp/Tables)
public class CarsTable : TableMakerEx<Car>
{
    public CarsTable()
    {
        this["Color"].HeaderText = "اللون";
        this["Color"].Filterable = true;
    }
}

// 2. سطر واحد في HTML الخاص بالصفحة
<div id="CarsTable" class="table"></div>
  • تُشتقّ الأعمدة تلقائيًا من سمات [Column] في الكيان.
  • وتحصل مجانًا على: جدول، وفرز بالنقر على العنوان، وترقيم صفحات، ونموذج إضافة/تحرير/حذف، وتصدير واستيراد.
  • اسم عنصر الـ‏div = اسم الفئة؛ و‏ClassManager يعثر عليها بحسب الاسم.

كيف يسير التدفّق؟

div.table + JS tablemaker.js api/tablemaker/GetTable CarsTableGetTableAsync → HTML
  • يرسل ‏JS اسم الفئة + الفرز والتصفية ورقم الصفحة؛ ويعيد الخادم HTML جاهزًا أو صفوفًا للتحديث.
  • حفظ النموذج: ‏SaveForm → ‏SaveFormAsync → ‏SaveAsync الخاصة بالكيان. والكل غير متزامن.

شريط تصفية عام

this["IsAutomatic"].Filterable = true;              // مربّع اختيار → نعم/لا/الكل
this["Grade"].Filterable = true;
this["Grade"].DataSource = new[] {1,2,3,4,5,6,7,8}; // → قائمة منسدلة
this["Color"].Filterable = true;                    // نص → مطابقة تامة
  • مربّع البحث الحرّ يبحث في جميع الأعمدة النصية (LIKE مع معاملات).
  • وكل تغيير في التصفية يحدّث الجدول دون إعادة تحميل الصفحة.
  • التنفيذ يتمّ في BuildFilter واحدة عامة — فلا كود تصفية خاص بكل شاشة.

حقول خاصة — UIField

  • ImageField — رفع الصورة بالسحب والإفلات، وتُحفظ بصيغة JPG وفق معرّف السجلّ.
  • ColorField — مُنتقي ألوان مع عرض عيّنة لونية في الجدول.
  • ButtonUiField / LinkUiField / IconUiField — إجراء في كل صف.
  • ListField<P> — اختيار متعدّد لكيانات مرتبطة (مربّعات اختيار).
  • تحقّق تصريحي: ‏IsMandatory و‏RegExp ورسائل مخصّصة — يُطبَّق في جانب العميل.

نمط App + ButtonClicked

// كل صفحة = دالة تُعيد ReturnDetails
public ReturnDetails Cars() => AdminPage("Cars");

// زر في HTML — بلا onclick:
<button id="Cars">سيارات</button>
// ‏id الزر = اسم الدالة التي ستُنفَّذ في الخادم
  • نقطة نهاية واحدة: ‏api/app/ButtonClicked.
  • ReturnDetails يخبر العميل بما عليه فعله: ‏html للحقن، أو ‏popUp، أو ‏script، أو ملء قائمة…
  • تعود حالة التطبيق إلى العميل مشفّرة ومضغوطة (ProtectAppState) — وأي عبث بها يُكتشف فورًا.
  • سجلّ تصفّح كامل: لكل صفحة عنوان URL خاص بها، بما في ذلك الدخول المباشر (deep-link).

شاشة جديدة — قائمة تحقّق

  1. كيان في طبقة BLL: ‏class Invoice : Record مع [Column].
  2. جدول: ‏class InvoicesTable : TableMakerEx<Invoice> — عناوين بلغة الواجهة + ‏Filterable.
  3. صفحة: ‏Pages/Invoices.html تتضمّن <div id="InvoicesTable" class="table">.
  4. دالة: ‏public ReturnDetails Invoices() => AdminPage("Invoices");
  5. زر في القائمة: ‏<input type="button" id="Invoices" value="الفواتير">

خمس خطوات، بلا SQL، وبلا JavaScript — وهذه هي الحكاية كلها.