ফায়ারবেস কৌণিক ওয়েব ফ্রেমওয়ার্ক কোডল্যাব

১. আপনি যা তৈরি করবেন

এই কোডল্যাবে, আপনি আমাদের অ্যাঙ্গুলার লাইব্রেরির সর্বশেষ সংস্করণ অ্যাঙ্গুলারফায়ার (AngularFire) ব্যবহার করে একটি রিয়েল-টাইম কোলাবোরেটিভ ম্যাপসহ একটি ট্র্যাভেলিং ব্লগ তৈরি করবেন। চূড়ান্ত ওয়েব অ্যাপটিতে একটি ট্র্যাভেল ব্লগ থাকবে, যেখানে আপনি আপনার ভ্রমণ করা প্রতিটি স্থানের ছবি আপলোড করতে পারবেন।

ওয়েব অ্যাপটি তৈরি করতে অ্যাঙ্গুলারফায়ার, লোকাল টেস্টিংয়ের জন্য এমুলেটর স্যুট, ব্যবহারকারীর ডেটার হিসাব রাখতে অথেনটিকেশন, ক্লাউড ফাংশনস দ্বারা চালিত ডেটা ও মিডিয়া সংরক্ষণের জন্য ফায়ারস্টোর ও স্টোরেজ এবং সবশেষে, অ্যাপটি ডেপ্লয় করতে ফায়ারবেস হোস্টিং ব্যবহার করা হবে।

আপনি যা শিখবেন

  • এমুলেটর স্যুট ব্যবহার করে স্থানীয়ভাবে ফায়ারবেস প্রোডাক্ট দিয়ে কীভাবে ডেভেলপ করবেন
  • AngularFire দিয়ে আপনার ওয়েব অ্যাপকে কীভাবে আরও উন্নত করবেন
  • ফায়ারস্টোরে আপনার ডেটা কীভাবে স্থায়ী করবেন
  • স্টোরেজে মিডিয়া কীভাবে সংরক্ষণ করবেন
  • আপনার অ্যাপটি ফায়ারবেস হোস্টিং-এ কীভাবে ডেপ্লয় করবেন
  • আপনার ডাটাবেস এবং এপিআই-এর সাথে যোগাযোগ করতে ক্লাউড ফাংশন কীভাবে ব্যবহার করবেন

আপনার যা যা লাগবে

  • Node.js সংস্করণ ১০ বা তার বেশি
  • আপনার ফায়ারবেস প্রজেক্ট তৈরি এবং পরিচালনার জন্য একটি গুগল অ্যাকাউন্ট।
  • ফায়ারবেস সিএলআই সংস্করণ ১১.১৪.২ বা তার পরবর্তী
  • আপনার পছন্দের একটি ব্রাউজার, যেমন ক্রোম
  • অ্যাঙ্গুলার এবং জাভাস্ক্রিপ্ট সম্পর্কে প্রাথমিক ধারণা

২. নমুনা কোডটি নিন।

কমান্ড লাইন থেকে কোডল্যাবের গিটহাব রিপোজিটরিটি ক্লোন করুন:

git clone https://github.com/firebase/codelab-friendlychat-web

বিকল্পভাবে, যদি আপনার গিট ইনস্টল করা না থাকে, তাহলে আপনি রিপোজিটরিটি একটি জিপ ফাইল হিসেবে ডাউনলোড করতে পারেন।

গিটহাব রিপোজিটরিটিতে একাধিক প্ল্যাটফর্মের জন্য নমুনা প্রজেক্ট রয়েছে।

এই কোডল্যাবটি শুধুমাত্র ওয়েবফ্রেমওয়ার্ক রিপোজিটরি ব্যবহার করে:

  • 📁 ওয়েবফ্রেমওয়ার্ক : এটি হলো প্রাথমিক কোড, যার উপর ভিত্তি করে আপনি এই কোডল্যাবটি তৈরি করবেন।

নির্ভরতা ইনস্টল করুন

ক্লোন করার পর, ওয়েব অ্যাপটি বিল্ড করার আগে রুট এবং functions ফোল্ডারে ডিপেন্ডেন্সিগুলো ইনস্টল করুন।

cd webframework && npm install
cd functions && npm install

ফায়ারবেস সিএলআই ইনস্টল করুন

টার্মিনালে এই কমান্ডটি ব্যবহার করে Firebase CLI ইনস্টল করুন:

npm install -g firebase-tools

নিম্নলিখিত কমান্ড ব্যবহার করে পুনরায় যাচাই করুন যে আপনার Firebase CLI সংস্করণটি 11.14.2-এর চেয়ে বেশি।

firebase  --version

আপনার ভার্সন যদি 11.14.2-এর চেয়ে কম হয়, তাহলে অনুগ্রহ করে নিম্নলিখিত পদ্ধতি ব্যবহার করে আপডেট করুন:

npm update firebase-tools

৩. একটি ফায়ারবেস প্রজেক্ট তৈরি ও সেট আপ করুন।

