Adnane Kadri

الأعضاء
  • المساهمات

    80
  • تاريخ الانضمام

  • تاريخ آخر زيارة

السُّمعة بالموقع

65 Excellent

المعلومات الشخصية

2 متابعين

  1. غرض تمرير بيانات في المسار هو لجعل الصفحة تظهر بشكل ديناميكي غير ثابت , ولفعل هذا في مكتبة gatspy ستحتاج الواجهة createPage لبناء أي صفحات ديناميكية و متغيرة (مثل صفحات البروفايل أو صفحة المنتج أو المقالة و غيرها) , في حين أن كل الصفحات الثابتة تبنى و تصدر بطريقة عادية بداخل src/pages . مثال عملي : بداخل ملف gatsby-node.js نقوم بتصدير الثابت createPages على هذا النحو : export const createPages = ({ actions }) => { const { createPage } = actions; createPage({ // تعريف المسار path: '/users/YOURID', // تعريف المكون المعاد في المسار component: YourRelatedComponent, // إرسال بيانات مخصصة للمكون context: { userID: 'YOURID', }, }); }; ثم يمكنك الوصول للبيانات الممررة بشكل عادي . إقرأ أكثر عن إنشاء و تعديل الصفحات في Gatspy هنا.
  2. يبدو أن المشكلة في الوصول إلى الـ loader بداخل مجلد الـ node_modules . تأكد أن تقوم بإعادة تثبيت url-loader عن طريق الأمر : npm install url-loader --save-dev ثم قم بإعادة البناء . و أيضا , قم بالتأكد أنك تقوم بتمرير اللاحقة loader- لكل الـ loaders المعنية على هذا النحو : loaders: [ { test: /\.css$/, loader: "style-loader!css-loader" }, ] و ذلك عوضا عن : loaders: [ { test: /\.css$/, loader: "style!css" }, ] هذا سيقوم بتجنب مشكلة إعتبار style أو css مثلا (دون لاحقة) كالـ module المعني بالعملية في حين أن القائم بالعملية هي الموديلات css-loader و url-loader و هكذا .
  3. يظهر من الصورة أنك تقومين بفتح مشروع الـ webpack عن طريق ملف الـ index بداخل مجلد dist . و هذا في الغالب سيؤدي بكل مسارات الملفات من الشكل main.css/ التي قد قمت بتضمينها تظهر على هذا النحو بعد البناء : file:///main.css و بالتالي فهي غير قابلة للوصول من الأساس و لو قمت بفتح الـ console ستجدين خطأ يخبرك أن الملفات غير موجودة . فالحل هو فتح المشروع عن طريق طباعة الأمر : npm run serve الذي سيقوم بدوره بطباعة التالي : Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from /path/to/some/path/project/dist wait until bundle finished: / Compiled successfully. بعد البناء بنجاح يمكنك التصفح إلى المسار الموصوف على هذا النحو : http://localhost:9000/ و سيتم إظهار كل الملفات شاملة ملفات التنسيق و السكربتات بشكل صحيح . ملاحظات : في حالة ما لم يعمل الأمر بشكل صحيح و قمت بمواجهة خطأ من هذا النوع : missing script: serve فتأكدي أن تقومي بتسجيل الأمر و إضافته إلى كائن scripts بملف package.json على هذا النحو : "scripts": { "serve": "webpack serve --mode development" }, و الان يمكنك طباعة الأمر و التصفح إلى المسار الموصوف بعد نجاح البناء , و إستعراض مشروعك بشكل عادي .
  4. هل يمكنك إرفاق ملف إعداد webpack حتى يمكننا تشخيص المشكلة بشكل أفضل ؟
  5. يمكننا إستغلال ميزة قواعد البيانات العلائقية لتحقيق الغرض بمنطق مشابه للتالي : لنقم بإنشاء جدول للمواضيع بقاعدة البيانات و ليكن topics . نقوم بإنشاء جدول للصور و ليحتوي على مفتاح أجنبي كعمود : topic_id , يمثل عمود الـ id بجدول المواضيع . فتكون العلاقة بين جدول المواضيع و الصور one to many . طباعة وتنفيذ إستعلام لجلب الصور ذات موضوع محدد على هذا النحو : SELECT * FROM PHOTOS WHERE topic_id = 'YOUR_TOPIC_ID_HERE'; و سيسهل عرضها مباشرة عن طريق الفلاتر .
  6. للمشكلة عدة أسباب محتملة .ولكن الأرجح أنها قد تكون بسبب إستعمال loader واحد لنفس نوع الملف أكثر من مرة فيتم بناء مسار الصورة أكثر من مرة فيتم كسر المسار . مثال عن ذلك : إن كنت تقوم بتحميل الملفات باللواحق woff , woff2 , eot, ttf , png , svg بإستعمال url-loader ثم تقوم بتحميل الملفات باللواحق jpeg , jpg , gif , png , svg بإستعمال url-loader ضمن كائن loader جديد فسيتم كسر مسارات الصور بالصيغ png و svg ولن تظهر في المتصفح . loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader' } .. ], الحل : تحميل الملفات من نفس النوع مرة واحدة , بحذف الملفات ذات اللواحق png , svg المكررة فيكون : loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(woff|woff2|eot|ttf)$/, loader: 'url-loader' } .. ], ملاحظة : ليس بالضرورة أن يكون url-loader , المهم في الإحتمال هو أن يكون قد تم إستعمال نفس الـ loader لنفس لواحق الملفات كذا مرة لا مرة واحدة .
  7. يمكنك معاملة Role كأي Laravel Class ثان , و ليكن في العلم أنه توجد علاقة one To Many بين الدور \App\Models\Role::class و الأذونات \App\Models\Permission::class . يمكنك الوصول إلى الأذونات الخاصة بدور محدد عن طريق : <?php Role::where('name', 'admin')->first()->permissions;
  8. تحديث تحقيقا لنفس الغرض يمكنك جلب الأذونات الخاصة بمستخدم ما عن طريق إستعمال الدالة allPermissions على هذا النحو : <?php dd($user->allPermissions()); سيتم إعادة مجموعة Illuminate\Database\Eloquent\Collection بجميع الأذونات المتعلقة بمستخدم ما , و يمكنك تصفية المجموعات بحسب دور Role معين .
  9. سيكون عليك بناء نموذج إدخال و الواجهة الخلفية للبرنامج حتى يتم ذلك بشكل سليم . يمكنك تطبيق العملية وفق الخطوتين التاليتين : بناء نموذج إدخال البيانات على هذا النحو : <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> بناء الواجهة الخلفية للبرنامج : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) فيكون الكود كاملا كالتالي : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>UPDATE ITEM</title> </head> <body> <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> </body> </html> و هذا هو الشكل الأبسط و منطق العملية . يمكنك فعل الأمر عن طريق طلبات Ajax أو تضمين الكود و منطق العملية بصفحة أو نموذج إدخال اخر. الأمر فقط هو في التحقق من تحديد الـ checkbox من عدمه , العملية تبسط في : <?php $checked = null; if(isset($_POST['myCheckbox'])) { $checked = 1; } else() { $checked = 0; } // كتابة مختصرة $checked = isset($_POST['myCheckbox']) ? 1 : 0; ثم يمكنك إدراج القيمة المتحصل عليها بقاعدة البيانات مثل ما هو موصوف في المثال الأول .
  10. يمكنك إما حذف , إخفاء , تعطيل أو حتى إزالة التفاعلية من الزر بعد إستيفاء الغرض منه ( عرض الفيديو ) لتجنب المشكل من الأساس . يمكنك ذلك عن طريق التعديل إلى أحد الأكواد : <!-- حذف الزر --> <button onclick="launchVideo();$(this).remove();">افتح الفيديو</button> <!-- إخفاء الزر --> <button onclick="launchVideo();$(this).hide();">افتح الفيديو</button> <!-- تعطيل الزر --> <button onclick="launchVideo();$(this).attr('disabled', true);">افتح الفيديو</button> <!-- إلغاء تفاعلية الزر --> <button onclick="launchVideo();$(this).attr('onclick', '');">افتح الفيديو</button>
  11. إن كنت تقصد تطبيق طريقة الكود الأول في طريقة وضع الفيديو من الكود الثاني (أي إظهار الفيديو بعد الضغط على الزر في كلتا الحالتين , الأولى و الثانية ) فيمكنك ذلك عن طريق : إنشاء الزر و إضافة حدث عند الضغط عليه : <button onclick="launchVideo();">افتح الفيديو</button> إنشاء عنصر الفيديو و تضمينه بالصفحة : <div class="videoyoutube"><div class="video-responsive"><div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"></div></div></div> تعريف الدالة المسؤولة عن بدء الفيديو على هذا النحو : function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } فيكون الكود كاملا على هذا النحو : <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <script> function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } </script> هذا سيقوم بتضمين الفيديو بعد الضغط على الزر فقط . بنفس الطريقة فم بإضافة الزر المسؤول عن ملئ الشاشة أسفل عنصر الفيديو : <div id="demo-element"> <button id="go-button" style="background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap;">افتح الفيديو في كامل الشاشة</button> </div> ثم قم بإضافة التفاعلية الخاصة بالزر بعد الضغط على تشغيل الفيديو (الموصوفة في التعليق السابق) . ربما قد تحتاج بعض التنسيقات الإضافية . فيكون الكود كاملا مشابها للتالي : <style> #go-button{ background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap; } </style> <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <div id="demo-element"> <button id="go-button">افتح الفيديو في كامل الشاشة</button> </div> <script> // قم ببدء الفيديو function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); // إضافة تفاعلية لزر ملئ الشاشة setEventForGoButton(); // إضافة تفاعلية لنص الزر handleFullScreen(); } function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } </script>
  12. أظن أن قصدك "وضع الكود الثاني و الثالث بداخل الأول" (و هذا تحقيقا للغرض المطلوب). لا حاجة لذلك , يمكنك فصل كل الدوال بحسب المهمة و من ثم إستدعاءهم في دالة واحدة . بداية يمكنك تبسيط العملية أكثر عن طريق التالي : قم بوضع كل الأكواد الأول و الثاني و الثالث بداخل دوال على هذا النحو (وهذا بحسب مبدأ فصل الإهتمامات) : function openVideoFile() { if(!$('#iframe').length) { $('#iframeHolder').html('<iframe id="iframe" src="//player.vimeo.com/video/90429499" width="700" height="450"></iframe>'); } } و : function putVideoInPage() { setTimeout(function(){$(".video-youtube").each(function(){$(this).replaceWith('<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>')})},5e3); } و : function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } و : function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } و : function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } ثم يمكنك دمج و إستدعاء كل الدوال بعد الضغط على زر تشغيل الفيديو على هذا النحو : $(function(){ $('#button').click(function(){ // تضمين الفيديو في الصفحة openVideoFile(); // وضع رابط فيديو بصفحة النشر بدون وضع اكواد فريم putVideoInPage(); // إضافة التفاعلية لزر ملئ الشاشة setEventForGoButton(); // تغيير النصوص بحسب وضع ملئ الشاشة // #demo-element span النصوص المعرفة بـ handleFullScreen(); }); }); ملاحظات : الكثير من الأكواد غير واضحة المهمة في الأكواد التي أرفقتها و لا يظهر بالنسبة لي أي ترابط بين الكود الثاني و الأكواد الأخرى , و رغم ذلك قد قمت بتضيمنها في الأكواد التي وصفتها لك (يمكن لأن ذلك راجع إلى غياب باقي عناصر الصفحة ) . يمكنك تتبع نفس المنطق لكتابة دالة تجمع عمل كل الدوال المعرفة (ألف دالة تقوم بألف مهمة أفضل من دالة تقوم بألف مهمة) , سيكون الكود أفضل قراءة و أكثر وضوحا.
  13. لا يمكنك طباعة كل المتغيرات مرة واحدة , عوضا عن ذلك يجب تمرير اسم المتغير لتتم القراءة بشكل صحيح أثناء البناء , و ببساطة هذا ﻷن متصفح الواجهة الأمامية نفسه ليس له أي وصول لملف البيئة فالعملية تخص الخادم وحده و لذلك أثناء البناء يتم إستبدال أي متغير معرف على هذا النحو : process.env.MY_VAR بقيمته الفعلية و يتم البناء بشكل عادي . في حين أن المتغير : process.env يتم تجاهله بطبيعة الحال و يتم إعادة كائن فارغ عن طريقه . فعوضا عن طباعة كل المتغيرات يمكنك فقط طباعة المتغير الذي تحتاج و إستعماله بشكل عادي .
  14. لما لا تقوم فقط بتحميله تزامنيا ثم تضمينه بالصفحة ؟ componentDidMount() { // script إنشاء عنصر بوسم const script = document.createElement("script"); // تعريف المسار أو الرابط script.src = "/path/to/my_scripts.js"; // تفعيل التزامن و الوصول اليه script.async = true; script.onload = () => this.scriptLoaded(); // تضمينه في البودي document.body.appendChild(script); }
  15. يمكنك تضمين useLocation من @reach/router و من ثم قراءة القيمة على هذا النحو : import * as React from 'react'; import { useLocation } from '@reach/router'; const Current = () => { const location = useLocation(); console.log(location); }; سيتم طباعة كائن يسهل قراءة الخواص منه على هذا النحو : { pathname: "/", href: "http://localhost:8000/", origin: "http://localhost:8000" }