Firebase Angular Web Frameworks Codelab

1. आपको क्या बनाना है

इस कोडलैब में, आपको यात्रा से जुड़ा एक ब्लॉग बनाना है. इसमें रीयल-टाइम में साथ मिलकर काम करने की सुविधा वाला मैप शामिल होगा. इसके लिए, आपको हमारी Angular लाइब्रेरी AngularFire का इस्तेमाल करना होगा. फ़ाइनल वेब ऐप्लिकेशन में एक ट्रैवल ब्लॉग होगा. इसमें, उन सभी जगहों की इमेज अपलोड की जा सकेंगी जहां आपने यात्रा की है.

वेब ऐप्लिकेशन बनाने के लिए AngularFire का इस्तेमाल किया जाएगा. साथ ही, स्थानीय टेस्टिंग के लिए Emulator Suite, उपयोगकर्ता के डेटा को ट्रैक करने के लिए Authentication, डेटा और मीडिया को बनाए रखने के लिए Firestore और Storage, Cloud Functions की मदद से काम करने वाले फ़ंक्शन, और आखिर में ऐप्लिकेशन को डिप्लॉय करने के लिए Firebase Hosting का इस्तेमाल किया जाएगा.

आपको क्या सीखने को मिलेगा

  • Emulator Suite की मदद से, Firebase प्रॉडक्ट को स्थानीय तौर पर डेवलप करने का तरीका
  • AngularFire की मदद से, अपने वेब ऐप्लिकेशन को बेहतर बनाने का तरीका
  • Firestore में डेटा को सेव करने का तरीका
  • मीडिया को स्टोरेज में सेव रखने का तरीका
  • अपने ऐप्लिकेशन को Firebase Hosting पर डिप्लॉय करने का तरीका
  • अपने डेटाबेस और एपीआई के साथ इंटरैक्ट करने के लिए, Cloud Functions का इस्तेमाल कैसे करें

आपको इनकी ज़रूरत होगी

  • Node.js का वर्शन 10 या इसके बाद का वर्शन
  • Firebase प्रोजेक्ट बनाने और उसे मैनेज करने के लिए Google खाता
  • Firebase CLI का 11.14.2 या इसके बाद का वर्शन
  • अपनी पसंद का ब्राउज़र, जैसे कि Chrome
  • Angular और JavaScript की बुनियादी जानकारी

2. सैंपल कोड पाना

कमांड लाइन से, कोडलैब की GitHub रिपॉज़िटरी को क्लोन करें:

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

इसके अलावा, अगर आपने git इंस्टॉल नहीं किया है, तो रिपॉज़िटरी को ZIP फ़ाइल के तौर पर डाउनलोड करें.

GitHub रिपॉज़िटरी में, कई प्लैटफ़ॉर्म के लिए सैंपल प्रोजेक्ट शामिल होते हैं.

इस कोडलैब में सिर्फ़ webframework रिपॉज़िटरी का इस्तेमाल किया जाता है:

  • 📁 webframework: यह शुरुआती कोड है, जिसे आपको इस कोडलैब के दौरान बनाना है.

डिपेंडेंसी इंस्टॉल करना

क्लोन करने के बाद, वेब ऐप्लिकेशन बनाने से पहले, रूट और functions फ़ोल्डर में डिपेंडेंसी इंस्टॉल करें.

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

Firebase CLI इंस्टॉल करना

टर्मिनल में इस कमांड का इस्तेमाल करके, Firebase CLI इंस्टॉल करें:

npm install -g firebase-tools

दोबारा जांच करें कि Firebase CLI का वर्शन 11.14.2 से ज़्यादा है. इसके लिए, यह कमांड इस्तेमाल करें:

firebase  --version

अगर आपके ऐप्लिकेशन का वर्शन 11.14.2 से पहले का है, तो कृपया इसे अपडेट करें. इसके लिए, इनमें से किसी एक तरीके का इस्तेमाल करें:

npm update firebase-tools

3. Firebase प्रोजेक्ट बनाना और उसे सेट अप करना