একটি ফায়ারবেস প্রজেক্ট তৈরি করুন

  1. আপনার গুগল অ্যাকাউন্ট ব্যবহার করে ফায়ারবেস কনসোলে সাইন ইন করুন।
  2. নতুন প্রজেক্ট তৈরি করতে বাটনটিতে ক্লিক করুন এবং তারপর একটি প্রজেক্টের নাম লিখুন (যেমন, FriendlyChat )।
  3. চালিয়ে যান-এ ক্লিক করুন।
  4. অনুরোধ করা হলে, Firebase-এর শর্তাবলী পর্যালোচনা করে গ্রহণ করুন এবং তারপর 'চালিয়ে যান' (Continue ) বোতামে ক্লিক করুন।
  5. (ঐচ্ছিক) Firebase কনসোলে AI সহায়তা সক্রিয় করুন (Firebase-এ এটিকে "Gemini" বলা হয়)।
  6. এই কোডল্যাবের জন্য আপনার গুগল অ্যানালিটিক্স-এর প্রয়োজন নেই , তাই গুগল অ্যানালিটিক্স অপশনটি বন্ধ করে দিন
  7. Create project-এ ক্লিক করুন, আপনার প্রজেক্টটি প্রস্তুত হওয়া পর্যন্ত অপেক্ষা করুন, এবং তারপর Continue-তে ক্লিক করুন।

প্রজেক্টে একটি ফায়ারবেস ওয়েব অ্যাপ যোগ করুন

  1. নতুন ফায়ারবেস ওয়েব অ্যাপ তৈরি করতে ওয়েব আইকনে ক্লিক করুন।
  2. পরবর্তী ধাপে, আপনি একটি কনফিগারেশন অবজেক্ট দেখতে পাবেন। এই অবজেক্টের বিষয়বস্তু environments/environment.ts ফাইলে কপি করুন।

ফায়ারবেস পণ্য সেট আপ করুন

আমরা যে অ্যাপ্লিকেশনটি তৈরি করতে যাচ্ছি, তাতে ফায়ারবেসের সেইসব প্রোডাক্ট ব্যবহার করা হয়েছে যা ওয়েব অ্যাপের জন্য উপলব্ধ:

  • আপনার ব্যবহারকারীদের অ্যাপে সহজে সাইন ইন করার জন্য ফায়ারবেস অথেনটিকেশন
  • ক্লাউডে স্ট্রাকচার্ড ডেটা সংরক্ষণ করতে এবং ডেটা পরিবর্তিত হলে তাৎক্ষণিক বিজ্ঞপ্তি পেতে ক্লাউড ফায়ারস্টোর ব্যবহার করুন।
  • ক্লাউডে ফাইল সংরক্ষণ করার জন্য ফায়ারবেসের ক্লাউড স্টোরেজ
  • আপনার অ্যাসেটসমূহ হোস্ট ও পরিবেশন করার জন্য ফায়ারবেস হোস্টিং
  • অভ্যন্তরীণ এবং বাহ্যিক এপিআই-এর সাথে যোগাযোগের ফাংশনসমূহ

এই পণ্যগুলোর কয়েকটির জন্য বিশেষ কনফিগারেশন প্রয়োজন হয় অথবা ফায়ারবেস কনসোল ব্যবহার করে সেগুলোকে সক্রিয় করতে হয়।

ফায়ারবেস অথেনটিকেশনের জন্য গুগল সাইন-ইন সক্রিয় করুন

ব্যবহারকারীদের তাদের গুগল অ্যাকাউন্ট দিয়ে ওয়েব অ্যাপে সাইন ইন করার সুযোগ দিতে, আমরা গুগল সাইন-ইন পদ্ধতি ব্যবহার করব।

গুগল সাইন-ইন সক্রিয় করতে:

  1. Firebase কনসোলের বাম প্যানেলে Build সেকশনটি খুঁজুন।
  2. Authentication-এ ক্লিক করুন, তারপর Sign-in method ট্যাবে ক্লিক করুন (অথবা সরাসরি সেখানে যেতে এখানে ক্লিক করুন )।
  3. গুগল সাইন-ইন প্রদানকারীকে সক্রিয় করুন, তারপর সেভ-এ ক্লিক করুন।
  4. আপনার অ্যাপের পাবলিক নাম <আপনার-প্রকল্পের-নাম> হিসেবে সেট করুন এবং ড্রপডাউন মেনু থেকে একটি প্রকল্প সহায়তার ইমেল বেছে নিন।

ক্লাউড ফায়ারস্টোর সক্রিয় করুন

  1. Firebase কনসোলের Build সেকশনে, Firestore Database- এ ক্লিক করুন।
  2. ক্লাউড ফায়ারস্টোর প্যানে Create database- এ ক্লিক করুন।
  3. আপনার ক্লাউড ফায়ারস্টোর ডেটা কোথায় সংরক্ষিত হবে, সেই অবস্থানটি নির্ধারণ করুন। আপনি এটিকে ডিফল্ট হিসাবে রাখতে পারেন অথবা আপনার কাছাকাছি কোনো অঞ্চল বেছে নিতে পারেন।

