مقدمة إلى إنشاء مكون تعليمات برمجية

مكتمل

Power Apps يوفر العديد مِن الوظائف المضمنة لصانعي التطبيقات لإنشاء تطبيقاتهم، ولكن فِي بعض الأحيان، ستحتاج إلى إنشاء تجارب مستخدم مخصصة للتعامل مع متطلباتك الفريدة. قد تتمثل الأمثلة فِي استبدال قيمة النسبة المئوية بمقياس، أو عرض رمز شريطي بدلاً مِن معرف، أو استبدال عناصر التحكم الموجودة بعناصر تحكم تحتوي على المزيد مِن الوظائف - مثل طريقة عرض الشبكة بالسحب والإفلات. يمكنك أيضاً أن تجعل Power Apps Component Framework يلتف حول مكونات موجودة قمت بكتابتها فِي إطارات عمل ويب أخرى، مثل React أو Angular.

يتيح لك إنشاء هذه المكونات استخدام النطاق الكامل للنظام البيئي الحديث لتطوير الويب: المكتبات، وأطر العمل، والأدوات الأخرى التي قد تكون على دراية بها، وحزم تلك الإمكانات فِي نموذج يسمح لصانعي التطبيقات بإنشاء تطبيقات باستخدام التعليمات البرمجية الخاصة بك كما لو كانت لقد كان جزءًا مِن النظام الأساسي خارج الصندوق.

يُشار إلى Power Apps المكونات المخصصة بشكل متكرر على أنها مكونات التعليمات البرمجية لأنها تتطلب تعليمات برمجية مخصصة لإنشائها. وهي تتألف مِن ثلاثة عناصر: البيان، والتنفيذ، والموارد.

في التمرين التالي، ستقوم بإنشاء مكون تعليمات برمجية مخصص للتعامل مع السيناريو الخاص بشركتك. ترغب شركتك فِي الحصول على بعض الحقول فِي النموذج الموجود فِي التطبيق تكون للقراءة فقط حتى يبدأ المستخدم يدوياً فِي إجراء تعديل على قيمة البيانات. لقد حدّد الفريق أن أيًا مِن عناصر التحكم المضمنة لن يعمل، لذا طلبوا منك إنشاء مكون تعليمات برمجية مخصص.

لحل هذا المطلب، ستقوم بإنشاء مكون مخصص للحقل قابل للتحرير والذي سيبدو مثل الصورة التالية. ستكون القيمة للقراءة فقط حتى يقوم المستخدم بتحديد التحرير.

لقطة شاشة لمكون التعليمات البرمجية المخصصة.

سوف يستمع هذا المكون إلى التغييرات القادمة مِن التطبيق المضيف ويسمح للمستخدم بإجراء التغييرات التي يتم دفعها بعد ذلك إلى التطبيق المضيف. ستساعدك الخطوات التالية فِي بناء هذا المكون.

تثبيت Power Platform CLI

لإعداد الكمبيوتر لإنشاء مكونات التعليمات البرمجية، اتبع الخطوات التالية:

  1. تثبيت Node.js (يأتي مع npm). نوصيك باستخدام إصدار LTS (دعم طويل الأجل) مثل الإصدار الذي يمكنك العثور عليه هنا. ستحتاج إلى التحقق من أنه ليس لديك Node/NPM مثبّت بالفعل. يمكنك فعل بذلك من خلال الانتقال إلى موجه الأوامر وكتابة ما يلي:

    // Launch a standard command prompt and type both of the following
    
    npm --version
    Node --version
    

    إذا تلقيتَ خطأ في تشغيل مثل هذه الأوامر، فستحتاج إلى تثبيت Node.js باستخدام الروابط الموجودة أعلاه.

    سيؤدي تثبيت node بشكل ناجح إلى إرجاع أرقام الإصدار في نافذة الأوامر عند إدخال الأوامر أعلاه كما هو موضح أدناه:

    // If installed properly you will see something like the output below. The version numbers may be slightly different based on the version installed.
    
    C:\npm --version
    10.5.0
    
    C:\Node --version
    v20.12.2
    
  2. ثبّت Visual Studio Code.

  3. ثبّت ملحق Power Platform Tools. تأكد من إكمال تثبيت Visual Studio Code قبل تثبيت Power Platform Tools.

    لن تتيح لك Power Platform Tools تشغيل أوامر CLI لـ Power Platform في موجه الأوامر خارج Visual Studio Code. نوصيك بتثبيت CLI MSI لـ PowerPlatform أيضاً.

    لتثبيت CLI على مستوى نظام التشغيل Windows، اتبع هذه الإرشادات. يمكنك تثبيت CLI وملحق Power Platform Tools في نفس الوقت.