Firebase प्रोजेक्ट बनाना

  1. अपने Google खाते का इस्तेमाल करके, Firebase कंसोल में साइन इन करें.
  2. नया प्रोजेक्ट बनाने के लिए, बटन पर क्लिक करें. इसके बाद, प्रोजेक्ट का नाम डालें. उदाहरण के लिए, FriendlyChat.
  3. जारी रखें पर क्लिक करें.
  4. अगर आपसे कहा जाए, तो Firebase की शर्तें पढ़ें और स्वीकार करें. इसके बाद, जारी रखें पर क्लिक करें.
  5. (ज़रूरी नहीं) Firebase कंसोल में एआई की मदद पाने की सुविधा चालू करें. इसे "Firebase में Gemini" कहा जाता है.
  6. इस कोडलैब के लिए, आपको Google Analytics की ज़रूरत नहीं है. इसलिए, Google Analytics के विकल्प को टॉगल करके बंद करें.
  7. प्रोजेक्ट बनाएं पर क्लिक करें. इसके बाद, प्रोजेक्ट के प्रोविज़न होने का इंतज़ार करें. इसके बाद, जारी रखें पर क्लिक करें.

प्रोजेक्ट में Firebase वेब ऐप्लिकेशन जोड़ना

  1. नया Firebase वेब ऐप्लिकेशन बनाने के लिए, वेब आइकॉन पर क्लिक करें.
  2. अगले चरण में, आपको कॉन्फ़िगरेशन ऑब्जेक्ट दिखेगा. इस ऑब्जेक्ट के कॉन्टेंट को environments/environment.ts फ़ाइल में कॉपी करें.

Firebase प्रॉडक्ट सेट अप करना

हम जिस ऐप्लिकेशन को बनाने जा रहे हैं वह वेब ऐप्लिकेशन के लिए उपलब्ध Firebase प्रॉडक्ट का इस्तेमाल करता है:

  • Firebase Authentication की मदद से, उपयोगकर्ताओं को आसानी से अपने ऐप्लिकेशन में साइन इन करने की अनुमति दें.
  • क्लाउड पर स्ट्रक्चर्ड डेटा सेव करने के लिए Cloud Firestore का इस्तेमाल करें. साथ ही, डेटा में बदलाव होने पर तुरंत सूचना पाएं.
  • क्लाउड में फ़ाइलें सेव करने के लिए, Firebase के लिए Cloud Storage का इस्तेमाल करें.
  • अपनी ऐसेट को होस्ट और डिलीवर करने के लिए, Firebase Hosting का इस्तेमाल करें.
  • इंटरनल और बाहरी एपीआई के साथ इंटरैक्ट करने के लिए फ़ंक्शन.

इनमें से कुछ प्रॉडक्ट के लिए खास कॉन्फ़िगरेशन की ज़रूरत होती है. इसके अलावा, इन्हें Firebase कंसोल का इस्तेमाल करके चालू करना होता है.

Google sign-in for Firebase Authentication की सुविधा चालू करना

हम उपयोगकर्ताओं को उनके Google खातों से वेब ऐप्लिकेशन में साइन इन करने की अनुमति देने के लिए, Google साइन-इन करने के तरीके का इस्तेमाल करेंगे.

Google साइन-इन की सुविधा चालू करने के लिए:

  1. Firebase कंसोल में, बाएं पैनल में मौजूद Build सेक्शन पर जाएं.
  2. पुष्टि पर क्लिक करें. इसके बाद, साइन-इन करने का तरीका टैब पर क्लिक करें. इसके अलावा, सीधे इस टैब पर जाने के लिए यहां क्लिक करें.
  3. Google साइन-इन की सुविधा देने वाली कंपनी को चालू करें. इसके बाद, सेव करें पर क्लिक करें.
  4. अपने ऐप्लिकेशन का नाम <your-project-name> के तौर पर सेट करें. साथ ही, ड्रॉपडाउन मेन्यू से प्रोजेक्ट के लिए सहायता ईमेल पता चुनें.