ক্লাউড স্টোরেজ সক্রিয় করুন

ওয়েব অ্যাপটি ছবি সংরক্ষণ, আপলোড এবং শেয়ার করার জন্য ক্লাউড স্টোরেজ ফর ফায়ারবেস ব্যবহার করে।

  1. Firebase কনসোলের Build সেকশনে, Storage-এ ক্লিক করুন।
  2. যদি ‘Get Started’ বাটন না থাকে, তার মানে হলো ক্লাউড স্টোরেজ ইতিমধ্যেই চালু আছে।

সক্রিয় করা আছে, এবং আপনাকে নিচের ধাপগুলো অনুসরণ করতে হবে না।

  1. শুরু করতে ক্লিক করুন।
  2. আপনার Firebase প্রোজেক্টের নিরাপত্তা নিয়মাবলী সম্পর্কিত দাবিত্যাগটি পড়ুন, তারপর Next বাটনে ক্লিক করুন।
  3. আপনার ক্লাউড ফায়ারস্টোর ডেটাবেসের জন্য বেছে নেওয়া অঞ্চলের সাথে ক্লাউড স্টোরেজের অবস্থানটি আগে থেকেই নির্বাচিত থাকে। সেটআপটি সম্পূর্ণ করতে 'সম্পন্ন' (Done ) বোতামে ক্লিক করুন।

ডিফল্ট নিরাপত্তা নিয়ম অনুযায়ী, যেকোনো প্রমাণীকৃত ব্যবহারকারী ক্লাউড স্টোরেজে যেকোনো কিছু লিখতে পারে। আমরা এই কোডল্যাবের পরবর্তী অংশে আমাদের স্টোরেজকে আরও সুরক্ষিত করব।

৪. আপনার ফায়ারবেস প্রজেক্টের সাথে সংযোগ করুন।

ফায়ারবেস কমান্ড-লাইন ইন্টারফেস (CLI) ব্যবহার করে আপনি ফায়ারবেস হোস্টিং-এর মাধ্যমে আপনার ওয়েব অ্যাপ স্থানীয়ভাবে পরিবেশন করতে পারেন, এবং সেইসাথে আপনার ফায়ারবেস প্রজেক্টে ওয়েব অ্যাপটি ডেপ্লয়ও করতে পারেন।

নিশ্চিত করুন যে আপনার কমান্ড লাইন আপনার অ্যাপের স্থানীয় webframework ডিরেক্টরি অ্যাক্সেস করছে।

ওয়েব অ্যাপ কোডটি আপনার ফায়ারবেস প্রজেক্টের সাথে সংযুক্ত করুন। প্রথমে, কমান্ড লাইনে ফায়ারবেস সিএলআই-তে লগ ইন করুন:

firebase login

এরপর একটি প্রজেক্ট অ্যালিয়াস তৈরি করতে নিচের কমান্ডটি চালান। $YOUR_PROJECT_ID জায়গায় আপনার ফায়ারবেস প্রজেক্টের আইডি বসান।

firebase  use  $YOUR_PROJECT_ID

AngularFire যোগ করুন

অ্যাপে AngularFire যোগ করতে, এই কমান্ডটি চালান:

ng add @angular/fire

এরপর, কমান্ড লাইনের নির্দেশাবলী অনুসরণ করুন এবং আপনার ফায়ারবেস প্রজেক্টে বিদ্যমান ফিচারগুলো নির্বাচন করুন।

ফায়ারবেস শুরু করুন

ফায়ারবেস প্রজেক্টটি চালু করতে, চালান:

firebase init

এরপর, কমান্ড লাইন নির্দেশাবলী অনুসরণ করে আপনার Firebase প্রজেক্টে ব্যবহৃত ফিচার ও এমুলেটরগুলো নির্বাচন করুন।

এমুলেটরগুলো চালু করুন

webframework ডিরেক্টরি থেকে এমুলেটরগুলো চালু করতে নিম্নলিখিত কমান্ডটি চালান:

firebase  emulators:start

অবশেষে আপনি এইরকম কিছু দেখতে পাবেন:

$  firebase  emulators:start

i  emulators:  Starting  emulators:  auth,  functions,  firestore,  hosting,  functions

i  firestore:  Firestore  Emulator  logging  to  firestore-debug.log

i  hosting:  Serving  hosting  files  from:  public

  hosting:  Local  server:  http://localhost:5000

i  ui:  Emulator  UI  logging  to  ui-debug.log

i  functions:  Watching  "/functions"  for  Cloud  Functions...

  functions[updateMap]:  firestore  function  initialized.

  

┌─────────────────────────────────────────────────────────────┐

    All  emulators  ready!  It  is  now  safe  to  connect  your  app.  

  i  View  Emulator  UI  at  http://localhost:4000  

└─────────────────────────────────────────────────────────────┘

  

┌────────────────┬────────────────┬─────────────────────────────────┐

  Emulator    Host:Port    View  in  Emulator  UI  

├────────────────┼────────────────┼─────────────────────────────────┤

  Authentication    localhost:9099    http://localhost:4000/auth  

