إضافة فيديو خلفية لملفات تعريف مستخدمين معينة؟

إذا كنت ترغب في إضافة محتوى إلى صفحة محددة، فإن أفضل خيار لديك هو “plugin-outlet”. باختصار، plugin-outlets هي مساحات محجوزة في قوالب Discourse يمكنك استخدامها لإضافة محتوى جديد.

أول ما ستحتاج إلى اكتشافه هو ما إذا كان هناك plugin-outlet موجود في الصفحة التي تستهدفها. هناك مكون موضوع يمكنك تثبيته لمساعدتك في ذلك.

(deprecated) Plugin outlet locations theme component

بمجرد تثبيت هذا المكون، قم بتفعيله، ثم انتقل إلى الصفحة التي تستهدفها وتحقق مما لديك للعمل به. في حالتك، يوجد مثل هذا plugin-outlet (مُظلل باللون الأخضر)

إذن، الذي نريده هو above-user-profile.

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

على أي حال، كما قلت، إنه موجود بالفعل في هذه الحالة. لذا، دعنا نرى كيف يمكنك إضافة علامات HTML إليه. لن تحتاج إلى المكون المذكور أعلاه لبقية هذا الدليل، لذا يمكنك تعطيله الآن لأنك حصلت بالفعل على اسم plugin outlet.

كل ما عليك فعله هو إضافة شيء مثل هذا في تبويب الرأس (header) في موضوعك.

<script type="text/x-handlebars" data-template-name="/connectors/OUTLET_NAME/SOME_NAME">
  Your markup goes here...
</script>

يجب عليك تغيير OUTLET_NAME إلى اسم outlet الذي تريد استهدافه. ثم غيّر SOME_NAME إلى الاسم الذي تريد إعطاؤه لهذا التخصيص. يمكن أن يكون الاسم أي شيء، لكن حاول أن تكون وصفيًا إذا أمكن. إنها ممارسة جيدة. إذن، ننتهي بهذا.

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
  Your markup goes here...
  <h1>مرحبًا بالعالم!!</h1>
</script>

لنجرب ذلك ونرى ما يحدث… تذكر، المقطع أعلاه يذهب في تبويب common > header في موضوعك.

و…

حتى الآن كل شيء على ما يرام، لكن دعنا نغوص أعمق.

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

دعنا نجد البيانات. أتذكر عندما قلت إن plugin-outlets هي مساحات محجوزة؟ حسنًا، ما فائدة وجودها بدون سياق؟ لهذا السبب يمرر Discourse الأجزاء ذات الصلة من السياق إلى كل plugin outlet… لكن أولاً، دعنا نرجع خطوة للوراء. عندما تضيف هذا

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
  Your markup goes here, like...
  <h1>مرحبًا بالعالم!!</h1>
</script>

يبدو مثل HTML - وعلامات السكربت كذلك - لكن ما بداخلها يُعامل ككود Handlebars.

هذا يعني أنه يمكنك فعل شيء مثل هذا بدلاً من ذلك:

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
  {{log this}}
</script>

ثم تحقق من وحدة تحكم المتصفح. سترى هذا كل مرة يتم فيها عرض outlet؛ أي عندما تكون على صفحة مستخدم.

الآن، هل أي من هذه الأشياء مفيد؟ نعم… لكن ليس في الوقت الحالي. سنعود إلى هذا لاحقًا. دعنا نرجع خطوة أخرى للوراء ونرى كيف يمرر Discourse السياق إلى outlet. إذا بحثت عن اسم outlet على Github - أو محليًا - فستحصل على هذا.

Repository search results · GitHub

دعنا نفتح ذلك الملف. أول شيء تراه هو هذا السطر:

انظر إلى الجزء الأخير من ذلك السطر:

args=(hash model=model)

سترى أن Discourse يمرر model كحجة إلى outlet. ولأغراضنا ولتبسيط الأمور، model = data.

إذن، إحدى الحجج لـ outlet لدينا هي model، وهذا هو المكان الذي ستكون فيه البيانات التي نريدها. لذا، دعنا نعود إلى مقطعنا.

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
  {{log this}}
</script>

ودعنا نغيره إلى هذا بدلاً من ذلك:

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
-  {{log this}}
+  {{log args}}
</script>

الآن نحصل على هذا في وحدة التحكم.

