لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 03/01/21 في كل الموقع
-
نستطيع القيام بذلك من خلال Html أو Css بداية لاحظ معي الكود دون تعديل على حجم الصورة كود Html <div class="test"> <img src="test.png" alt=""> </div> كود Css .test{ border: 1px solid #333; width: 50vw; height: 50vh; } حددت للحاوية div التي لها الصنف test طول وارتفاع وأعطيته بوردر وسوف تكون النتيجة هكذا الآن سوف نعدل في حجم الصورة باستخدام Html و Css أولا من خلال Html : نعطي العنصر img خاصية width و height كالمثال الآتي <div class="test"> <img width="100%" height="100%" src="test.png" alt=""> </div> لاحظ الخاصيتان width , height بعد تحديد قيمتهما سوف تكون النتيجة هكذا ثانيا من خلال Css : نعطي العنصر img خاصية width و height كالتالي .test{ border: 1px solid #333; width: 50vw; height: 50vh; } img{ width: 100%; height: 100%; } سوف تكون النتيجة مشابهة للنتيجة في الأعلى2 نقاط
-
السلام عليكم هل يوجد دالة تستبدل عدة ارقام بجملة كاملة مثلا الرقم 5يعني قميص والرقم8 يعني رجالي والرقم 14 يعني صيفي وهكذا ليصبح عندي (قميص رجالي صيفي) علما ان لكل رقم عامود خاص وشكرا لكم1 نقطة
-
سنفترض أنك قد قرأت الفصول السابقة وتأكدت أن العمل الحر مناسب لك، وأنشأت حسابًا جديدًا في إحدى منصات العمل الحر ولتكن مستقل أو خمسات مثلًا، ورفعت نماذج من أعمالك السابقة إن كانت لك أعمال، أو أنشأت أعمالًا جديدة من تلقاء نفسك لتجعلها نماذج شاهدة على جودة عملك، والخطوة التالية الآن هي التعاقد مع عملاء، أليس كذلك؟ بلى، لكن كيف السبيل إلى ذلك؟ إننا ندرك جيدًا الصعوبة التي يشعر بها من لم يتعامل مع عملاء بشكل حر عبر الإنترنت من قبل، فقد مررنا بهذه المرحلة، ولن نحاول تجميل الوضع لك هنا لنقول لك أن هذه مرحلة عابرة أو أنها قصيرة أو نحو ذلك، بل نفضل إبقاء الأمور على حقيقتها مع بذل الوسائل التي تعينك على تجاوزها بإذن الله. وإنك لا محالة ستعمل بأحد أسلوبين، إما أن تعرض خدماتك في حسابك ليتصفحها العميل ويختار منها ما يشاء، كما في حالة موقع خمسات للخدمات المصغرة، أو أنك تضع ملخصًا عنك وعن أعمالك في حسابك، وتزين معرض أعمالك بأفضلها، ثم تتصفح أنت المشاريع التي يطرحها العملاء ليطلبوا من يتعاقدون معه على تنفيذها، كما في حالة موقع مستقل. وربما تقدم عروضك على المشاريع في مستقل أو تنتظر طلب العميل لخدمتك على خمسات وقتًا طويلًا، لكن هذا لا يعني أن تنتظر مكتوف اليدين دون عمل، فهذا وقت فراغ لك تشغله بتطوير نفسك ومهاراتك، والبحث عما يطلبه العملاء، فقد تقدم خدمات لسوق غير موجود، أو ربما لديك ثغرة في ملفك الشخصي تمنع العملاء من التعاقد معك. ولا يصيبنك الإحباط عند رفض العميل لك، فهذا سوق يحكمه العرض والطلب، وقد يكون العميل ممثلًا لشركة تحكمها قواعد ضابطة لاختيار العاملين معها، قواعد قد لا يكون لك فيها دخل، كمن يطلب من له خبرة بلهجة معينة أو قوانين لدولة بعينها. وإننا ندعوك إلى الحرص على تتبع العملاء بشكل لطيف غير مزعج لتسألهم عن سبب عدم اختيارهم لك من أجل أن تصقل نفسك فيه، وستجد العميل يخبرك أنه كان يحتاج من عنده مهارة كذا، أو من له خبرة في كذا وكذا، فتضع يدك على مطالب السوق لتصرف فيها وقتك وجهدك. ولنقل أنك وضعت عرضك على أحد المشاريع التي رأيت أنها مناسبة لك، وحددت ميزانيتك ووقت التنفيذ، وقبل العميل عرضك، وها أنتما الآن وجهًا لوجه في صفحة المشروع ونقاش الصفقة، فهذا محل حديثنا في هذا المقال وما يليه، وسنبدأ بالإدارة الفنية للمشروع. تنظيم طريقة التعامل بينك وبين العميل يتحمس البعض لقبول عرضه فيلتفت فورًا إلى مباشرة العمل، ثم لا يرجع إلى العميل إلا عند انتهاء المشروع، وهذا خطأ يجب الحذر منه أشد الحذر، خاصة عند التعامل مع عميل لأول مرة لا يعرف نمط عملك ولا تعرف طبيعة احتياجاته، وقد وقعت في هذا كثيرًا، والواجب هنا هو إرساء أرضية واضحة مشتركة بينكما تحددون فيها المطلوب في المشروع بدقة وفي نقاط واضحة، وتحددون وسائل التواصل بينكما وأوقات ذلك التواصل، وأنواع الملفات التي ستقدمها له وامتداداتها لاحتمال عملك على نظام تشغيل يختلف عن الذي لدى العميل، وسنبين كل ذلك في هذا المقال إن شاء الله. وربما يشعر العميل ببعض الراحة إن كان يتعامل على منصة عمل حر تضمن له حقه مثل مستقل أو خمسات أكثر من التعامل عبر البريد أو عبر أداة إدارة مشاريع مثل تطبيق أنا أو تريللو، لكن هذا لا يمنع أنه يريد معرفة مجريات المشروع وما حدث فيه وقتما يحب أو يرى ذلك مناسبًا. وهذا التفصيل أول المشروع مفيد لك أنت أيضًا في حفظ حقك، فقد يطلب العميل شيئًا في صفحة المشروع أمام المستقلين، ثم يراسلك أنه يريد كذا وكذا -أكثر من الذي طلبه أول مرة- أو يطلب عينة مجانية كبيرة للتأكد من جودة عملك، أو يغير طلباته أو يضيف عليها بعد قبوله لعرضك، فكل هذه مؤشرات تنذر أنه عميل سوء يجب الحذر منه والتعامل معه بشكل واضح ومحدد، حتى إذا حدث -لا قدر الله- نزاع بينكما، استطعت ضمان حقك من جانب إدارة المنصة التي تستخدمها. تنظيم الملفات قد يكون شأن تنظيم ملفات العمل تافهًا لظنك أنك يجب أن تولي المشروع الذي بين يديك وقتك وجهدك، لكن اعلم أن عمل بلا تخطيط هو بداية فوضى محققة، وإن لم تشعر بها في أول عملك، لكن ستجد نفسك بعد عام أو أكثر تنفذ أعمالًا من الصفر أنت تعلم أنك عملتها من قبل، لكن لأنك لم تنظم الملفات يوم بدأت العمل عليها لا تستطيع استرجاعها ولا ربما تذكر أين كانت! وكذلك أثناء العمل على المشروع نفسه، فبين ملف على حاسوبك وآخر على خدمة تخزين سحابية، وملف اسمه "الملف النهائي" وآخر اسمه "التعديل الأخير" ستجد أنك والعميل تائهين بين هذه الإصدارات وبعضها. وقد شرحنا بالتفصيل هذه النقطة لتتعلم كيف تنظم ملفاتك في خطوات بسيطة دون الدخول في تعقيدات في العناية ببيئة العمل. مجلد جامع للمشروع إذا كان العميل يريد ترجمة ملف واحد أو تصميمًا واحدًا أو استشارة فنية لشركته أو نحو ذلك مما يمكن إتمامه بأدوات بسيطة فإن صفحة نقاش المشروع تكفي في الغالب، إذ ترفق الملفات إن وجدت في ردودك على العميل وانتهى الأمر. وقد عملت بهذا الأسلوب بضعة سنين كنت أترجم فيها أحيانًا المقالة الواحدة والخمسة والستة، ولا أحتاج سوى صفحة إدارة المشروع فقط. لكن إن كان المشروع يحتاج تفصيلًا لملفات كثيرة أو متنوعة فقد تحتاج إلى مجلد مشترك بينكما تكون ملفات العمل متاحة فيه للاطلاع والمراجعة والتعديل، بل والعمل عليها من البداية للنهاية أحيانًا، والخيار الشائع الآن والمناسب هو خدمة مثل درايف (Google Drive) من جوجل، أو ما يشابهها من الخدمات السحابية مثل دروب بوكس (DropBox) أو زوهو (Zoho) أو غيرها، وفق ما يناسبك ويناسب عميلك. صيغة ملفات المشروع فإن اخترت موقع المجلد المشترك بينكما وليكن في جوجل درايف مثلًا، فيجب أن تتفق مع العميل على صيغة الملفات التي يريدها، فإن كانت ملفات نصية فقد يريدها بصيغة odf مثلًا أو odt أو حتى بصيغة مارك داون (Mark Down)، عوضًا عن صيغة docx المعتادة التي يصدرها طقم مكتب مايكروسوفت. وقل مثل هذا على ملفات الصور والصوتيات والمرئيات وملفات التصميم ثنائي وثلاثي الأبعاد وغير ذلك، كي لا يحدث أي عبث واختلاف في طريقة عرض المستندات بينك وبين العميل. وقد وقعت في هذا بنفسي أول عملي في الترجمة على موقع مستقل، إذ كنت أستخدم نظام تشغيل وطقم مكتب يختلفان عن اللذان يستخدمهما العميل، فكنت إذا أرسلت إليه الملف وفتحه وجد الكلمات مبعثرة فيعيده إلي مرة أخرى، وذلك لأننا لم نتفق على صيغة محددة للملفات التي سأرسلها إليه. أسلوب إدارة المشروع والآن نأتي لطريقة إدارة المشروع بينك وبين العميل، إذ يجب أن تحددا هل يجب تقسيم المشروع إلى عدة مراحل إن كان كبيرًا أم تكفي مرحلة واحدة، وهذه الطريقة مفيدة لكما على سواء، وهل تكفي صفحة إدارة المشروع على منصة العمل الحر التي تستخدمانها أو رسائل البريد إن كان العميل وصل إليك من بريدك أو موقعك أو أحد حساباتك الاجتماعية، أم يحتاج المشروع إلى تقسيم وتفصيل للمهام وملفات مرجعية وغير ذلك مما قد يجعل العمل من صفحة واحدة أو رسائل بريدية أمرًا مزعجًا جدًا وفوضويًا. وكذلك تنظر مع العميل في كيفية التواصل بينكما ومواقيت ذلك التواصل، هل ستكفي رسائل البريد أو صفحة إدارة المشروع أم تحتاج إلى أن تجتمع به في مكالمات مرئية، أو ربما تحتاج أن تريه شيئًا على حاسوبه أو العكس، وتخبره بمواعيد إجازاتك الأسبوعية كي لا ينزعج حين يراسلك ولا ترد عليه، ومنطقتك الزمنية إن علمت أنه من منطقة زمنية مختلفة. تقسيم المشروع إلى مراحل إن كان المشروع كبيرًا، مثل ترجمة كتاب من سبع مئة صفحة، أو تطبيق لمستشفى يعمل على الأندرويد والآيفون إضافة إلى موقع للمستشفى مرتبط بهذين التطبيقين، أو تصميم لهوية شركة مثلًا، فإننا نفضل أن تطلب من العميل الاتفاق على تقسيم المشروع على عدة مراحل مناسبة، ثم تقدر ميزانية كل مرحلة وتشرعان في العمل. وفائدة ذلك للعميل أنه إن حدثت مشكلة معك أو لم يعجبه عملك فإنه يستطيع أن يلغي ما بقي من المشروع دون أن يخسر وقتًا أو مالًا كبيرًا، أما فائدة ذلك بالنسبة لك فإنه يحفظ حقك المالي أولًا، ويخفف وطأة العمل وإدارته عليك ثانيًا. ذلك أنك ربما تدرك أن العميل قد يحصل على المشروع الذي طلبه ثم لا يعطيك مالك وأجرك! وقد تقول أن منصة العمل ستحفظ لك حقك، نعم، هذا صحيح، ولهذا ننصحك دومًا بالعمل من منصات عمل حر، فإنها وإن كانت ستقتطع نسبة من كل مشروع إلا أنها تضمن لك حقك بما أن العميل يودع قيمة المشروع لدى المنصة قبل أن تتم الموافقة على مشروعه. لكن ماذا لو أتاك العميل من خلال موقعك أو حسابك الشخصي وطلب أن تتعاملا عبر البريد أو أي وسيلة أخرى؟ حينها تطلب منه نصف قيمة المشروع (أو الجزء المتفق العمل عليه) مقدمًا حفظًا لحقك، وتقسم المشروع إلى مراحل إن كان كبيرًا كما ذكرنا، فإن حدث -لا قدر الله- أن حصل العميل على المشروع ولم يعطك باقي المبلغ، فإنك تكون حصّلت أخف الضررين، فلا أنت أنفقت وقتك في المشروع كاملًا، ولا أنت فقدت أجرك على المشروع بما أنك حصلت على نصف الثمن مقدمًا. وإني أخبر عملائي الذين يراسلونني عبر بريدي أني أحصل على نصف قيمة المشروع قبل أن أشرع في العمل فيه، فإن قرر العميل إلغاء المشروع قبل البدء فيه فإني أرجع إليه ما دفعه، وإن قررت أنا الاعتذار عن المشروع فإني أعيد إليه ما دفعه كذلك، أما إن قرر العميل إلغاء المشروع بعد البدء فيه فإن الأمر إلي إن شئت أرجع المال وإن شئت احتفظت به، وذلك وفقًا للوقت والجهد الذي بذلته في المشروع إلى حين طلب العميل إلغاءه. وتبقى الحالة الأخيرة التي يقرر فيها العميل إلغاء المشروع بعد نصف مدة التنفيذ، فإنه لا يحق له حينها شيء مما دفعه طبعًا في حال انتهيت من العمل على ذلك النصف وسلمته إياه أو أوشكت على ذلك. وتلك الفقرة أعلاه ليست بيني وبين نفسي أو أحدثك بها سرًا، بل أخبره بها مفصلة قبل البدء في المشروع إن لم نكن على منصة عمل حر تضمن حقي أو لم نكن تعاملنا من قبل ولا نعرف قواعد العمل لكل منا. لتقسيم العمل أيضًا فائدة أخرى لا يعلمها إلا أصحاب الخبرة في المجال ومن ذاق لوعة الاحتيال؛ ففي حال عدم تقسيم العمل وإنجازه كله وتسليمه إلى العميل، قد يدَّعي العميل أن العمل ليس بالجودة أو المواصفات المطلوبة ويطلب إلغاء العمل ثم يأخذ العمل ويستعمله في حال نجح في إلغاء المشروع وبذلك تقع ضحية الاحتيال والنصب. فإن كنتما تستعملان منصة مثل منصة مستقل، فربما ينصفك فريق الدعم الفني في ذلك إلا إن نجح العميل في إقناع فريق الدعم الفني بطريقة مخادعة بصحة ادعائه خصوصًا أن لديه حجة تسليم العمل دفعة واحدة دون الرجوع إليه أو اطلاعه على سير العمل وعرض عينات له. وهذا الحال على منصة تضمن لك حقك، فكيف إن كنت خارجها؟! لذلك، احرص على تسليم العميل جزءًا تلو الآخر من العمل، وتأكد أن يعطيك الضوء الأخضر بالإكمال في كل جزء وتأكد من توثيق ذلك كتابيًا لإبرازه لفريق الدعم الفني إن حصل أي خلاف بعدئذٍ. أدوات إدارة المشاريع ومتابعة المهام ربما تكفيك صفحة إدارة المشروع على منصة العمل نفسها مع إرسال تقرير دورية عن مرحلة التنفيذ إلى صاحب المشروع أو ربما تكتفي بملف بسيط في جداول جوجل لمتابعته إن كانت مراحله لا تحتاج كثيرًا من التفصيل، مثل ترجمة مقالات فلا تحتاج إلا إلى مرحلتي الترجمة والمراجعة بالإضافة إلى حساب عدد كلمات المقال وعدد الكلمات المترجمة أو ما أنجز من العمل وغير ذلك، فتضعه كله في ورقة عمل (sheet) بصيغة معينة تتفق عليها مع صاحب المشروع. لكن المشاريع المعقدة التي ترتبط بأقسام مختلفة تحتاج إلى تفصيل أكثر من هذا في مراحل التنفيذ خصوصًا المشاريع البرمجية منها، بل ربما تكون أنت جزءًا من عدة أشخاص يوظفهم العميل كي يعملوا على مشروع واحد كبير، وهنا يبرز دور تطبيقات متابعة المهام وإدارة المشاريع. تطبيق "أنا" من حسوب أطلقت حسوب قبل عام تقريبًا تطبيق "أنا" لاستخدامه في إدارة المهام والمشاريع، وهو تطبيق يمكّنك من رفع ملفات إليه وإنشاء ملاحظات ومستندات وقوائم مهام العمل الذي تعمل عليه ومشاركتها مع الآخرين، وتخصيص قوائم للمشاريع التي تنفذها إن كنت تعمل على عدة مشاريع في وقت واحد. كذلك تستطيع إنشاء لوحات فيها قوائم الأخبار والمعلومات المتعلقة بموضوع ما لتتصفحها متى شئت، دون أن تشتت نفسك على الويب، فتكون مجموعة لك في مكان واحد. انظر الصورة التالية. وميزة هذا التطبيق عن تطبيق Trello أو غيره الذي سنتحدث عنه فيما يلي، أنه من العرب للعرب، ولا أقصد من حيث اللغة فقط، بل هو يسد الثغور التي ليس لدينا تطبيقات نحن العرب تفهمنا ونفهمها وتعرف احتياجاتنا، فنضطر إلى استخدام تطبيقات أجنبية قد تحل مشاكل لا تهمنا بالضرورة. وحسب قول عبد المهيمن الآغا في مقالة نشرها على مدونته بشأن تطوير "أنا" أنه لم يرد أن تتحكم خوارزميات في ما يراه على الويب كل يوم، وأراد إنشاء قوائم لما يتابعه تحديدًا، ومكانًا يجمع ما يهتم به في مكان واحد. وفي رأيي هو أسهل التطبيقات بدءًا لك، إذ يكون لك حساب فيه مباشرة إذا سجلت حسابًا في حسوب للعمل على منصة مثل مستقل أو خمسات، فتستطيع تجربته أولًا فإن لم يعجبك انتقلت إلى غيره. تطبيق إدارة المهام ومتابعتها (Trello) لنقل أن العميل يريد إنشاء موقع به عشرين قسمًا كل قسم فيه أربع صفحات، ستجد في الغالب أن كل صفحة ستمر بمرحلة التخطيط الهيكلي (Wireframing) ثم التصميم المرئي، ثم مراجعة التصميم المرئي برمجيًا، ثم تجهيز قواعد البيانات في الناحية الخلفية (BackEnd)، وكتابة محتوى الصفحة ومراجعته وتنسيقه مرئيًا داخل الصفحة، وغيرها. وهكذا قد تجد نفسك بين ثلاثة أو أربعة أشخاص يعملون على هذا المشروع، وحينها لن تصلح صفحة إدارة المشروع لإنهائه أو حتى الرسائل البريدية، بل يحسن بكم حينها استخدام أحد برامج متابعة المهام وتنظيمها، وهذا مثال يمكن إسقاطه على تطبيق أنا الذي ذكرناه أعلاه، لكن لديك خيار Trello هنا بما أننا نتحدث عنه، إذ هو مختص بإدارة المهام فقط، على عكس "أنا" الذي يشمل أكثر من هذا كما وضحنا، كما أن لديك بدائل أخرى مثل BaseCamp و Asana. والحق أني جربتها جميعًا ووجدت أن تطبيق "أنا" أفضل في جمع كل ما أحتاج من إدارة لمشاريعي في مكان واحد، ثم BaseCamp الذي يتفوق على Trello في متابعة المهام وتفويضها وإشعاراتها لكنه ليس مجانيًا وعليه يكون غير مناسب لك إذا كانت ميزانيتك محدودة، على عكس "أنا" وتريللو. المكالمات والاجتماعات قد تحتاج إلى الحديث مع العميل حول عدة أمور أو نقاط لتتخذوا قرارات بشأنها، وإن تم ذلك عبر رسائل نصية فربما يطول اتخاذ قرار واحد إلى نحو أسبوع مثلًا بين الأخذ والرد، فحينها يكون الخيار الأفضل هو اعتماد برنامج للمحادثات الصوتية والمرئية بينك وبين العملاء مثل Skype أو Zoom أو أي وسيلة تواصل مناسبة، بل ربما حتى يكون الاتصال الهاتفي إن رأيتما ذلك، المهم أن تتوفر وسيلة تواصل سريعة تكون قناة مباشرة للمناقشة والعصف الذهني. وإنني أعتمد سكايب في مكالماتي مع العملاء، لكن قد يكون سكايب غير متاح أحيانًا لدي أو لدى العميل، فحينها نستخدم جيتسي Jitsi، وكنت أستخدم Zoom أحيانًا أخرى عند عدم توفر الخيارين الأولين أو عند الحاجة إلى تسجيل الاجتماع بسهولة. وانتبه إلى أن تستأذن العميل من باب الأمانة في تسجيل اجتماعه إن أردت التسجيل، فإني أذكر أن أول استخدام لي لبرنامج Zoom كان أثناء عملي عن بعد في شركة برمجية من قبل، فكنت أسجل اجتماعي مع مدير الشركة في كل مرة بعلمه بأن أخبره أني سأسجل الجلسة إن كنت أنا بادئ الاجتماع، أو أطلب منه السماح لي بالتسجيل إن كان هو البادئ، إذ يجب أن يسمح صاحب الجلسة لغيره بتسجيلها من خلال البرنامج أولًا. ثم استخدمته بعد ذلك مع عملاء من غزة والسعودية وغيرها، وقد وافق البعض بأريحية تامة إذ أني أخبرهم بتسجيلي من أجل العودة إلى الجلسة ومراجعة ما قيل فيها، فقد تمتد الجلسة إلى نصف ساعة أو ساعة، ولا آمن أن أسهو في تسجيل نقطة أو اثنتين إن كنت أسجل كتابةُ، في حين استهجن بعض العملاء واستغربوا طلب التسجيل في البداية، ثم لما شرحت لهم وافقوا على طلبي. وبأي حال فإن شاهد هذه النقطة أن يكون لك أكثر من بديل ليكون احتياطيًا للخيار الافتراضي في حال تعطل البرنامج أو عدم توافره لديك أو لدى العميل، وهذه نقطة يجب التنبه إليها في كل أمرك وأدواتك إذ لا بد من بدائل تكون جاهزة للاستخدام دومًا كي لا يتعطل عملك. إدارة الأزمات نقصد بإدارة الأزمات كيفيّة الاستجابة والتّعامل مع المُشكلات التي تواجهنا فجأةً أثناء تنفيذ عمل معيّن والتي لا يكون لك يد فيها في الغالب مثل المرض والحوادث والسفر الاضطراري، فالمستقل بَشرٌ معرض لمشكلات ومواقف لم يحسب حسابها، وفي حين أنّ الموظّف العادي يستطيع أخذ إجازة فإن المستقل يجب عليه إيجاد آليّة معيّنة للتّجاوب مع الأزمة التي تعرض له لحلّها واستكمال العمل بأسرع وقت ممكن. وأحد الأساليب المهمّة جدًا في حل هذه المشاكل وأنجحها هو إطلاع العميل على الموقف في أقرب وقت ممكن، فذلك أدعى أن تنظرا في حالة المشروع في أقرب وقت لتلافي الخسائر المحتملة عليك أو على العميل. وإننا لنعرف أن التصرف الافتراضي للمستقل في هذا الشأن هو تأجيل إخبار العميل ريثما يتحسن الوضع خوفًا من خسارة المشروع، لكن اعلم أنك تخاطر هنا بعلاقتك مع هذا العميل وربما سمعتك على الإنترنت، فربما لا يتحمل العميل هذا التأخر غير المبرر ويلغي مشروعه معك على أي حال، وربما يتجاوز هذا إلى تحذير غيره من العملاء منك. فتجنب هذا بالمسارعة إلى إخباره بما حدث معك مع تقديم الحلول المقترحة مراعيًا لمصلحة العميل، إما تأجيل التنفيذ أو الاعتذار عن إتمامه إن كان العميل في عجلة من أمره أو كان الطارئ الحادث لك سيطول أمده. وقد واجهت سارة أثناء إعدادها لهذه السلسلة من المقالات أزمة صحية منعتها ممارسة الأعمال اليومية الروتينية، فقررت رغم ذلك متابعة العمل لكن مع شرح حالتها الصحية لأي عميل تعاملَت معه في تلك الفترة، أما العملاء الذين لم تنهي مشاريعهم فقد خيَّرَتهم بين تأجيل المشروع أو إلغائه بشكل نهائي، أو متابعة العمل لكن بوتيرة أبطأ من المعتاد، ولم يطلب أي عميل منهم التوقف عن العمل بل اختار جميعهم انتظارها حتى تتحسن صحتها. خلاصة المقال وهكذا بعد أن فصَّلنا كيفية الإدارة الفنية للمشروع، سننظر في المقال التالي كيفية التعامل الأمثل مع العملاء وإدارة التواصل معهم، والخلافات التي قد تطرأ أثناء العمل على المشروع. اقرأ أيضًا المقال التالي: فن التعامل مع العملاء في العمل المستقل المقال السابق: كيفية التسويق الذاتي في العمل الحر أنا حسوب: أداة واحدة تجمع كل ما تحتاجه لإدارة عملك عن بعد مقدمة إلى تطبيق Trello لإدارة المشاريع أفضل أدوات التواصل عن بعد كيف يساعدك برنامج إدارة البريد الإلكتروني في السيطرة على بريدك الوارد النسخة الكاملة من كتاب دليل المستقل والعامل عن بعد1 نقطة
-
عندي Input type اديته متغير اسمه consumption-m و اتنين تانيين اديتهم اسماء marker-hight-production و الاخر اسميته layers-count عاوز الحقل بتاع consumption-m يكون نتيجته حاصل ضرب marker-hight-production و layers-count كتبت الكود لحد كده مساعدة فضلا مع الشكر $(".consumption-m").keyup(function(){ var val = $(this).val(); });1 نقطة
-
السلام عليكم .. كيف أجعل هذا ال reducer يقلل الكمبية بمقدار 1 فى ال initState الخاصة ب cakes.qty فى كل مرة اقوم بعمل dispatch للأكشن .. هذا هو الكود // Here is The Reducer import { SELL_ONE_CAKE } from "./types"; const initialState = { cakes: [ { id: 1, title: "Classic Cake", qty: 40, price: 15, }, { id: 2, title: "Chocolate Cake", qty: 10, price: 20, }, { id: 3, title: "Simple White Cake", qty: 40, price: 30, }, ], }; // I Think The problem is here export const reducer = (state = initialState, action) => { switch (action.type) { case SELL_ONE_CAKE: return { ...state, cakes: state.cakes[0].qty - 1 }; // => I Think The problem is Here default: return state; } }; // The Action import { SELL_ONE_CAKE } from "./types"; export const sellOneCake = () => ({ type: SELL_ONE_CAKE, }); // The Screen <Text>porfit: {Profits}</Text> <Text>Number Of Cakes: {cakes}</Text> <Button title="Sell One Cake" onPress={() => dispatch(sellOneCake())} /> فقط أريد أن أعرف ما المفترض أن أكتبه هنا لكى يقل الرقم export const reducer = (state = initialState, action) => { switch (action.type) { case SELL_ONE_CAKE: return { ...state, cakes: state.cakes[0].qty - 1 }; // => I Think The problem is Here default: return state; } };1 نقطة
-
يظهر هذا الخطأ عند عدم وجود ذاكرة RAM كافية على الخادم أو الجهاز الذي يقوم بتشغيل المشروع. إن الحل الأفضل هو بزيادة RAM ضمن الجهاز في حال كانت الموارد الموجودة لا تتناسب مع حجم المشروع، ولكن يمكن تدارك ذلك بإنشاء swap لإضافة مساحة إضافية لمعالجة التعليمات ضمن المشروع كالتالي: /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 /sbin/mkswap /var/swap.1 /bin/chmod 0600 /var/swap.1 /sbin/swapon /var/swap.1 ويمكن أيضاً إنشاء ملف swap دائم، على سبيل المثال لنفترض أننا سنقوم بإنشاء ملف 4Gigabyte يمكننا إجراء ذلك عن طريق تحديد بلوك بسعة 1Gigabyte وعداد على القيمة 4 كالتالي: sudo dd if=/dev/zero of=/swapfile bs=1G count=4 4+0 records in 4+0 records out 4294967296 bytes (4.3 GB) copied, 18.6227 s, 231 MB/s ويوجد أيضاً طريقة مختصرة لما سبق، عن طريق تنفيذ أمر واحد هو: sudo fallocate -l 4G /swapfile ملاحظة: عند إجراء أي أمر من الأوامر السابقة يجب أن يتم تنفيذه عن طريق المستخدم root.1 نقطة
-
يُمكنك عمل ذلك عن طريق التالي: لنفترض أنه لديك الحقول بالشكل التالي: <input type="number" class="marker-hight-production" placeholder="marker-hight-production" value="0"> <input type="number" class="layers-count" placeholder="layers-count" value="0"> <input type="number" class="consumption-m" placeholder="consumption-m"> بعد ذلك يُمكنك إستخدام jQuery للتسمع على حدث keyup أو الحدث الذي تريده في كل من الحقلين و على أساسه تقوم بتغير قيمة الحقل الثالث كما هو موضح أدناه: $(function () { $('.marker-hight-production, .layers-count').on('keyup', function() { let x = $(".marker-hight-production").val(), y = $(".layers-count").val(); $('.consumption-m').val(x * y); }); }); و هذه الpen توضح العملية: إضغط هنا1 نقطة
-
1 نقطة
-
أحاول التخلص من الشروط في الكود التالي: if ($this->searchTerm) { $searchTerm = '%' . $this->searchTerm . '%'; $getSales = Shoppingcart::where('trans_code', 'LIKE', $searchTerm) ->select('trans_code', 'created_at', DB::raw("SUM(sub_total) as total")) ->groupBy('trans_code') ->paginate(10); } else { $getSales = Shoppingcart::with(['user']) ->select('trans_code', 'created_at', DB::raw("SUM(sub_total) as total")) ->groupBy('trans_code') ->paginate(10); } و تقليصه قليلا عن طريق إستخدام when كيف يُمكنني عمل ذلك حاولت لكن لم أستطع.1 نقطة
-
يُمكنك إستخدام when بالشكل التالي: $getSales = Shoppingcart::when($this->searchTerm, function ($query, $searchTerm) { return $query->where('trans_code', 'LIKE', "%{$searchTerm}%"); }, function ($query) { return $query->with('user'); })->select('trans_code', 'created_at', DB::raw("SUM(sub_total) as total")) ->groupBy('trans_code') ->paginate(10); يُمكنك الإطلاع على توثيق موسوعة حسوب: البنود المشروطة (Conditional Clauses) و ستجد مثال يُشابه لما تريد في هذه الفقرة: يُنفّذ التابع when النطاق المُغلق المحدّد Closure فقط عندما تكون المعاملة الأولى true. في حالة كانت المعاملة الأولى false لن يُنفّذ النطاق المغلق Closure. تستطيع تمرير نطاق مُغلق Closure آخر كثالث معامل للتابع when. سيُنفّذ هذا النطاق المُغلق في حالة كانت المعاملة الأولى false.1 نقطة
-
قمت بإنشاء Job إسمه ProcessCSV لكن عند تنفيذ الأمر: php artisan queue:work لا يتم تنفيذ الJob و تحدث حلقة غير منتهية Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV Processing: App\Jobs\ProcessCSV ... لا أدري ما المشكلة و كيف يُمكن معالجة الأمر.1 نقطة
-
هذه المُشكلة تحدث لأن الأمر: php artisan queue:work سيُواصل العمل لحين يتم إنهاؤه يدوياً او إغلاق الطرفية. لذلك laravel تُوفر الأمر: php artisan queue:work --tries=3 يُمكنك تمرير عدد مرات المُحاولة بإستخدام --tries لتجنب الحلقة الغير مُنتهية التي تحدث بسبب خطأ في تنفيذ ال job و لمعرفة الخطأ الذي يُسبب المُشكلة يُمكنك الإطلاع على ملف laravel.log و ستجد سبب المُشكلة أيضاً يُمكنك الإطلاع على جدول failed_jobs في العمود exception لتعرف سبب المُشكلة إذا كنت تستخدم database driver.1 نقطة
-
أحاول أن أقوم بتغير الحالة الخاصة بمكون react عند الضغط على زر معين لتصبح true بدلًا من false أو العكس ولكن يظهر لي الخطأ التالي: فهمت من الخطأ أنه تم تغير حالة المكون عدد كبير من المرات، وللحفاظ على أداء الصفحة يظهر هذا الخطأ، لكن المشكلة أن هذا الخطأ يظهر بدون أن أضغط على الزر حتى. هذا الكود الذي أستعمله: import React, { Component } from 'react'; class Row extends React.Component { constructor(props) { super(props); this.toggle= this.toggle.bind(this); this.state = { details: false } } toggle(){ this.setState({ details: !this.state.details }); } render() { return ( <div> <span className={this.state.details ? "block" : "hidden"}>Some Content</span> {<div className="btn btn-lg" onClick={this.toggle()}>Toggle</div>} </div> )} } export default Row;1 نقطة
-
يحدث هذا الخطأ لأنك تقوم بإستدعاء التابع toggle داخل التابع render وهذا يسبب أن يقوم react بعمل re-render المكون والحل هو تغير الجزء الخاص بإستدعاء التابع toggle ليصبح كالتالي: {<div className="btn btn-lg" onClick={this.toggle}>Toggle</div>} وفي حالة أردت أن تقوم بتمرير قيمة معينة للتابع toggle مثل الكائن event يمكنك أن تستخدم الدالة السهمية onClick={(event) => this.toggle(event, params)} بهذا الشكل لن يتم إستدعاء التابع toggle مباشرة بل سيتم تنفيذه إذا قام المستخدم بالضغط عليه. بالتوفيق.1 نقطة
-
إن الفرق الأساسي بينهما هو في طريقة استخدامهما. فاستخدام roles هو عند الاتصال المباشر مع التطبيق، أما Oauth-2 أو scopes يغطي الوصول إلى مصادر API لمستخدم خارجي بالنيابة عن المستخدم المباشر. لتطبيق ذلك يجب أولاً تهئية مكتبة laravel/passport بالشكل الصحيح من التوثيق الرسمي باتباع الخطوات. ثم يجب تعريف ال scopes بشكل مفصّل بحيث يتم ذكر كافة الصلاحيات التي سيتم استخدامها، ففي ملف AuthServiceProvider نقوم بكتابة التالي: Passport::tokensCan([ 'manage-order' => 'Manage order scope' 'read-only-order' => 'Read only order scope' ]); ثم نقوم بكتابة ملف المتحكم الخاص بالتوثيق: namespace App\Http\Controllers; class OrderController extends Controller { public function index(Request $request) { } public function store(Request $request) { // عملية مخصصة للمدير } public function show($id) { // الإظهار للمدير والمستخدم العادي } } ثم في ملف api نقوم بتعريف الموجهات مع استخدام auth المناسب لها: Route::get('/api/orders', 'OrderController@index') ->middleware(['auth:api', 'scopes:manage-order']); Route::post('/api/orders', 'OrderController@store') ->middleware(['auth:api', 'scopes:manage-order']); Route::get('/api/orders/{id}', 'OrderController@show') ->middleware(['auth:api', 'scopes:manage-order, read-only-order']); حيث نقوم بتمرير 'scopes:manage-order, read-only-order' حسب الصلاحيات التي قمنا بتعريفها في الباسبورت وأيضاً، لإصدار token للمستخدم، يجب أولاً التحقق من صلاحيات هذا المستخدم ولتنفيذ ذلك نحتاج متحكم إضافي كالتالي: namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; class ApiLoginController extends Controller { use AuthenticatesUsers; protected function authenticated(Request $request, $user) { // التحقق من صلاحيات المستخدم من قاعدة البيانات $role = $user->checkRole(); // إعطاء scope تبعاً لصلاحيات المستخدم if ($role == 'admin') { $request->request->add([ 'scope' => 'manage-order' // grant manage order scope للمدير ]); } else { $request->request->add([ 'scope' => 'read-only-order' // read-only order scope للمستخدم ]); } // تحويل الطلب إلى oauth $tokenRequest = Request::create( '/oauth/token', 'post' ); return Route::dispatch($tokenRequest); } } أخيراً، نقوم بتوجيه المستخدم عندما يقوم بتسجيل الدخول إلى هذا المتحكم كالتالي: Route::group('namespace' => 'Auth', function () { Route::post('login', 'ApiLoginController@login'); });1 نقطة
-
للتخلص من الإستعلامات الإضافية او تخفيض عدد الإستعلامات إستخدم دائماً التحميل الحثيث Eager loading او التحميل المُسبق للعلاقات لأنه عند إستخدامك للعلاقة كخاصية من دون التحميل الحثيث سيتم إجراء إستعلام إضافي في كل مرة و هذه المُشكلة تُسمى ب N + 1 أي من أجل كل كائن تستعلم N مرة إضافية. ففي حالتك مثلاً: في النموذج Comment public function children() { return $this->hasMany(Comment::class, 'parent_id'); } في المُتحكم: public function show($slug) { $article = Article::with(['comments' => function ($query) { $query->with('children')->where('status', true); }])->where('slug', $slug)->firstOrFail(); return view('article.show', compact('article')); } في صفحة العرض تكون بهذا الشكل مثلاً: @foreach($article->comments as $comment) {{ $comment->body }} @foreach($comment->children as $subComment) {{ $subComment->body }} @endforeach @endforeach1 نقطة
-
إن المشروع سيعمل باستخدام xampp أو أي برنامج رديف على جهازك المحلي لأن xampp بطبيعته يحوي جميع الإضافات اللازمة ومنها ext-dom، أما على خادم الويب فهذه الإضافة ناقصة. ولكن يوجد أيضاً رسالة تحذير بأنه لا يجب أن تقوم بتشغيل composer من المستخدم الجذر (لأسباب الحماية). فالأفضل أن تقوم بإنشاء مستخدم آخر قبل البدء بالعمليات على المشروع لتجنب أي خطأ أو مشكلة على الخادم. أما بالنسبة للمكتبة، فعند تحميل php-xml يتم معها تحميل جميع المكتبات اللازمة، عن طريق الأمر التالي: sudo apt-get update sudo apt install php-xml وأيضاً على الأرجح أنه ينقص لديك mbstring، يتم تحميلها كالتالي: sudo apt-get install php-mbstring وأخيراً نقوم بتحديث composer والإضافة كالتالي: composer update composer require cviebrock/eloquent-sluggable1 نقطة
-
هذا كود من مكتبة jquery وهي مكتبة javascript قديمة والكود هو مستمع لتمرير النافذة ويحدد ما ان كانت النافذة ممررة الى الأسفل بقيمة أكبر من 10px فاذا كانت كذلك يضيف class header-active الى العنصر الذي يحمل id=header أما اذا كان العكس فسوف يزيل ال class header-active من العنصر $(window).on('scroll load',function(){ if($(window).scrollTop() > 10){ $('#header').addClass('header-active'); } else{ $('#header').removeClass('header-active'); } });1 نقطة
-
يعتمد Next JS على React ليسهّل العمل على المطورين ويختصر الكثير من الوقت عن طريق ما يقدمّه من توجيه routing وفصل الكود ببنية متينة، ودعمه ل webpack بشكل افتراضي والعديد من الميزات الأخرى التي تكون متاحة بشكل تلقائي بمجرد إنشاء مشروع عن طريقه. وبالتالي لا يحتاج المطوّر لتضمين هذه الأمور من الصفر في المشروع الذي يعمل عليه. فمثلاً من أهم الفروقات الموجودة بينهما: عند إنشاء مشروع جديد باستخدام react يتم إنشاء مجلدين أساسيين هما public و src بالمحتويات التالية: ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock أما إنشاء مشروع عن طريق Next فيتم تلقائياً تهئية بنية ملفات المشروع لتكون جاهزة مباشرةً للعمل كالتالي: . ├── README.md ├── package.json ├── node_modules ├── pages │ ├── _app.js │ ├── api │ └── index.js ├── public │ ├── favicon.ico │ └── vercel.svg ├── styles │ ├── Home.module.css │ └── globals.css └── yarn.lock حيث تم إضافة مجلد pages ويمكنك مباشرةً البدء بتنسيق الوجهات وتكون جاهزة للربط والتوجيه routing، وأيضاً مجلد public الذي سيحوي الملفات الثابتة لمشروعك مثل الصور ولن تحتاج لإجراء require في كل مرة لإدخال الصور إلى المكونات على سبيل المثال. وبالنسبة للتوجيه تستطيع مباشرةً استخدام Link للتنقل بين الصفحات: <Link href="/"> <a className="header__anchor">Home</a> </Link> وأيضاً، بالنسبة للتعامل مع البيانات، يقدّم Next بشكل افتراضي آليات data fetch للتعامل مع API وجلب البيانات إلى الواجهات بدلاً من تعريفها من الصفر وقبل تحميل الوجهات مما يتيح سهولة للمستخدم في استعراض الموقع والبيانات. يوجد العديد من الخصائص والميزات الأخرى التي يقدمها Next والتي يمكنك التعرف عليها وعن كيفية استخدامها من الموقع الرسمي. أخيراً، مع استخدام Next سيبقى بإمكانك استخدام جميع خصائص React ولا يتم الاستغناء عن أي شيء أو تبديله، فهو فقط يبسط الأمور ويسرّع العمل للانطلاق بالمشروع.1 نقطة
-
لايمكنك استدعاء أيقونات font-awesome بهذه الطريقة باستخدام ريكت. فعند استخدامك لهذه المكتبة في تطبيق ريكت يجب عليك إحضار الأيقونات على شكل Component كما وعليك استدعاء الملفات الخاصة به من حزمة الـ node_modules. فمثلًا يمكنك استدعاء الأيقونة التي ذكرت باستخدام هذه الطريقة. أولًا عليك استدعاء المكون FontAwesomeIcon من خلال الكود التالي: import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ومن ثم يجب عليك أيضًا استدعاء الأيقونة التي ترغب من ملف الأيقونات فمثلًا لاستخدام الأيقونة search يمكنك جلبها من مجلد free-solid-svg-icons من خلال هذه الطريقة: import { faSearch } from "@fortawesome/free-solid-svg-icons"; بالنسبة للأيقونة spinner فيمكنك البحث عليها داخل مجلدات fortawesome@ عليها. ومن ثم يمكنك استدعاء هذا الـ component داخل الصفحة باستخدام هذه الطريقة: <!-- ايقونة البحث --> <FontAwesomeIcon icon={faSearch} /> <!-- الايقونة التي تريد بعد استدعائها من ملفها الصحيح --> <FontAwesomeIcon icon={faSpinner} /> بهذه الطريقة يمكنك استدعاء أيقونات هذه المكتبة باستخدام ريكت.1 نقطة
-
للوصول لعدد أيام الشهر 2 أنت تحتاج أيضا للسنة كمتغير يوفره المستخدم وهناك نوعام من السنوات سنة عادية تحتوي على 365 يوم و leap year تحتوي على 366 يوم ال leap year تقبل القسمة على 4 ولا تقبل القسمة على 100 لكن ان كانت تقبل القسمة على 4 و 400 و 100 فهي leap year class CalcNumberOfDays(object): def numberOfDays(self, y, m): leap = 0 if y% 400 == 0: leap = 1 elif y % 100 == 0: leap = 0 elif y% 4 == 0: leap = 1 if m==2: return 28 + leap list = [1,3,5,7,8,10,12] #أرقام الاشهر التي تحتوي على 31 يوم if m in list: return 31 return 30 ob1 = CalcNumberOfDays() y= input("year:") codemon=input("month:") print(ob1.numberOfDays(int(y), int(codemon)))1 نقطة
-
مرحبا أحاول القيام باضافة صورة بداخل عنصر div كنت قد حددت عرضه وطوله ولكن تكون النتيجة أن الصورة أكبر من الحاوية كيف بقدر أجعل الصورة مناسبة للحاوية؟1 نقطة
-
هل يمكن لهذا الكود ان يعاد كتابته بطريقة تكون اكثر تنظيما import React, { useState, useEffect } from 'react'; import axios from 'axios'; export default function App() { const [data, setData] = useState(); useEffect(() => { function getData() { axios.get('http://localhost:5000/posts').then((res) => { setData(res.data); }); } getData(); }, []); return ( <div> {data && data.map((post) => ( <div key={post.id}> <h1>{post.title}</h1> <p>{post.description}</p> </div> ))} </div> ); }1 نقطة
-
نعم. يمكن استخدام Python لبرمجة Arduino ، ببساطة عن طريق استيراد pyfirmata ، والتي يمكنها ربط اردوينو مع Python. يمكنك أن تتعلم من C (AVR) كيفية عمل المستشعرات ولكنها تحتاج إلى مزيد من الوقت للتعلم . لتتمكن من العمل ب Python مع Arduino تتبع الخطوات التالية: - قم بإضافة Firmata على Arduino. - اكتب البرمجة التي تريد بلغة Python. - والان يمكنك التحكم في المدخلات والمخرجات الخاصة بـ Arduino.1 نقطة
-
يجب ان تحدد معنى قيمة اولا لانه في هذه الحالة لا اظنك يجب ان تقلق على null و undefined فقط لذا يجب ان تسأل نفسك هل مثلا string فارغ قيمة مقبولة بالنسبة لك ام لا ويمكنك ان ترى في الكود في الاسفل ماهو truthy وما هو falsy !null //true !undefined //true !" " //false !0 //true هذا يعتمد جدا على ما تريده انت فاذا كنت تريد ان تعطل العنصر في حالة لم يكن المتغير معرف او null فقط فيمكنك عكس قيمته المنطقية <input type="text" disabled={!name} /> لكن ان كنت تريد تعطيله ايضا لما يتواجد عندك string فارغ مثلا ففي هذه الحالة ستقوم بربط سلاسل شرطية بما يناسبك1 نقطة
-
مرحباً @Adam Ebrahim يمكنك فعل ما تريد كالآتي ( إذا كنت تريد props أن تكون dynamic ): const InputComponent = function() { const name = "My Name"; return ( // في هذا الجزء أريد أن يتم حذف الخاصية disable لأن المتغير name يحتوي على قيمة <input type="text" {...(!name && { disabled: true })} /> ); } لاحظ المثال السابق أننا قمنا بإضافة object فيه disabled prop في حالة لا يوجد name وبعد ذلك قمنا بعمل spread للأوبجيكت مع كل ال props1 نقطة