├────────────────┼────────────────┼─────────────────────────────────┤

  Functions    localhost:5001    http://localhost:4000/functions  

├────────────────┼────────────────┼─────────────────────────────────┤

  Firestore    localhost:8080    http://localhost:4000/firestore  

├────────────────┼────────────────┼─────────────────────────────────┤

  Hosting    localhost:5000    n/a  

└────────────────┴────────────────┴─────────────────────────────────┘

Emulator  Hub  running  at  localhost:4400

Other  reserved  ports:  4500

  

Issues?  Report  them  at  https://github.com/firebase/firebase-tools/issues  and  attach  the  *-debug.log  files.

যখন আপনি ✔All emulators ready! বার্তাটি দেখতে পাবেন, তখন এমুলেটরগুলো ব্যবহারের জন্য প্রস্তুত।

আপনার ট্র্যাভেল অ্যাপের UI দেখা উচিত, যা (এখনও!) কাজ করছে না:

এবার নির্মাণ শুরু করা যাক!

৫. ওয়েব অ্যাপটিকে এমুলেটরগুলোর সাথে সংযুক্ত করুন।

এমুলেটর লগের টেবিল অনুসারে, ক্লাউড ফায়ারস্টোর এমুলেটরটি ৮০৮০ পোর্টে এবং অথেনটিকেশন এমুলেটরটি ৯০৯৯ পোর্টে লিসেন করছে।

EmulatorUI খুলুন

আপনার ওয়েব ব্রাউজারে http://127.0.0.1:4000/ -এ যান। আপনি এমুলেটর স্যুট UI দেখতে পাবেন।

অ্যাপটিকে এমুলেটরগুলো ব্যবহার করার জন্য নির্দেশ দিন।

src/app/app.module.ts ফাইলে, AppModule এর ইম্পোর্ট তালিকায় নিম্নলিখিত কোডটি যোগ করুন:

@NgModule({
	declarations: [...],
	imports: [
		provideFirebaseApp(() =>  initializeApp(environment.firebase)),

		provideAuth(() => {
			const  auth = getAuth();
			if (location.hostname === 'localhost') {
				connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings:  true });
			}
			return  auth;
		}),

		provideFirestore(() => {
			const  firestore = getFirestore();
			if (location.hostname === 'localhost') {
				connectFirestoreEmulator(firestore, '127.0.0.1', 8080);
			}
			return  firestore;
		}),

		provideFunctions(() => {
			const  functions = getFunctions();
			if (location.hostname === 'localhost') {
				connectFunctionsEmulator(functions, '127.0.0.1', 5001);
			}
			return  functions;
		}),

		provideStorage(() => {
			const  storage = getStorage();
			if (location.hostname === 'localhost') {
				connectStorageEmulator(storage, '127.0.0.1', 5001);
			}
			return  storage;
		}),
		...
	]

অ্যাপটি এখন স্থানীয় এমুলেটর ব্যবহার করার জন্য কনফিগার করা হয়েছে, ফলে স্থানীয়ভাবে টেস্টিং এবং ডেভেলপমেন্ট করা সম্ভব হবে।

৬. প্রমাণীকরণ যোগ করা

এখন যেহেতু অ্যাপটির জন্য এমুলেটরগুলো সেট আপ করা হয়ে গেছে, আমরা অথেনটিকেশন ফিচার যোগ করতে পারি, যাতে প্রত্যেক ব্যবহারকারী মেসেজ পোস্ট করার আগে সাইন ইন করেন।

এটি করার জন্য, আমরা সরাসরি AngularFire থেকে signin ফাংশনগুলো ইম্পোর্ট করতে পারি এবং authState ফাংশন ব্যবহার করে আপনার ব্যবহারকারীর অথেন্টিকেশন অবস্থা ট্র্যাক করতে পারি। লগইন পেজের ফাংশনগুলো এমনভাবে পরিবর্তন করুন যাতে পেজটি লোড হওয়ার সময় ব্যবহারকারীর অথেন্টিকেশন অবস্থা যাচাই করে।

AngularFire Auth ইনজেক্ট করা

src/app/pages/login-page/login-page.component.ts ফাইলে, @angular/fire/auth থেকে Auth ইম্পোর্ট করুন এবং এটিকে LoginPageComponent এ ইনজেক্ট করুন। Google-এর মতো অথেনটিকেশন প্রোভাইডার এবং signin , signout মতো ফাংশনগুলোও একই প্যাকেজ থেকে সরাসরি ইম্পোর্ট করে অ্যাপে ব্যবহার করা যেতে পারে।

import { Auth, GoogleAuthProvider, signInWithPopup, signOut, user } from  '@angular/fire/auth';

export  class  LoginPageComponent  implements  OnInit {
	private  auth: Auth = inject(Auth);
	private  provider = new  GoogleAuthProvider();
	user$ = user(this.auth);
	constructor() {}  

	ngOnInit(): void {} 

	login() {
		signInWithPopup(this.auth, this.provider).then((result) => {
			const  credential = GoogleAuthProvider.credentialFromResult(result);
			return  credential;
		})
	}

