كيفية إضافة حقل مخصص لموضوع أساسي للغاية

أحاول فهم كيفية إضافة حقل مخصص إلى المواضيع، وأعمل على مثال بسيط جدًا. الهدف: إضافة حقل مخصص يُسمى “sample_field” إلى كل موضوع يتم إنشاؤه، بقيمة نصية بسيطة.

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

لذا لم أصل بعد إلى النتيجة المرجوة—ملف plugin.rb الخاص بي يفتقر إلى شيء ما (أعتقد)، ولم أستطع بعد معرفة كيفية ربط القيمة النصية بالحقل المخصص في لحظة إنشاء الموضوع.

ما الذي أحتاجه لجعل هذا يعمل؟

أي مساعدة مُقدَّرة. شكرًا!

إليك ما لدي حتى الآن:

plugin.rb:
//إنشاء الحقل المخصص:

  after_initialize do
     Topic.register_custom_field_type('sample_field', :string)
     add_to_serializer(:topic_view, :custom_fields) { object.custom_fields } //إذا أردت عرض الحقل المخصص على جانب العميل
  end

assets/javascripts/initializers/topic-custom-field.js.es6:
//تهيئة كائن الحقول المخصصة، وجعل من الممكن إرساله إلى الخادم:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
  name: 'topic-custom-field',
  initialize() {
    withPluginApi('0.8.31', api => {
      api.modifyClass('model:topic', {
        custom_fields: {},
        asJSON() {
          return Object.assign(this._super(), {
            custom_fields: this.custom_fields
          });
        }
      })
    })
  }
}

إذن، كيف يمكنني إضافة قيمة الحقل المخصص إلى الموضوع في لحظة حفظه؟

أعتقد أن الإجراء الرئيسي “save” للموضوع يحدث هنا في قاعدة الكود:

app/templates/composer.hbs:

  <div class="save-or-cancel">
            {{#unless model.viewFullscreen}}
              {{composer-save-button action=(action "save")
                                     icon=saveIcon
                                     label=saveLabel
                                     disableSubmit=disableSubmit}}
...

كيف يمكنني فعل شيء ما (في هذه الحالة، إضافة قيمة إلى الحقل المخصص) عند حدوث إجراء “save” هذا؟

لقد حاولت إنشاء ملف JS تحت initializers، حيث يمكنني فعل شيء مثل:

api.modifyClass('component:composer-save-button', {
   actions: {
       topic.set('custom_fields.sample_field', 'here's a value for the sample_field')
   }
}

لكنني أحتاج إلى ربط ذلك “topic.set” بإجراء “save” في composer.hbs، ولا أعرف كيف أفعل ذلك.


وإذا كانت هناك طريقة أبسط للقيام بذلك، فسأكون سعيدًا بسماعها!

إعجابَين (2)

لا أعتقد أنني على علم بمثال مثالي، لكن قد أحاول تطوير واحد في وقت ما.

قد ترغب في الاطلاع على بعض الإضافات الأخرى للبحث عن أمثلة. لست متأكدًا منها في الوقت الحالي. هناك مستودع Discourse يُسمى شيئًا مثل all-the-plugins، وغالبًا ما أستخدم الأمر grep فيه للبحث عن أشياء.

أراهن أن إضافة التفاعلات التي تُختبر حاليًا هنا هي مثال جيد. راجع اللافتة وانظر إليها.

إعجابَين (2)

نعم، راجع دائمًا الإضافات الموجودة.

إليك مثال:

الذي يعتمد على هذا المكوّن والوحدة:

إعجابَين (2)

شكرًا لكم جميعًا، سألقِ نظرة على هذه. لقد ذكرتُ في المنشور الأصلي أنني قد راجعتُ العديد من الأمثلة الأخرى مسبقًا. هل لديكم أي ملاحظات حول الكود الذي قدمته؟

إعجابَين (2)

عذراً. لم ألاحظ أي مشاكل واضحة (من وجهة نظري). وعلى الرغم من أنني أتحسن في تطوير الإضافات، إلا أنني أشعر غالباً أنني أعرف ما يكفي لأكون خطيراً.

إعجابَين (2)

قد يكون الأمر معقدًا أكثر من اللازم إذا كنت مستعدًا لاتباع “الطريقة التي يعمل بها Discourse”، وهي: تعديل البيانات داخل منطقة “Topic Meta”، ثم فقط عند النقر على أيقونة القلم.

كل ما تحتاجه هو عرض مربع إدخال متصل بشكل صحيح والتأكد من تسلسل القيمة إلى “Topic View”.

سيقوم كود PostRevisor بالعمل السحري لتحديث الحقل المخصص.

راجع مثال إضافة Locations. حتى ذلك المثال أكثر مما تحتاجه.

تأكد من تشغيل إضافة Locations أيضًا لترى كيف يبدو الأمر.

إعجابَين (2)

إليك مثال آخر، مع سيناريو إدخال مختلف قليلاً، لكنه لا يزال يستفيد من نفس الآليات والخطافات:

https://github.com/paviliondev/discourse-topic-previews/blob/master/assets/javascripts/discourse/connectors/edit-topic/select-thumbnail-connector.hbs

4 إعجابات

شكرًا لك. أنا لستُ على دراية بـ PostRevisor. سأبحث في ذلك الآن.

غير متأكد مما تقصده بمنطقة موضوع Meta. هل تقصد ملفًا معينًا؟ (من حيث واجهة المستخدم، أعرف أن هناك محررًا لإنشاء المواضيع يحتوي على d-editor، ثم هناك عرض الموضوع نفسه. غير متأكد أين تقع منطقة “Meta” هناك.)

إعجابَين (2)

أعتبر معلومات الفئة والوسم بيانات وصفية.

إعجابَين (2)

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

ألاحظ أنه في الإضافات التي تحتوي على حقول مخصصة للموضوع، هناك استخدام شائع في ملف plugin.rb لـ PostRevisor (مثل PostRevisor.track_topic_field) و DiscourseEvent.on(:topic_created) do |topic|.... قد يسمح ذلك بتعيين الحقل المخصص دون الحاجة إلى النقر على زر—مثل تعيين الحقل المخصص عند إنشاء الموضوع. لكنني لم أتمكن من فهم ذلك بعد.

[تعديل: إذا كان أي شخص يرغب في اقتراح كود لملف plugin.rb لإضافة قيمة الحقل المخصص إلى الموضوع في لحظة إنشائه (بدلاً من وجود زر منفصل يحتاج إلى النقر عليه)، يرجى فعل ذلك! :)]

إذن، إليك مثالًا أساسيًا يعمل دون الحاجة إلى تلك الأمور المتقدمة:

plugin.rb

Topic.register_custom_field_type('sample_field', :string)
add_to_class(:topic, :sample_field) { self.custom_fields['sample_field'] } ##ربما غير ضروري. استنادًا إلى السطر 83 من ملف plugin.rb الخاص بإضافة discourse-locations
	
add_to_serializer(:topic_view, :sample_field, false) { object.topic.sample_field } ##ربما ضروري فقط إذا كنت ترغب في عرض نتيجة الحقل المخصص للمستخدم

connector/[add-button].hbs

//مثال هنا: الموصل هو topic-above-post-stream، والذي يمرر نموذجًا (موضوع) في منفذ الإضافة

<button {{action "setThatTopic" model}}>اضغط هنا</button>

connector/[add-button].js.es6

import Topic from 'discourse/models/topic';  //ربما غير ضروري

export default {			
    actions: {
       setThatTopic(model){
           model.set('custom_fields.sample_field', 'newValue123')
           console.log('اختبار وجود الحقل المخصص = ' + JSON.stringify(model.custom_fields))
        }
     }
}

assets/javascripts/initializers/topic-custom-field.js.es6

//ربما غير ضروري. لكن الفكرة هي تهيئة كائن الحقول المخصصة وجعله قابلاً للإرسال إلى الخادم:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
    name: 'topic-custom-field',
     initialize() {
	   withPluginApi('0.8.31', api => {
		 api.modifyClass('model:topic', {
			custom_fields: {},
			asJSON() {
			    return Object.assign(this._super(), {
				custom_fields: this.custom_fields
			   });
			}
	     })
	   })
    }
}
6 إعجابات

لقد نشرت للتو “إضافة تعليمية” توضح كيفية القيام بذلك

9 إعجابات

شكرًا لك، @angus. هذا مفيد للغاية، وهو بالضبط نوع الشيء الذي يجعل البرمجة مع discourse أسهل. شخصيًا، أحب أن أرى هذا النوع من الموارد — مثال برمجي مباشر وبسيط يوضح تنفيذ ميزة واحدة في كل مرة — لمجموعة متنوعة من المهام مع discourse. على سبيل المثال، الحقول المخصصة للفئات والمجموعات أيضًا. هذا النوع من الموارد يوفر الكثير من الوقت.

3 إعجابات