Cloud Firestore चालू करना

  1. Firebase कंसोल के बनाएं सेक्शन में, Firestore डेटाबेस पर क्लिक करें.
  2. Cloud Firestore विंडो में, डेटाबेस बनाएं पर क्लिक करें.
  3. वह जगह सेट करें जहां आपका Cloud Firestore डेटा सेव किया जाता है. इसे डिफ़ॉल्ट के तौर पर छोड़ा जा सकता है या अपने आस-पास का कोई इलाका चुना जा सकता है.

Cloud Storage चालू करना

यह वेब ऐप्लिकेशन, Cloud Storage for Firebase का इस्तेमाल करके फ़ोटो को सेव, अपलोड, और शेयर करता है.

  1. Firebase कंसोल के बनाएं सेक्शन में, Storage पर क्लिक करें.
  2. अगर शुरू करें बटन नहीं दिखता है, तो इसका मतलब है कि क्लाउड स्टोरेज पहले से ही

चालू है, तो आपको यहां दिया गया तरीका अपनाने की ज़रूरत नहीं है.

  1. शुरू करें पर क्लिक करें.
  2. अपने Firebase प्रोजेक्ट के लिए सुरक्षा नियमों के बारे में डिसक्लेमर पढ़ें. इसके बाद, आगे बढ़ें पर क्लिक करें.
  3. Cloud Storage की जगह पहले से ही उस क्षेत्र के हिसाब से चुनी जाती है जिसे आपने Cloud Firestore डेटाबेस के लिए चुना था. सेटअप पूरा करने के लिए, हो गया पर क्लिक करें.

डिफ़ॉल्ट सुरक्षा नियमों के तहत, पुष्टि किया गया कोई भी उपयोगकर्ता Cloud Storage में कुछ भी लिख सकता है. हम इस कोडलैब में बाद में अपने स्टोरेज को ज़्यादा सुरक्षित बनाएंगे.

4. अपने Firebase प्रोजेक्ट से कनेक्ट करना

Firebase कमांड-लाइन इंटरफ़ेस (सीएलआई) की मदद से, Firebase होस्टिंग का इस्तेमाल करके अपने वेब ऐप्लिकेशन को स्थानीय तौर पर दिखाया जा सकता है. साथ ही, अपने वेब ऐप्लिकेशन को Firebase प्रोजेक्ट में डिप्लॉय किया जा सकता है.

पक्का करें कि आपकी कमांड लाइन, आपके ऐप्लिकेशन की लोकल webframework डायरेक्ट्री को ऐक्सेस कर रही हो.

वेब ऐप्लिकेशन के कोड को अपने Firebase प्रोजेक्ट से कनेक्ट करें. सबसे पहले, कमांड लाइन में Firebase CLI में लॉग इन करें:

firebase login

इसके बाद, प्रोजेक्ट का उपनाम बनाने के लिए यह कमांड चलाएं. $YOUR_PROJECT_ID की जगह अपने Firebase प्रोजेक्ट का आईडी डालें.

firebase  use  $YOUR_PROJECT_ID

AngularFire जोड़ना

ऐप्लिकेशन में AngularFire जोड़ने के लिए, यह कमांड चलाएं:

ng add @angular/fire

इसके बाद, कमांड लाइन के निर्देशों का पालन करें और वे सुविधाएं चुनें जो आपके Firebase प्रोजेक्ट में मौजूद हैं.

Firebase को चालू करना

Firebase प्रोजेक्ट को शुरू करने के लिए, यह कमांड चलाएं:

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! मैसेज दिखने का मतलब है कि अब इम्यूलेटर इस्तेमाल किए जा सकते हैं.

आपको अपने ट्रैवल ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) दिखेगा. हालांकि, यह अभी काम नहीं कर रहा है:

अब चलिए, बनाना शुरू करते हैं!

5. वेब ऐप्लिकेशन को एम्युलेटर से कनेक्ट करना