	logout() {
		signOut(this.auth).then(() => {
			console.log('signed out');}).catch((error) => {
				console.log('sign out error: ' + error);
		})
	}
}

এখন লগইন পেজটি কাজ করছে! লগইন করে দেখুন এবং অথেনটিকেশন এমুলেটরে ফলাফলগুলো দেখে নিন।

৭. ফায়ারস্টোর কনফিগার করা

এই ধাপে, আপনি ফায়ারস্টোরে সংরক্ষিত ভ্রমণ ব্লগ পোস্টগুলো পোস্ট এবং আপডেট করার কার্যকারিতা যোগ করবেন।

অথেনটিকেশনের মতোই, ফায়ারস্টোর ফাংশনগুলো অ্যাঙ্গুলারফায়ারের সাথে আগে থেকেই প্যাকেজ করা থাকে। প্রতিটি ডকুমেন্ট একটি কালেকশনের অন্তর্গত, এবং প্রতিটি ডকুমেন্টের ভেতরে নেস্টেড কালেকশনও থাকতে পারে। একটি ট্র্যাভেল ব্লগ পোস্ট তৈরি ও আপডেট করার জন্য ফায়ারস্টোরে ডকুমেন্টটির path জানা আবশ্যক।

ভ্রমণ পরিষেবা বাস্তবায়ন

যেহেতু ওয়েব অ্যাপের বিভিন্ন পেজকে ফায়ারস্টোর ডকুমেন্ট পড়তে ও আপডেট করতে হবে, তাই প্রতিটি পেজে বারবার একই AngularFire ফাংশন ইনজেক্ট করা এড়ানোর জন্য আমরা ফাংশনগুলো src/app/services/travel.service.ts এ ইমপ্লিমেন্ট করতে পারি।

পূর্ববর্তী ধাপের মতোই আমাদের সার্ভিসে Auth এবং Firestore যুক্ত করার মাধ্যমে শুরু করুন। বর্তমান অথেন্টিকেশন স্ট্যাটাস শোনার জন্য একটি অবজার্ভেবল user$ অবজেক্ট সংজ্ঞায়িত করাও উপকারী।

import { doc, docData, DocumentReference, Firestore, getDoc, setDoc, updateDoc, collection, addDoc, deleteDoc, collectionData, Timestamp } from  "@angular/fire/firestore";