يمكنك تصفح تلك البيانات ورؤية ما إذا كانت تحتوي على ما تحتاجه. يجب أن تكون كذلك لأنها تحتوي على جميع البيانات حول المستخدم المستخدمة في عناصر أخرى على تلك الصفحة. إنها “النموذج” لصفحة المستخدم لتلك المستخدم المحدد.

إحدى الخصائص المتاحة هناك هي… دق الطبل :drum: … المجموعات التي ينتمي إليها المستخدم.

إذن، إذا قمت بـ:

{{log args.model.groups}}

ستحصل على جميع المجموعات التي ينتمي إليها المستخدم في وحدة التحكم.

حسنًا، الآن لدينا البيانات التي نحتاجها، لذا كل ما تبقى هو إضافة شرط (شروط) بناءً على ذلك.

قد تميل إلى التفكير في أننا يمكننا القيام بذلك في نفس المقطع، لكن، للأسف، لا يمكننا ذلك. Handlebars هي لغة قوالب. لديها دعم جدًا بسيط للمنطق - لا شيء أبعد من شروط صحيحة/خاطئة بسيطة وحلقات. لا يمكنك إجراء مقارنات وأشياء أخرى من هذا القبيل.

إذن أين يمكنك بالضبط القيام بذلك؟ في فئة connector، يبدو ذلك رائعًا… أعرف.

باختصار، فئة connector هي في الأساس جزء من جافا سكريبت متصل بـ outlet. الأمر أكثر دقة من ذلك، لكن هذا كل ما تحتاج حقًا إلى معرفته الآن.

لذا، دعنا ننشئ واحدة. نفعل ذلك كما يلي:

<script type="text/discourse-plugin" version="0.8">
api.registerConnectorClass('OUTLET_NAME', 'SOME_NAME', {

});
</script>

يجب أن يكون OUTLET_NAME و SOME_NAME هنا نفس الأسماء التي استخدمناها أعلاه. لذا دعنا نغيرها:

<script type="text/discourse-plugin" version="0.8">
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {

});
</script>

يذهب هذا المقطع أيضًا في تبويب common > header في موضوعك. لذا يجب أن يكون لديك الآن شيء يبدو مثل هذا:

<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
  {{log args.model.groups}}
</script>

<script type="text/discourse-plugin" version="0.8">
  api.registerConnectorClass('above-user-profile', 'add-profile-videos', {

  });
</script>

داخل فئة connector لدينا، يمكننا القيام ببعض العمل… لكن… يجب أن نكون حذرين من أنه ليس مثل أي ملف جافا سكريبت. ولعدم وجود وصف أفضل… اعتبره مكون Ember على نظام غذائي. توسيع هذا خارج نطاق هذا الدليل، لذا دعنا نتابع.

هناك أربع طرق مربوطة بها افتراضيًا:

تسمح لك actions بتعريف إجراءات مثل هذا:

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  actions: {
    myAction() {
      // do something
    }
  }
});

يمكنك بعد ذلك استدعاء هذا الإجراء من داخل outlet، مثل عند الضغط على زر. لن نحتاج إلى هذا هنا، لذا دعنا نتابع.

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  shouldRender(args, component) {
    // return true or false here
  }
});

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

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  setupComponent(args, component) {
    // do something
  }
});

هذا هو الذي نريد التركيز عليه. أي شروط جافا سكريبت أو متغيرات تريد تعيينها تذهب هنا. قبل أن نغوص أعمق في ذلك، دعنا نغطي الطريقة الأخيرة أولاً من أجل الاكتمال:

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  teardownComponent(args, component) {
    // do something
  }
});

هذا يعمل عندما سيتم إزالة outlet. لذا، يسمح لك بأي تنظيف مطلوب، مثل إزالة مستمعي الأحداث وما إلى ذلك.

حسنًا، دعنا نعود إلى setupComponent:

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  setupComponent(args, component) {
    // do something
  }
});

يمكنك رؤية أن هناك شيئين تم تمريرهما إليه. أولاً، هناك args ثم هناك component.

args هنا هي نفس الأشياء التي نظرنا إليها سابقًا. إنها بيانات السياق التي مررها Discourse إلى outlet. لذا، إذا قمت بـ:

api.registerConnectorClass("above-user-profile", "add-profile-videos", {
  setupComponent(args, component) {
    console.log(args.model.groups);
  }
});

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

  api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
    setupComponent(args, component) {
      const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
      const showVideo = inGroup.length ? true : false;

      console.log(showVideo);
    }
  });

إذا جربت هذا على صفحة ملف شخصي ينتمي إلى مستخدم في مجموعة staff، فسيتم طباعة true في وحدة التحكم. لذا، الآن كل ما تبقى لنا هو تمرير ذلك إلى قالب outlet. إليك كيف يمكنك فعل ذلك.

component الممرر إلى setupComponent هنا مشترك بين connector و outlet. يمكنك تمرير أشياء إلى outlet عن طريق تعيينها كخصائص على component كما يلي:

  const TARGET_GROUP = "staff"

  api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
    setupComponent(args, component) {
      const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
      const showVideo = inGroup.length ? true : false;
-     console.log(showVideo);
+     component.setProperties({showVideo})
    }
  });

الآن، إذا عدنا إلى القالب وفعلنا شيئًا مثل:

{{log showVideo}}

سيتم طباعة نفس النتيجة. لذا نضع الآن ذلك في شرط Handlebars ونضيف علامتك HTML بداخله كما يلي:

<script
  type="text/x-handlebars"
  data-template-name="/connectors/above-user-profile/add-profile-videos"
>
  {{#if showVideo}}
    <video playsinline autoplay muted loop id="myVideo" poster="[INSERT LINK]">
      <source src="[INSERT LINK]" type="video/webm">
      <source src="[INSERT LINK]" type="video/mp4">
    </video>
  {{/if}}
</script>

ثم تحقق من صفحة ملف شخصي لمستخدم staff. سترى أنه يقوم بتحميل الفيديو.

بمجرد التنقل بعيدًا عن ملف عضو staff، سيختفي الفيديو. لن يظهر الفيديو على ملفات المستخدمين الذين لا ينتمون إلى مجموعة staff.

إذن، دعنا نجمع كل هذا معًا. هذا هو نفس الشيء من أعلاه.

إليك CSS الذي استخدمته. تبويب common > css:

#myVideo {
  position: fixed;
  top: var(--header-offset);
  min-height: 100vh;
  left: 0;
  z-index: -1;
}

.user-content {
  background: none;
}

.user-main {
  padding: 0.5em;
  background: rgba(var(--secondary-rgb), 0.8);
}

// إذا كنت تريد ذلك على الجوال أيضًا
.mobile-view {
  body[class*="user-"] {
    background: none;
    .user-main,
    .user-content {
      padding: 0.5em;
      background: rgba(var(--secondary-rgb), 0.8);
    }
  }
}

HTML / جافا سكريبت / Handlebars. هذا يذهب في تبويب common > header في موضوعك:

<script
  type="text/x-handlebars"
  data-template-name="/connectors/above-user-profile/add-profile-videos"
>
  {{#if showVideo}}
    <video playsinline autoplay muted loop id="myVideo" poster="[INSERT LINK]">
      <source src="[INSERT LINK]" type="video/webm">
      <source src="[INSERT LINK]" type="video/mp4">
    </video>
  {{/if}}
</script>

<script type="text/discourse-plugin" version="0.8">
  const TARGET_GROUP = "staff"

  api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
    setupComponent(args, component) {
      const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
      const showVideo = inGroup.length ? true : false;
      component.setProperties({showVideo})
    }
  });
</script>

غيّر TARGET_GROUP إلى اسم المجموعة التي تريد استهدافها وأضف سمات src لمقاطع الفيديو الخاصة بك.

كان هذا المنشور طويلًا بعض الشيء… لا تثبط عزيمتك بذلك. بمجرد استيعاب المفهوم، يمكن القيام بكل ما فعلناه أعلاه في أقل من 3-5 دقائق.

الشيء الجميل هنا هو أن كل الأشياء التي تحدثنا عنها متشابهة تقريبًا لأي plugin outlet. الشيء الوحيد الذي يتغير هو الاسم. لذا، ينطبق هذا على أي تعديلات plugin-outlet تريد القيام بها في المستقبل.

  1. ابحث عن اسم outlet
  2. احصل على البيانات
  3. معالج البيانات في connector
  4. مرر الخصائص مرة أخرى إلى القالب