إنشاء مشروع مكون جديد

قبل بدء إنشاء المكونات تحقق من أن المكونات المثبتة المذكورة أعلاه تعمل بشكل صحيح. ستعمل أوامر NPM وCLI من نافذة Terminal في Visual Studio Code. إذا كنت تواجه مشاكل في تشغيلها بشكل صحيح من داخل VS Code، فيمكنك اختيار تشغيل أوامر Terminal الواردة في الخطوات الموضحة أدناه في موجه الأوامر إذا كنت قد قمت بتثبيت CLI لـ Power Platform.

في Visual Studio Code، انتقل إلى Terminal > New Terminal (أو اضغط على CTRL+SHFT+`). في نافذة Terminal في VS Code، كرّر عبارات إصدار npm وNode. يمكنك المتابعة إلى إنشاء الحل، إذا أرجع كل شيء أرقام الإصدارات الصحيحة.

// Test installs from Steps 1-3 listed above

// This will verify NPM installation
C:\npm --version
10.5.0

// This will verify Node installation
C:\Node --version
v20.12.2

// This will launch Visual Studio Code from the command line.
C:\Code

الآن أنت مستعد لإنشاء مشروع مكون جديد، اتبع الخطوات التالية لبدء عملية الإنشاء:

قم بإنشاء دليل حيث ستبني المكون الخاص بك. في هذا النموذج، ستضع المكوّن في المسار C:\source\Editable-pcf. لإنشاء الدليل الخاص بك، ستستخدم Visual Studio Code. أو يمكنك بدلاً من ذلك إنشاء المجلدات باستخدام موجه الأوامر إذا كنت تواجه مشاكل في استخدام VS Code Terminal.

  1. ابدأ تشغيل Visual Studio Code.

  2. حدّد Terminal ثم حدّد New Terminal.

    لقطة شاشة تعرض اختيار الوحدة الطرفية الجديدة فِي Visual Studio Code.

  3. سيتم تعيين جلسة عمل Terminal افتراضياً في المجلد الأخير الذي استخدمته. وسيتم توضيح ذلك في منطقة موجه الأوامر TERMINAL على النحو المبيّن أدناه:

    //Note Your PS will not list exactly what is seen below, but will be specific to your starting path.
    
    PS C:\Users\Name\Folder
    

    قم بتغيير الدليل إلى الموقع الذي تريد إنشاء هذا الحل فيه. يمكنك استخدام أمر CD للانتقال إلى الموقع المناسب.

    ملاحظة

    يجب أن تدرك مدى أهمية المجلد الذي تنفذه NPM أو الأوامر الأخرى. احرص دائماً على وجودك في مجلد "المشاريع" قبل تنفيذ أوامر الإنشاء. قد يؤدي عدم القيام بذلك إلى إتلاف عملية الإنشاء والتسبب في حدوث مشكلات تمنع الحصول على أفضل النتائج.

    لإنشاء مجلد جديد في الموقع الافتراضي استخدم md (انشاء الدليل) كما هو موضح أدناه في نافذة VS Code Terminal.

    md source
    cd source
    

    سيؤدي ذلك إلى إنشاء دليل باسم المصدر ونقلك إلى هذا الدليل باستخدام الأمر cd (تغيير الدليل).

  4. من الدليل المصدر الذي تم إنشاؤه، أنشئ دليلاً باسم editable-pcf. سيكون هذا دليل PROJECT الخاص بك حيث سيتم تخزين جميع ملفات المشروع الخاصة بك. سنعمل أيضاً على تغيير الدليل إلى دليل المشروع الجديد.

    md editable-pcf
    cd editable-pcf
    

    لقطة شاشة تعرض الوحدة الطرفية مع أوامر لإنشاء الدليل وتغييره.

  5. قم بتهيئة مشروع المكون باستخدام Power Platform CLI بواسطة الأمر التالي:

    pac pcf init --namespace SampleNamespace --name EditablePCF --template field
    

    تظهر الصورة التالية مثالاً عن الإخراج الذي يجب أن تراه.

    تنبيه

    إذا لم يتم تشغيل الأمر PAC PCF INIT في نافذة طرفية في VS Code وقمت بتثبيت Power Platform CLI، فيمكنك اختيار تشغيل موجه الأوامر والقرص المضغوط إلى دليل editable-pcf. بمجرد وصولك إلى هناك، يمكنك إدخال الأمر في "موجه الأوامر" وسيعمل بشكل صحيح. يجب أن ترى نفس المخرجات المذكورة أعلاه.

  6. ثبّت أدوات بناء المشروع باستخدام الأمر npm install. قد تظهر بعض التحذيرات المعروضة؛ ولكن، يمكنك تجاهلها. تأكد من وجودك في دليل PROJECT الخاص بك قبل إصدار هذا الأمر.

    npm install
    

    تنبيه

    إذا لم يتم تثبيت npm في نافذة طرفية في VS Code وقمت بتثبيت Power Platform CLI، فيمكنك اختيار تشغيل موجه الأوامر والقرص المضغوط إلى دليل editable-pcf. بمجرد وصولك إلى هناك، يمكنك إدخال الأمر في "موجه الأوامر" وسيعمل بشكل صحيح.

    يمكنك التحقق من عمل كل شيء بشكل صحيح عن طريق تنفيذ أمر DIR في نافذة Terminal في VS Code أو في موجه الأوامر إذا اخترت الإنشاء خارج Visual Studio Code. يجب أن ترى سلسلة من الملفات والمجلدات في دليل editable-pcf. هذا هو المشروع الذي قمت بإنشائه في الخطوات أعلاه والذي سنقوم ببنائه باستخدام VS Code.

  7. قم بتشغيل الأمر أدناه لفتح المشروع في Visual Studio Code أو إذا كنت تستخدم موجه الأوامر في نافذة موجه الأوامر. يجب أن يؤدي هذا إلى تشغيل المشروع الذي أنشأته في VS Code.

    code -a .
    
  8. يجب أن تبدو محتويات المشروع مثل الصورة أدناه.

    لقطة شاشة تعرض ملفات المشروع.

تحديث بيان مكون التعليمات البرمجية

قم بتحديث ملف البيان ليمثل التحكم الخاص بك بدقة.

  1. قم بتوسيع المجلد EditablePCF وافتح الملف ControlManifest.Input.xml.

    لقطة شاشة توضح ملف XML لإدخال بيان التحكم.

  2. قم بتغيير الإصدار إلى 1.0.0 وdescription-key إلى تحرير اسم المشروع.

  3. حدّد موقع عقدة property.

  4. غيّر قيمة الاسم إلى الاسم وdisplay-name-key إلى الاسم‏‎ وdescription-key إلى اسم.

  5. حدّد موقع عقدة الموارد.

  6. قم بتضمين مرجع إلى CSS الملف المسمى editable-pcf.css الذي ستقوم بإنشائه في الخطوات التالية.

    <css path="css/EditablePCF.css" order="1" />
    

    لقطة شاشة توضح التغييرات التي تم إجراؤها على عقدة الموارد.

  7. احفظ التغييرات من خلال تحديد ملف ثم حفظ أو اضغط على CTRL+S لحفظ الملف.

إضافة تصميم إلى مكون التعليمات البرمجية‬

لإضافة تصميم إلى مكون التعليمات البرمجية‬، اتبع الخطوات الآتية:

  1. تأكد مِن تحديد الملف ControlManifest.Input.xml ثم حدّد مجلد جديد.

    لقطة شاشة تعرض زر إضافة مجلد جديد.

  2. قم بتسمية المجلد الجديد css.

  3. حدّد المجلد css الذي أنشأته وحدّد ملف جديد.

  4. قم بتسمية الملف الجديد EditablePCF.css (أو أيًا كان الاسم الذي أطلقتَه على ملف css في الخطوة 6 أعلاه).

  5. افتح ملف EditablePCF.css الجديد الذي قمت بإنشائه، والصق قصاصة CSS البرمجية التالية. هذا هو الاسم المرجعي للمورد الذي استخدمته سابقاً عندما أضفت كود مسار css إلى ملف البيان.

    .SampleNamespace\.HelloPCF {
          font-size: 1.5em;
        }
    
  6. يجب أن يبدو محتوى ملف CSS الآن مثل الصورة أدناه.

    لقطة شاشة تعرض محتوى ملف CSS.

  7. حدّد ملف وحدّد حفظ أو اضغط على CTRL+S لحفظ الملف.

إنشاء مكون التعليمات البرمجية

قبل أن تتمكن مِن تطبيق منطق المكون تحتاج إلى تشغيل بنية على المكون. يؤدي ذلك إلى التأكد مِن إنشاء أنواع TypeScript الصحيحة لمطابقة الخصائص فِي مستند ControlManifest.xml.

ارجع إلى المحطة في VS Code وقم ببناء مشروعك باستخدام الأمر التالي. إذا واجهتك مشاكل في استخدام Terminal في Visual Studio Code لأي سبب من الأسباب، فيمكنك الانتقال إلى المجلد الخاص بك باستخدام موجه الأوامر وتشغيل الأمر من هناك.

تنبيه

تأكد من وجودك في مجلد PROJECT في المحطة لديك قبل إصدار هذا الأمر.

npm run build

يتم تجميع المكون فِي الدليل out/controls/EditablePCF. تشمل آثار البناء ما يلي:

  • مجلد css

  • bundle.js - كود مصدر المكون المجمع

  • ControlManifest.xml - ملف البيان الفعلي الخاص بالمكون الذي يتم تحميله إلى مؤسسة Microsoft Dataverse

    لقطة شاشة تعرض محتوى مجلد الإخراج.

تحذير

الخطأ الأكثر شيوعاً الذي عادةً ما يرد هنا هو خطأ مطبعي في اسم ملف CSS الذي أنشأته سابقاً. إذا حدث ذلك، فقم ببساطة بإعادة تسمية الملفات وفقًا لذلك وإعادة تشغيل أمر npm run build حتى يتم الانتهاء منه بدون أخطاء. تحقق من قسم "المورد" في ملف COntrolManifest.Input.xml الخاص بك مقابل الملف الذي تم إنشاؤه في مجلد CSS. يجب أن تتطابق بنسبة 100%.

تنفيذ منطق مكون التعليمات البرمجية

لتنفيذ منطق مكون التعليمات البرمجية الخاص بك، اتبع هذه الخطوات بمجرد اكتمال عملية الإنشاء من الخطوات السابقة. في Visual Studio Code، ابحث في EXPLORER عن ملف باسم index.ts. هنا سنبدأ بكتابة الكود البرمجي للمكون الخاص بنا.

  1. افتح الملف index.ts في Visual Studio Code.

  2. فوق الأسلوب constructor، أدخل المتغيرات الخاصة التالية:

    // The PCF context object\
    private context: ComponentFramework.Context<IInputs>;
    // The wrapper div element for the component\
    private container: HTMLDivElement;
    // The callback function to call whenever your code has made a change to a bound or output property\
    private notifyOutputChanged: () => void;
    // Flag to track if the component is in edit mode or not\
    private isEditMode: boolean;
    // Tracking variable for the name property\
    private name: string | null;
    
  3. حدّد موقع الأسلوب public init واستبدله بالأسلوب أدناه.

    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
    
        // Track all the things
        this.context = context;
        this.notifyOutputChanged = notifyOutputChanged;
        this.container = container;
        this.isEditMode = false;
    
        // Create the span element to hold the project name
        const message = document.createElement("span");
        message.innerText = `Project name ${this.isEditMode ? "" :context.parameters.Name.raw}`;
    
        // Create the textbox to edit the name
        const text = document.createElement("input");
        text.type = "text";
        text.style.display = this.isEditMode ? "block" : "none";
    
        if (context.parameters.Name.raw) {
            text.value = context.parameters.Name.raw;
            // Wrap the two above elements in a div to box out the content
            const messageContainer = document.createElement("div");
            messageContainer.appendChild(message);
            messageContainer.appendChild(text);
    
            // Create the button element to switch between edit and read modes
    
            const button = document.createElement("button");
            button.textContent = this.isEditMode ? "Save" : "Edit";
            button.addEventListener("click", () => { this.buttonClick(); });
    
            // Add the message container and button to the overall control container
            this.container.appendChild(messageContainer);
            this.container.appendChild(button);
        }
    
    }
    

    تحذير

    قد تلاحظ أن EventListener الخاص بـ buttonClick تحته خط باللون الأحمر. لا تقلق، سنقوم بإنشاء طريقة لهذا الحدث أدناه. إذا رأيتَ أقساماً أخرى باللون الأحمر، فستحتاج إلى التحقق من أن كل شيء تم نسخه أو إدخاله بشكل صحيح.

  4. أضف أسلوب معالج تحديد الزر. أضف الأسلوب التالي أسفل الأسلوب init‎.

    public buttonClick() {
        // Get our controls via DOM queries
        const text = this.container.querySelector("input")!;
        const message = this.container.querySelector("span")!;
        const button = this.container.querySelector("button")!;
    
        // If not in edit mode, copy the current name value to the textbox
        if (!this.isEditMode) {
            text.value = this.name ?? "";
        } 
        else if (text.value != this.name) {
            // if in edit mode, copy the textbox value to name and call the notify callback
            this.name = text.value;
            this.notifyOutputChanged();
        }
    
        // flip the mode flag
        this.isEditMode = !this.isEditMode;
    
        // Set up the new output based on changes
        message.innerText = `Project name ${this.isEditMode ? "" : this.name}`;
        text.style.display = this.isEditMode ? "inline" : "none";
        text.value = this.name ?? "";
        button.textContent = this.isEditMode ? "Save" : "Edit";
    }
    
  5. حدّد موقع الأسلوب updateView‎ واستبدله بالأسلوب أدناه.

    public updateView(context: ComponentFramework.Context<IInputs>): void {
    
    // Checks for updates coming in from outside
    
    this.name = context.parameters.Name.raw;
    const message = this.container.querySelector("span")!;
    message.innerText = `Project name ${this.name}`;
    }
    
  6. حدّد موقع الأسلوب getOutputs واستبدله بالأسلوب أدناه.

    public getOutputs(): IOutputs {
    return {
    // If our name variable is null, return undefined instead
    Name: this.name ?? undefined
    };
    }
    
  7. حدّد موقع الأسلوب destroy واستبدله بالأسلوب أدناه.

    public destroy() {
    // Remove the event listener we created in init
    this.container.querySelector("button")!.removeEventListener("click", this.buttonClick);
    }
    
  8. يجب أن يبدو كود Index.ts النهائي الآن مثل الكود الموضح أدناه:

    import { IInputs, IOutputs } from "./generated/ManifestTypes";
    
    export class EditablePCF implements ComponentFramework.StandardControl<IInputs, IOutputs> {
    
        /**
        * Empty constructor.
        */
    
        // The PCF context object\
        private context: ComponentFramework.Context<IInputs>;
        // The wrapper div element for the component\
        private container: HTMLDivElement;
        // The callback function to call whenever your code has made a change to a bound or output property\
        private notifyOutputChanged: () => void;
        // Flag to track if the component is in edit mode or not\
        private isEditMode: boolean;
        // Tracking variable for the name property\
        private name: string | null;
    
        constructor()
        {
    
        }
    
        /**
        * Used to initialize the control instance. Controls can kick off remote server calls and other initialization actions here.
        * Data-set values are not initialized here, use updateView.
        * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
        * @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
        * @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
        * @param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
        */
        public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
    
            // Track all the things
            this.context = context;
            this.notifyOutputChanged = notifyOutputChanged;
            this.container = container;
            this.isEditMode = false;
    
            // Create the span element to hold the project name
    
            const message = document.createElement("span");
            message.innerText = `Project name ${this.isEditMode ? "" :context.parameters.Name.raw}`;
    
            // Create the textbox to edit the name
            const text = document.createElement("input");
            text.type = "text";
            text.style.display = this.isEditMode ? "block" : "none";
    
            if (context.parameters.Name.raw) {
                text.value = context.parameters.Name.raw;
                // Wrap the two above elements in a div to box out the content
                const messageContainer = document.createElement("div");
                messageContainer.appendChild(message);
                messageContainer.appendChild(text);
    
                // Create the button element to switch between edit and read modes
    
                const button = document.createElement("button");
                button.textContent = this.isEditMode ? "Save" : "Edit";
                button.addEventListener("click", () => { this.buttonClick(); });
    
                // Add the message container and button to the overall control container
                this.container.appendChild(messageContainer);
                this.container.appendChild(button);
            }
    
        }
    
        public buttonClick() {
            // Get our controls via DOM queries
    
            const text = this.container.querySelector("input")!;
            const message = this.container.querySelector("span")!;
            const button = this.container.querySelector("button")!;
    
            // If not in edit mode, copy the current name value to the textbox
    
            if (!this.isEditMode) {
                text.value = this.name ?? "";
            } 
            else if (text.value != this.name) {
    
                // if in edit mode, copy the textbox value to name and call the notify callback
                this.name = text.value;
                this.notifyOutputChanged();
            }
    
            // flip the mode flag
            this.isEditMode = !this.isEditMode;
    
            // Set up the new output based on changes
            message.innerText = `Project name ${this.isEditMode ? "" : this.name}`;
            text.style.display = this.isEditMode ? "inline" : "none";
            text.value = this.name ?? "";
            button.textContent = this.isEditMode ? "Save" : "Edit";
        }
    
        /**
        * Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
        * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
        */
        public updateView(context: ComponentFramework.Context<IInputs>): void {
    
            // Checks for updates coming in from outside
            this.name = context.parameters.Name.raw;
            const message = this.container.querySelector("span")!;
            message.innerText = `Project name ${this.name}`;
        }
    
        /**
        * It is called by the framework prior to a control receiving new data.
        * @returns an object based on nomenclature defined in manifest, expecting object[s] for property marked as "bound" or "output"
        */
        public getOutputs(): IOutputs {
            return {
            // If our name variable is null, return undefined instead
            Name: this.name ?? undefined
            };
        }
    
        /**
        * Called when the control is to be removed from the DOM tree. Controls should use this call for cleanup.
        * i.e. cancelling any pending remote calls, removing listeners, etc.
        */
        public destroy() {
            // Remove the event listener we created in init
            this.container.querySelector("button")!.removeEventListener("click", this.buttonClick);
        }
    }
    

إعادة إنشاء مكون التعليمات البرمجية وتشغيله

لإعادة إنشاء مكون التعليمات البرمجية وتشغيله، اتبع الخطوات التالية:

  1. الآن وبعد أن تم تطبيق منطق المكون، عد إلى الوحدة الطرفية لإعادة إنشائها باستخدام الأمر أدناه. يمكنك تشغيل هذا مباشرةً في VS Code أو من خلال موجه الأوامر طالما أنك تنتقل إلى مجلد editable-pcf أولاً.

    npm run build
    
  2. من المفترض أن تنجح عملية البناء.

    لقطة شاشة توضح نتيجة البناء.

  3. قم بتشغيل المكون الخاص بك فِي أداة اختبار Node عن طريق تشغيل الأمر أدناه. إذا لم تكن قد فعلت ذلك من قبل، فيجب أن تقوم بتشغيل المتصفح مع عرض المكون الذي تم إنشاؤه حديثاً.

    npm start
    

    ملاحظة

    يمكنك أيضاً تمكين وضع المراقبة لضمان إجراء أي تغييرات في الأصول التالية بشكل تلقائي من دون الحاجة إلى إعادة تشغيل مفعّل الاختبار باستخدام الأمر npm start watch.

    • ملف Index.ts.

    • ملف ControlManifest.Input.xml

    • المكتبات المستوردة فِي ملف Index.ts

    • جميع الموارد المدرجة فِي ملف البيان

  4. يجب أن تقوم نافذة متصفح جديدة بتحميل أداة الاختبار. (يجب أن تفتح النافذة تلقائيًا، ولكن يمكنك أيضًا الرجوع إلى العنوان كما موجود فِي نافذة الأوامر).

  5. حدّد تحرير.

    لقطة شاشة توضح زر التحرير فِي أداة الاختبار.

  6. أدخل Project One وحدّد حفظ.

  7. يُمكنك تغيير حجم الحاوية.

  8. يجب أن تبدو أداة الاختبار الآن كما فِي الصورة أدناه.

    لقطة شاشة توضح التحكم داخل أداة الاختبار.

  9. أغلق نافذة متصفح مفعّل الاختبار.

  10. ارجع إلى المحطة أو موجه الأوامر (إذا لم تكن تستخدم VS Code Terminal) وقم بإيقاف المراقب بالضغط مع الاستمرار على [CONTROL] + C.

  11. اكتب Y ثم ‏[ENTER].