export  class  TravelService {
	firestore: Firestore = inject(Firestore);
	auth: Auth = inject(Auth);
	user$ = authState(this.auth).pipe(filter(user  =>  user !== null), map(user  =>  user!));
	router: Router = inject(Router);

একটি ভ্রমণ পোস্ট যোগ করা

ভ্রমণ পোস্টগুলো ফায়ারস্টোরে সংরক্ষিত ডকুমেন্ট হিসেবে থাকবে, এবং যেহেতু ডকুমেন্ট অবশ্যই কালেকশনের মধ্যে থাকতে হয়, তাই সমস্ত ভ্রমণ পোস্ট ধারণকারী কালেকশনটির নাম হবে travels । সুতরাং, যেকোনো ভ্রমণ পোস্টের পাথ হবে travels/

AngularFire-এর addDoc ফাংশন ব্যবহার করে একটি কালেকশনে কোনো অবজেক্ট যুক্ত করা যায়:

async  addEmptyTravel(userId: String) {
	...
	addDoc(collection(this.firestore, 'travels'), travelData).then((travelRef) => {
		collection(this.firestore, `travels/${travelRef.id}/stops`);
		setDoc(travelRef, {... travelData, id:  travelRef.id})
		this.router.navigate(['edit', `${travelRef.id}`]);
		return  travelRef;

	})
}

ডেটা আপডেট এবং মুছে ফেলা

যেকোনো ট্র্যাভেল পোস্টের uid জানা থাকলে, ফায়ারস্টোরে সংরক্ষিত ডকুমেন্টটির পাথ বের করা যায়, যা পরবর্তীতে AngularFire-এর updateFoc এবং deleteDoc ফাংশন ব্যবহার করে পড়া, আপডেট করা বা মুছে ফেলা যায়।

async  updateData(path: string, data: Partial<Travel | Stop>) {
	await  updateDoc(doc(this.firestore, path), data)
}

async  deleteData(path: string) {
	const  ref = doc(this.firestore, path);
	await  deleteDoc(ref)
}

পর্যবেক্ষণযোগ্য হিসেবে ডেটা পড়া

যেহেতু ভ্রমণ পোস্ট এবং পথের বিরতিগুলো তৈরির পরেও পরিবর্তন করা যায়, তাই যেকোনো পরিবর্তনে সাবস্ক্রাইব করার জন্য ডকুমেন্ট অবজেক্টগুলোকে অবজার্ভেবল হিসেবে পাওয়া আরও বেশি সুবিধাজনক হবে। এই কার্যকারিতাটি @angular/fire/firestore এর docData এবং collectionData ফাংশনগুলোর মাধ্যমে প্রদান করা হয়।

getDocData(path: string) {
	return  docData(doc(this.firestore, path), {idField:  'id'}) as  Observable<Travel | Stop>
}

  
getCollectionData(path: string) {
	return  collectionData(collection(this.firestore, path), {idField:  'id'}) as  Observable<Travel[] | Stop[]>
}

একটি ভ্রমণ পোস্টে স্টপ যোগ করা

এখন যেহেতু ভ্রমণ পোস্টের কার্যক্রম চালু হয়ে গেছে, তাই স্টপগুলো নিয়ে ভাবার সময় এসেছে, যা একটি ভ্রমণ পোস্টের উপ-সংগ্রহের অধীনে এইভাবে থাকবে: travels/ /stops/

এটি একটি ভ্রমণ পোস্ট তৈরি করার প্রায় অনুরূপ, তাই নিজে থেকে এটি বাস্তবায়ন করার চ্যালেঞ্জ নিন, অথবা নিচে এর বাস্তবায়ন দেখে নিন:

async  addStop(travelId: string) {
	...
	const  ref = await  addDoc(collection(this.firestore, `travels/${travelId}/stops`), stopData)
	setDoc(ref, {...stopData, id:  ref.id})
}

চমৎকার! Travel সার্ভিসে Firestore ফাংশনগুলো প্রয়োগ করা হয়েছে, তাই এখন আপনি সেগুলোর কার্যকারিতা দেখতে পারেন।

অ্যাপে ফায়ারস্টোর ফাংশন ব্যবহার করা

src/app/pages/my-travels/my-travels.component.ts এ যান এবং এর ফাংশনগুলো ব্যবহার করার জন্য TravelService ইনজেক্ট করুন।

travelService = inject(TravelService);
travelsData$: Observable<Travel[]>;
stopsList$!: Observable<Stop[]>;
constructor() {
	this.travelsData$ = this.travelService.getCollectionData(`travels`) as  Observable<Travel[]>
}

সমস্ত ভ্রমণের একটি Observable অ্যারে পেতে TravelService কনস্ট্রাক্টরে কল করা হয়।

যে ক্ষেত্রে শুধুমাত্র বর্তমান ব্যবহারকারীর ভ্রমণপথের প্রয়োজন, সেখানে query ফাংশনটি ব্যবহার করুন।

নিরাপত্তা নিশ্চিত করার অন্যান্য পদ্ধতির মধ্যে রয়েছে নিরাপত্তা বিধি প্রয়োগ করা, অথবা ফায়ারস্টোরের সাথে ক্লাউড ফাংশন ব্যবহার করা, যা নিচের ঐচ্ছিক ধাপগুলিতে আলোচনা করা হয়েছে।

এরপর, TravelService এ বাস্তবায়িত ফাংশনগুলোকে কল করুন।

async  createTravel(userId: String) {
	this.travelService.addEmptyTravel(userId);
}

deleteTravel(travelId: String) {
	this.travelService.deleteData(`travels/${travelId}`)
}

এখন 'আমার ভ্রমণ' পাতাটি কাজ করার কথা! একটি নতুন ভ্রমণ পোস্ট তৈরি করলে আপনার ফায়ারস্টোর এমুলেটরে কী ঘটে তা দেখে নিন।

তারপর, /src/app/pages/edit-travels/edit-travels.component.ts এ থাকা আপডেট ফাংশনগুলোর জন্য এটি পুনরাবৃত্তি করুন:

travelService: TravelService = inject(TravelService)
travelId = this.activatedRoute.snapshot.paramMap.get('travelId');
travelData$: Observable<Travel>;
stopsData$: Observable<Stop[]>;

constructor() {
	this.travelData$ = this.travelService.getDocData(`travels/${this.travelId}`) as  Observable<Travel>
	this.stopsData$ = this.travelService.getCollectionData(`travels/${this.travelId}/stops`) as  Observable<Stop[]>
}

updateCurrentTravel(travel: Partial<Travel>) {
	this.travelService.updateData(`travels${this.travelId}`, travel)
}

  

updateCurrentStop(stop: Partial<Stop>) {
	stop.type = stop.type?.toString();
	this.travelService.updateData(`travels${this.travelId}/stops/${stop.id}`, stop)
}

  

addStop() {
	if (!this.travelId) return;
	this.travelService.addStop(this.travelId);
}

deleteStop(stopId: string) {
	if (!this.travelId || !stopId) {
		return;
	}
	this.travelService.deleteData(`travels${this.travelId}/stops/${stopId}`)
	this.stopsData$ = this.travelService.getCollectionData(`travels${this.travelId}/stops`) as  Observable<Stop[]>

}

৮. স্টোরেজ কনফিগার করা

এখন আপনি ছবি এবং অন্যান্য ধরনের মিডিয়া সংরক্ষণের জন্য স্টোরেজ ব্যবস্থা চালু করবেন।

ক্লাউড ফায়ারস্টোর JSON অবজেক্টের মতো স্ট্রাকচার্ড ডেটা সংরক্ষণের জন্য সবচেয়ে ভালো। ক্লাউড স্টোরেজ ফাইল বা ব্লব সংরক্ষণের জন্য ডিজাইন করা হয়েছে। এই অ্যাপটিতে, আপনি ব্যবহারকারীদের তাদের ভ্রমণের ছবি শেয়ার করার সুযোগ দিতে এটি ব্যবহার করবেন।

ফায়ারস্টোরের মতোই, স্টোরেজ ব্যবহার করে ফাইল সংরক্ষণ ও আপডেট করার জন্য প্রতিটি ফাইলের একটি অনন্য শনাক্তকারী প্রয়োজন হয়।

চলুন TraveService এ ফাংশনগুলো প্রয়োগ করি:

একটি ফাইল আপলোড করা হচ্ছে

src/app/services/travel.service.ts এ যান এবং AngularFire থেকে Storage ইনজেক্ট করুন:

export  class  TravelService {
firestore: Firestore = inject(Firestore);
auth: Auth = inject(Auth);
storage: Storage = inject(Storage);

এবং আপলোড ফাংশনটি বাস্তবায়ন করুন:

async  uploadToStorage(path: string, input: HTMLInputElement, contentType: any) {
	if (!input.files) return  null
	const  files: FileList = input.files;
		for (let  i = 0; i  <  files.length; i++) {
			const  file = files.item(i);
			if (file) {
				const  imagePath = `${path}/${file.name}`
				const  storageRef = ref(this.storage, imagePath);
				await  uploadBytesResumable(storageRef, file, contentType);
				return  await  getDownloadURL(storageRef);
			}
		}
	return  null;
}

ফায়ারস্টোর থেকে ডকুমেন্ট এবং ক্লাউড স্টোরেজ থেকে ফাইল অ্যাক্সেস করার মধ্যে প্রধান পার্থক্য হলো, যদিও উভয়ই ফোল্ডার-কাঠামোর পথ অনুসরণ করে, বেস ইউআরএল এবং পাথের সংমিশ্রণটি getDownloadURL মাধ্যমে পাওয়া যায়, যা পরবর্তীতে সংরক্ষণ করে ব্যবহার করা যেতে পারে। ফাইল।

অ্যাপে ফাংশনটি ব্যবহার করা

src/app/components/edit-stop/edit-stop.component.ts ফাইলে যান এবং নিম্নলিখিতভাবে আপলোড ফাংশনটি কল করুন:

	async  uploadFile(file: HTMLInputElement, stop: Partial<Stop>) {
	const  path = `/travels/${this.travelId}/stops/${stop.id}`
	const  url = await  this.travelService.uploadToStorage(path, file, {contentType:  'image/png'});
	stop.image = url ? url : '';
	this.travelService.updateData(path, stop);
}

যখন ছবিটি আপলোড করা হবে, তখন মিডিয়া ফাইলটি সরাসরি স্টোরেজে আপলোড হয়ে যাবে এবং ফায়ারস্টোরের ডকুমেন্টে ইউআরএলটি যথাযথভাবে সংরক্ষিত হবে।

৯. অ্যাপ্লিকেশনটি স্থাপন করা

এখন আমরা অ্যাপ্লিকেশনটি ডেপ্লয় করার জন্য প্রস্তুত!

src/environments/environment.ts থেকে firebase কনফিগারেশনগুলো src/environments/environment.prod.ts এ কপি করুন এবং রান করুন:

firebase deploy

আপনার এইরকম কিছু দেখা উচিত:

 Browser application bundle generation complete.
 Copying assets complete.
 Index html generation complete.

=== Deploying to 'friendly-travels-b6a4b'...

i  deploying storage, firestore, hosting
i  firebase.storage: checking storage.rules for compilation errors...
  firebase.storage: rules file storage.rules compiled successfully
i  firestore: reading indexes from firestore.indexes.json...
i  cloud.firestore: checking firestore.rules for compilation errors...
  cloud.firestore: rules file firestore.rules compiled successfully
i  storage: latest version of storage.rules already up to date, skipping upload...
i  firestore: deploying indexes...
i  firestore: latest version of firestore.rules already up to date, skipping upload...
  firestore: deployed indexes in firestore.indexes.json successfully for (default) database
i  hosting[friendly-travels-b6a4b]: beginning deploy...
i  hosting[friendly-travels-b6a4b]: found 6 files in .firebase/friendly-travels-b6a4b/hosting
  hosting[friendly-travels-b6a4b]: file upload complete
  storage: released rules storage.rules to firebase.storage
  firestore: released rules firestore.rules to cloud.firestore
i  hosting[friendly-travels-b6a4b]: finalizing version...
  hosting[friendly-travels-b6a4b]: version finalized
i  hosting[friendly-travels-b6a4b]: releasing new version...
  hosting[friendly-travels-b6a4b]: release complete

  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendly-travels-b6a4b/overview
Hosting URL: https://friendly-travels-b6a4b.web.app

১০. অভিনন্দন!

এখন আপনার অ্যাপ্লিকেশনটি সম্পূর্ণ এবং ফায়ারবেস হোস্টিং-এ ডেপ্লয় করা হয়ে গেছে! এখন থেকে সমস্ত ডেটা এবং অ্যানালিটিক্স আপনার ফায়ারবেস কনসোলে অ্যাক্সেস করা যাবে।

AngularFire, ফাংশন, নিরাপত্তা নিয়ম সম্পর্কিত আরও বৈশিষ্ট্যের জন্য, নীচের ঐচ্ছিক ধাপগুলি এবং অন্যান্য Firebase কোডল্যাবগুলি দেখতে ভুলবেন না!

১১. ঐচ্ছিক: AngularFire অথোরাইজেশন গার্ড

Firebase Authentication-এর পাশাপাশি, AngularFire রাউটগুলিতে অথেনটিকেশন-ভিত্তিক গার্ডও প্রদান করে, যাতে অপর্যাপ্ত অ্যাক্সেস থাকা ব্যবহারকারীদের রিডাইরেক্ট করা যায়। এটি ব্যবহারকারীদের দ্বারা সুরক্ষিত ডেটা অ্যাক্সেস করা থেকে অ্যাপটিকে রক্ষা করতে সাহায্য করে।

src/app/app-routing.module.ts এ, ইম্পোর্ট করুন

import {AuthGuard, redirectLoggedInTo, redirectUnauthorizedTo} from  '@angular/fire/auth-guard'

এরপর আপনি নির্দিষ্ট পৃষ্ঠাগুলিতে ব্যবহারকারীদের কখন এবং কোথায় পুনঃনির্দেশিত করা হবে, তার জন্য ফাংশন নির্ধারণ করতে পারেন:

const  redirectUnauthorizedToLogin = () =>  redirectUnauthorizedTo(['signin']);
const  redirectLoggedInToTravels = () =>  redirectLoggedInTo(['my-travels']);

তারপর সেগুলোকে আপনার রুটগুলোতে যোগ করে দিন:

const  routes: Routes = [
	{path:  '', component:  LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectLoggedInToTravels}},
	{path:  'signin', component:  LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectLoggedInToTravels}},
	{path:  'my-travels', component:  MyTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectUnauthorizedToLogin}},
	{path:  'edit/:travelId', component:  EditTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectUnauthorizedToLogin}},
];