एम्युलेटर लॉग में मौजूद टेबल के हिसाब से, Cloud Firestore Emulator पोर्ट 8080 पर और Authentication Emulator पोर्ट 9099 पर सिग्नल पाने के लिए कॉन्फ़िगर किया गया है.

EmulatorUI खोलें

अपने वेब ब्राउज़र में, http://127.0.0.1:4000/ पर जाएं. आपको Emulator Suite का यूज़र इंटरफ़ेस (यूआई) दिखेगा.

ऐप्लिकेशन को इम्यूलेटर इस्तेमाल करने के लिए रूट करें

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;
		}),
		...
	]

अब ऐप्लिकेशन को लोकल एम्युलेटर का इस्तेमाल करने के लिए कॉन्फ़िगर कर दिया गया है. इससे, टेस्टिंग और डेवलपमेंट को स्थानीय तौर पर किया जा सकता है.

6. पुष्टि करने की सुविधा जोड़ना

ऐप्लिकेशन के लिए अब इम्यूलेटर सेट अप हो गए हैं. इसलिए, हम पुष्टि करने की सुविधाएं जोड़ सकते हैं. इससे यह पक्का किया जा सकेगा कि हर उपयोगकर्ता, मैसेज पोस्ट करने से पहले साइन इन करे.

इसके लिए, हम 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);
		})
	}
}

अब लॉगिन पेज काम कर रहा है! लॉग इन करके देखें और पुष्टि करने वाले एम्युलेटर में नतीजे देखें.

7. Firestore को कॉन्फ़िगर करना

इस चरण में, Firestore में सेव की गई यात्रा से जुड़ी ब्लॉग पोस्ट को पोस्ट और अपडेट करने की सुविधा जोड़ी जाएगी.

पुष्टि करने के तरीके की तरह ही, Firestore के फ़ंक्शन AngularFire से पहले से पैकेज किए गए होते हैं. हर दस्तावेज़ किसी कलेक्शन का हिस्सा होता है. साथ ही, हर दस्तावेज़ में नेस्ट किए गए कलेक्शन भी हो सकते हैं. यात्रा से जुड़ी ब्लॉग पोस्ट बनाने और उसे अपडेट करने के लिए, Firestore में दस्तावेज़ का path जानना ज़रूरी है.

TravelService लागू करना

वेब ऐप्लिकेशन में कई अलग-अलग पेजों को Firestore दस्तावेज़ों को पढ़ने और अपडेट करने की ज़रूरत होगी. इसलिए, हम src/app/services/travel.service.ts में फ़ंक्शन लागू कर सकते हैं, ताकि हर पेज पर एक ही AngularFire फ़ंक्शन को बार-बार इंजेक्ट करने से बचा जा सके.

पिछले चरण की तरह ही, हमारी सेवा में 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);

यात्रा से जुड़ी पोस्ट जोड़ना

यात्रा से जुड़ी पोस्ट, Firestore में सेव किए गए दस्तावेज़ों के तौर पर मौजूद होंगी. दस्तावेज़ों को कलेक्शन में सेव किया जाता है. इसलिए, यात्रा से जुड़ी सभी पोस्ट वाले कलेक्शन का नाम 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;

	})
}

डेटा अपडेट करना और मिटाना

किसी भी यात्रा पोस्ट के यूआईडी से, Firestore में सेव किए गए दस्तावेज़ के पाथ का पता लगाया जा सकता है. इसके बाद, 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})
}

बहुत बढ़िया! Firestore के फ़ंक्शन, 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[]>
}

TravelService को कंस्ट्रक्टर में कॉल किया जाता है, ताकि सभी यात्राओं का Observable कलेक्शन मिल सके.

अगर सिर्फ़ मौजूदा उपयोगकर्ता की यात्राओं की जानकारी चाहिए, तो query फ़ंक्शन का इस्तेमाल करें.

सुरक्षा के लिए अन्य तरीकों में, सुरक्षा नियमों को लागू करना या Firestore के साथ Cloud Functions का इस्तेमाल करना शामिल है. इसके बारे में यहां दिए गए वैकल्पिक चरणों में बताया गया है