১২. ঐচ্ছিক: নিরাপত্তা নিয়মাবলী

ফায়ারস্টোর এবং ক্লাউড স্টোরেজ উভয়ই নিরাপত্তা জোরদার করতে এবং ডেটা যাচাই করতে নিরাপত্তা নিয়ম (যথাক্রমে firestore.rules এবং security.rules ) ব্যবহার করে।

এই মুহূর্তে, ফায়ারস্টোর এবং স্টোরেজের ডেটা পড়া ও লেখার জন্য উন্মুক্ত অ্যাক্সেস রয়েছে, কিন্তু আপনি নিশ্চয়ই চাইবেন না যে কেউ অন্যদের পোস্ট পরিবর্তন করে দিক! আপনি আপনার কালেকশন এবং ডকুমেন্টগুলোতে অ্যাক্সেস সীমাবদ্ধ করতে সিকিউরিটি রুল ব্যবহার করতে পারেন।

ফায়ারস্টোর নিয়ম

শুধুমাত্র প্রমাণীকৃত ব্যবহারকারীদের ভ্রমণ পোস্ট দেখার অনুমতি দিতে, firestore.rules ফাইলে গিয়ে নিম্নলিখিতটি যোগ করুন:

rules_version  =  '2';
service  cloud.firestore  {
	match  /databases/{database}/travels  {
		allow  read:  if  request.auth.uid  !=  null;
		allow  write:
		if  request.auth.uid  ==  request.resource.data.userId;
	}
}

ডেটা যাচাই করার জন্য নিরাপত্তা নিয়মও ব্যবহার করা যেতে পারে:

rules_version  =  '2';
service  cloud.firestore  {
	match  /databases/{database}/posts  {
		allow  read:  if  request.auth.uid  !=  null;
		allow  write:
		if  request.auth.uid  ==  request.resource.data.userId;
		&&  "author"  in  request.resource.data
		&&  "text"  in  request.resource.data
		&&  "timestamp"  in  request.resource.data;
	}
}

স্টোরেজ নিয়ম

একইভাবে, আমরা storage.rules এ নিরাপত্তা নিয়ম ব্যবহার করে স্টোরেজ ডেটাবেসে অ্যাক্সেস কার্যকর করতে পারি। উল্লেখ্য যে, আরও জটিল যাচাইয়ের জন্য আমরা ফাংশনও ব্যবহার করতে পারি:

rules_version  =  '2';

function  isImageBelowMaxSize(maxSizeMB)  {
	return  request.resource.size  <  maxSizeMB  *  1024  *  1024
		&&  request.resource.contentType.matches('image/.*');
}

 service  firebase.storage  {
	match  /b/{bucket}/o  {
		match  /{userId}/{postId}/{filename}  {
			allow  write:  if  request.auth  !=  null
			&&  request.auth.uid  ==  userId  &&  isImageBelowMaxSize(5);
			allow  read;
		}
	}
}