इसके बाद, TravelService में लागू किए गए फ़ंक्शन को कॉल करें.

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

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

अब 'मेरी यात्राएं' पेज काम करना चाहिए! जानें कि नई ट्रैवल पोस्ट बनाने पर, Firestore Emulator में क्या होता है.

इसके बाद, /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[]>

}

8. स्टोरेज कॉन्फ़िगर करना

अब आपको इमेज और अन्य तरह के मीडिया को सेव करने के लिए, स्टोरेज का इस्तेमाल करना होगा.

Cloud Firestore का इस्तेमाल, स्ट्रक्चर्ड डेटा को सेव करने के लिए सबसे अच्छा होता है. जैसे, JSON ऑब्जेक्ट. Cloud Storage को फ़ाइलों या ब्लॉब को सेव करने के लिए डिज़ाइन किया गया है. इस ऐप्लिकेशन में, इसका इस्तेमाल लोगों को यात्रा की फ़ोटो शेयर करने की अनुमति देने के लिए किया जाएगा.

इसी तरह, Firestore के साथ Storage का इस्तेमाल करके फ़ाइलों को सेव करने और अपडेट करने के लिए, हर फ़ाइल का यूनीक आइडेंटिफ़ायर होना ज़रूरी है.

आइए, TraveService में फ़ंक्शन लागू करें:

कोई फ़ाइल अपलोड करना

src/app/services/travel.service.ts पर जाएं और AngularFire से स्टोरेज इंजेक्ट करें:

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;
}

Firestore से दस्तावेज़ों और Cloud Storage से फ़ाइलों को ऐक्सेस करने के बीच मुख्य अंतर यह है कि दोनों फ़ोल्डर के स्ट्रक्चर वाले पाथ का इस्तेमाल करते हैं. हालांकि, बेस यूआरएल और पाथ का कॉम्बिनेशन 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);
}

इमेज अपलोड होने पर, मीडिया फ़ाइल को स्टोरेज में अपलोड किया जाएगा. साथ ही, यूआरएल को Firestore में मौजूद दस्तावेज़ में सेव किया जाएगा.

9. ऐप्लिकेशन डिप्लॉय करना

अब हम ऐप्लिकेशन को डिप्लॉय करने के लिए तैयार हैं!

src/environments/environment.ts से src/environments/environment.prod.ts में firebase कॉन्फ़िगरेशन कॉपी करें और यह कमांड चलाएं:

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

10. बधाई हो!

अब आपका ऐप्लिकेशन तैयार हो गया है और इसे Firebase Hosting पर डिप्लॉय कर दिया गया है! अब सभी डेटा और आंकड़े, Firebase कंसोल में ऐक्सेस किए जा सकेंगे.

AngularFire, Functions, और सुरक्षा से जुड़े नियमों के बारे में ज़्यादा जानने के लिए, नीचे दिए गए वैकल्पिक चरण देखें. साथ ही, अन्य Firebase Codelabs भी देखें!

11. ज़रूरी नहीं: AngularFire auth guards

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}},
];

12. ज़रूरी नहीं: सुरक्षा के नियम

Firestore और Cloud Storage, दोनों में सुरक्षा नियमों (क्रमशः firestore.rules और security.rules) का इस्तेमाल किया जाता है. इससे सुरक्षा को लागू करने और डेटा की पुष्टि करने में मदद मिलती है.

फ़िलहाल, Firestore और Storage के डेटा को पढ़ने और लिखने का ऐक्सेस सभी के पास है. हालांकि, आपको यह नहीं चाहिए कि लोग दूसरों की पोस्ट में बदलाव करें! सुरक्षा के नियमों का इस्तेमाल करके, अपने कलेक्शन और दस्तावेज़ों के ऐक्सेस को सीमित किया जा सकता है.

Firestore के नियम

सिर्फ़ पुष्टि किए गए उपयोगकर्ताओं को यात्रा से जुड़ी पोस्ट देखने की अनुमति देने के लिए, 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;
		}
	}
}