เติมไฟอยู่ที่บ้านกับงาน Firebase Study Jam
ตื่นเต้นสุดๆกับการร่วมงาน Firebase Study Jam ที่บ้านจ้า ในวันอาทิตย์หน้าร้อน 5 เมษายน 2563 ในเวลาบ่ายโมงตรงถึงสามโมง เสร็จปุ๊ปดู Netfilx ต่อ เอ้ยย สรุปบล็อกสิ
ตื่นเต้นขนาดไหน รีบเปิดคอมแต่เช้าแล้วเข้าไปหน้ายูทูปที่สตรีมสดวันนี้หล่ะสิ555555 ซึ่งลิ้งที่สตรีมสดสามารถดูย้อนหลังได้เลยจ้าาา
แน่นอนว่าในงานนี้ไม่มีใครเต้น เจนค่ะ! นุ่นคะ! โบค่ะ! เนอะ 55555555555555
งาน Firebase Study Jam เป็นงานที่จัดขึ้นหลายๆที่บนโลกในนี้ บางประเทศเขาจัดกันต้นปีเนอะ แล้วก็ทยอยๆกันจัดไป และในช่วงก็ COVID-19 ทำให้หลายๆคนต้อง Work From Home เลยเป็นครั้งแรกในไทยที่จัดแบบ online เลยจ้า เป็นการขึ้นเวทีพร้อมกันครั้งแรกของ Firebase GDE ทั้งสองท่าน คือ พี่ตี๋ และคุณนุ้ย โดยขึ้นเวทีพร้อมกันจากที่บ้าน โดยพี่ตี๋อยู่ที่สุราษ และคุณนุ้ยอยู่ที่พิษณุโลกจ้า
แน่นอนว่าบล็อกเราได้สแกนด้วยสายตาคร่าวๆเกี่ยวกับ Tech Stack ที่ใช้ในการสตรีมสดครั้งนี้ Firebase GDE ทั้งสองคน พูดคุยกันผ่าน Hangout Video Call มีการเตรียม Google Slide, link code lab และ Stackblitz, Firebase Console เพื่อแชร์หน้าจอให้พวกเราได้ทำตามกัน และทำการสตรีมสดผ่าน YouTube Live Streaming จ้า หลังจาก streaming เสร็จเราก็จะได้ดูต่อแบบย้อนหลังจ้า
สิ่งที่ทำในวันนี้ ก็คืออออ "Get to know Firebase for Web" เป็นการทำ Web Application ด้วย Firebase ซึ่งคนฟังอย่างเราไม่ต้องเตรียมอะไรมาเลยจ้า เตรียมแค่ใจ และสลับแท็ปให้ทันก็พอหล่ะ (ตอนแรกจะใช้ Sidecar แต่ดันหากันไม่เจอ งงเลยย แงงง) เพราะเราไม่ต้องลง tool หรือ editor ใดๆในวันนี้เลย เราจะทำผ่าน Stachblitz นั่นเอง เป็น online editor ที่เทพมากๆ แบบพิมพ์อะไรไปมันก็จะอัพเดต realtime ให้เราเลยจ้า แล้วก็เขียนเว็บก็จะใช้ HTML และ js จ้าาา เอ้า ลัลลั๊ลลา~ ลัลลัลลั๊ลลา~
แน่นอนว่าหลัง codelab มี surprise ด้วยหล่ะ และช่วงหลังจะมีการทำอาม่า เอ้ยยย AMA คือ Ask Me Anything ถามไรก็ถาม ไม่ต้องเกี่ยวกับ study jam วันนี้ก็ได้จ้า
มาเริ่มกันเถอะนะ
1) มาดูกันก่อน ว่าวันนี้จะได้อะไรกลับไป
ก่อนอื่น ไปที่ url ด้านบน ซึ่งเราจะเสกให้ในด้านล่างนี้ ชะแว้บบบบ
สิ่งที่เราจะได้กลับไปในวันนี้ ก็คืออออ~~ หน้าเว็บ event ที่สามารถกด RSVP ได้ และมี guestbook ด้านล่างจ้า
RSVP มาจากภาษาฝรั่งเศษ ย่อมาจาก Répondez s'il vous plaît แปลเป็นภาษาอังกฤษว่า Please Response หรือในภาษาชาวบ้านคือ โปรดตอบเพื่อ confirm การเชิญในครั้งนี้ เพื่อให้เจ้าของงานนั้นเขาสามารถนับจำนวนคนในการเตรียมงานนั่นเอง
--https://en.wikipedia.org/wiki/RSVP
สิ่งที่จะได้กลับไปในวันนี้คือ
- มีระบบ login เพื่อเข้าร่วมกิจกรรม ผ่าน Firebase Authentication และ FirebaseUI (คืออะไรน้าาา เดี๋ยวอ่านไปจะมีบอกจ้า)
- มีการพิมพ์ comment ใน guestbook แล้วเก็บข้อมูลเข้าไปใน Cloud Firestore
- แน่นอนว่าการเขียน/อ่านข้อมูล เรื่อง Security Rules ก็สำคัญนะ
- deploy web app ขึ้นไปบน Firebase Hosting
2) เริ่มการทำการเขียนโค้ดกันเถอะ
จากนั้นเราก็ clone project ออกมา โดยการกดเข้าไปที่ลิ้งนี้จ้า (ข้างล่างก็อลังการงานสร้างจนงง เหมือนทำผ่านตรงนี้ได้เลยแหะ)
พอเข้าไปแล้วกด fork จ้าเพื่อ clone มาเป็นของเรา เปิดมาเจอ @anonymous
ไม่ต้องตกใจเน้อ เพราะเรายังไม่ได้ login ผ่าน Github นั่นเอง หน้าตาจะประมาณนี้เนอะ
ส่วนประกอบคร่าวๆของเจ้า Stackblitz
- ด้านซ้าย เป็นที่อยู่ชองไฟล์ในโปรเจกเรา ซึ่งจริงๆสามารถสลับไปเป็น Firebase หรืออื่นๆ จะว่าไปหน้าตาคล้าย Visual Studio Code เหมือนกันแหะ
- ตรงกลาง หน้าจอ Editor เอาไว้เขียนโค้ด เอ้อออคล้าย Visual Studio Code อีกหล่ะ
- ด้านขวา ส่วน live preview แบบโค้ดปุ๊ป รันปั๊ป แสดงบัคอย่าง realtime เอ้ยยย แสดงผลแบบ realtime ถ้าพิมพ์ error มันก็ error แบบ realtime เช่นกัน
3) ลองแก้ข้อมูล event กันก่อน ซึ่ง tag ที่แก้ได้ก็มีหลายที่ ไม่ว่าจะเป็นชื่อ event วันที่ สถานที่ รายละเอียด event
ในที่นี้เราจะแก้ section ที่ชื่อว่า event-details-container
โดยเปลี่ยน location_city
เป็น Bangkok, Thailand
จ้า ซึ่งทางนี้ย้อนแก้ wording ทีหลังตอนก่อนส่งการบ้านจ้า
ส่วนนี้เขาต้องการให้เราชินกับ detail ต่างๆใน HTML ก่อนจ้า ว่าอะไรอยู่ไหน แล้วก็เป็นการหัดใช้ Stackblitz ไปในตัวด้วยจ้า
4) สร้างโปรเจก Firebase และเตรียมเชื่อต่อสิ่งต่างๆ
ก่อนอื่นเราสร้าง project Firebase จุดสำคัญ คือ Enable Google Analytics for this project ซะ เพราะเราไม่ได้ใช้ Google Analytics นั่นเอง
จากนั้นไปที่ Firebase Authentication เพื่อ enable email sign-in นั่นเอง
และไปกันต่อที่ Cloud Firestore เพื่อสร้าง database โดย security rules ในตอนนี้เลือกแบบ test mode ไปก่อน เดี๋ยวเราจะแก้ทีหลังน้าาา
อันนี้เน้นยํ้าหนักๆ Cloud Firestore location นั้น หลังจากสร้างแล้วจะเปลี่ยนไม่ได้อีกแล้วนะ ซึ่งทางพี่ตี๋เองก็บอกไปทาง Firebase แล้วเช่นกัน และไม่ใช่ประเทศเราประเทศเราที่อยากจะเปลี่ยน location เลย หลายๆประเทศก็เช่นกัน (ตอนนั้นก็หาวิธีอยู่ตอนที่ลองทำหลังบ้าน พบว่าเปลี่ยน location ของ Cloud Function ได้ แต่ Cloud Firebase ไม่ได้ แล้วเป็น project ที่นานมากแล้วด้วยง่ะ)
เรามีโอกาสเลือกเพียงครั้งเดียว ดังนั้น เราจะเลือก location ที่ใกล้บ้านเรามากที่สุด คือ asia-east2
อยู่ที่ฮ่องกงนั่งเอง (ถ้ามีของสิงคโปรก็เลือกกันไปนานแล้ว แต่นี่ไม่มีงายย) โดยการเลือก location นั้น เราจะพิจารณาจากคนใช้เป็นหลัก เพื่อให้แอพที่เราทำนั้นมีประสิทธิภาพและ performance ดีๆเนอะ
5) มา config ในแอพเรากันเถอะ
กลับไปที่ Stachblitz ไปที่ index.js เพื่อ import ของต่างๆเข้ามา และเราไม่ต้องทำเองด้วยจ้า ในนั้นเขาใส่มาให้พร้อมล้าววว สิ่งที่ต้อง import library ก็จะมี Firebase Authentication, Cloud Firestore และ FirebaseUI ใช้ตอน Authentication ก็คือส่วน login เราไม่ต้องเขียน view ขึ้นมาเอง ใช้
และเพิ่มเว็บเราใน Firebase Project ที่เพิ่งสร้างมะกี้
ใส่ชื่อเล่นของโปรเจกของเราไป และยํ้าหนาๆว่า ยังไม่ต้องติ๊กตรง Also set up Firebase Hosting for this app นะ เพราะเราใช้เจ้า Stachblitz ในการ preview เว็บเรานะ เสร็จแล้วกด Register app
หลังจากนั้น เราจะได้ key มาชุดนึง ไปแปะไว้ใน index.js
ซึ่งทางเขาจะมี comment ไว้ให้เราแปะได้ถูกที่และไม่ล่กจ้า แปะไปดังนี้
และอย่าลืม init Firebase ด้วยนะจ๊ะ
แล้วถ้าลืมก้อปทำไงง่ะ ไปที่ setting > project setting ไปหาแอพของเรา ไปตรง your app จะมี key ต่างๆไว้ตรงน้านจ้า เลือก config เน้อ
6) ทำส่วน Authentication เพื่อ sign in ก่อนกด RSVP โดยการแสดงเจ้า Firebase UI ซึ่งตอนนี้ยังเป็น prebuild library อยู่นะจ๊ะ เพื่อให้ user login โดยที่เราไม่ต้อง coding UI เพิ่มเลย ดีจัง
ก่อนอื่น init มันก่อน ไปที่ index.js
แล้วใส่ส่วนนี้ไว้ล่างสุดเลยจ้า
// Initialize the FirebaseUI widget using Firebase
const ui = new firebaseui.auth.AuthUI(firebase.auth());
ไปที่ index.html
แล้วใส่ปุ่มกันต่อเลยจ้า
<section id="event-details-container">
<!-- ... -->
<!-- ADD THE RSVP BUTTON HERE -->
<button id="startRsvp">RSVP</button>
</section>
และใส่ action ของปุ่มลงไปที่ index.js
// Listen to RSVP button clicks
startRsvpButton.addEventListener("click",
() => {
ui.start("#firebaseui-auth-container", uiConfig);
});
ลองกดดูหน่อยสิตัวเธอ การทำงานพอกดตุ่ม RSVP แล้ว เราสามารถ login เข้าไปในหน้าเว็บได้จ้าา หน้าตาจะประมาณนี้
ความฉลาดของเจ้า Firebase UI ก็คือ ถ้า account ไหนยังไม่ได้ register จะมี form ให้กรอก แบบนี้ๆ
เมื่อเรา register เสร็จแล้ว ไปดูที่ Firebase Authentication ว่า account ของเราสร้างไปหรือยัง และแล้วน้อง account ใหม่ที่เพิ่งสร้างก็มาแล้วว
สมัครเสร็จแล้วยังไงต่อนะ เราต้อง handle เพิ่มนี่นาา เพราะเมื่อกี้กดไปก็ไม่ได้มีอะไรเกิดขึ้นเลยในหน้าเว็บของเรา ใส่ current authentication state เพื่อ check ว่าเรา login อยู่ไหมนะ ไปที่ index.js
ไปลงไปที่ท้ายไฟล์เช่นเคย โดยเรียก onAuthStateChanged
ดังนี้
// Listen to the current Auth state
firebase.auth().onAuthStateChanged((user)=> {
if (user) {
startRsvpButton.textContent = "LOGOUT"
}
else {
startRsvpButton.textContent = "RSVP"
}
});
โดยรวม คือการเปลี่ยน text ของปุ่มตาม state นั่นเอง โดยถ้าเรา login แล้ว ปุ่มจะขึ้นคำว่า LOGOUT และตอนยังไม่ login จะขึ้นว่า RSVP
แต่ยังไม่ถูกเนอะ เพราะถ้าเรากด logout มันก็เป็นการเปลี่ยน state เนอะ เพราะเรา sign out ออกจากระบบ ใส่ condition เพิ่มเสียหน่อยจ้า
// Called when the user clicks the RSVP button
startRsvpButton.addEventListener("click",
() => {
if (firebase.auth().currentUser) {
// User is signed in; allows user to sign out
firebase.auth().signOut();
} else {
// No user is signed in; allows user to sign in
ui.start("#firebaseui-auth-container", uiConfig);
}
});
ลอง logout และ login ใหม่ จะได้แบบนี้
7) ทำส่วน guestbook กันต่อจ้า
data model ของระบบจะเป็นดังนี้
ทบทวนกันหน่อยเน้อ Cloud Firestore นั้นเป็น database แบบ NoSQL มีโครงสร้างแบบ document เนอะ ให้นึกถึงแฟ้มใส่เอกสารนะ
- collection คือ guestbook เสมือนเป็นแฟ้ม
- ส่วน document คือ message เสมือนเป็นเอกสารในแฟ้ม
- แต่ละ field ของ document เสมือนข้อความในเอกสารนั้นๆ มี name, text, timestamp, และ userId โดย name และ UserId นั้นได้มาจากตอน create account นั่นเอง
ถ้าอยากอ่านเกี่ยวกับ Cloud Firestore เพิ่ม ลองอ่าน use case ของเราได้จ้า
จากนั้นทำการเตรียม write data ลงคุณ Cloud Firestore กันต่อ ไปที่ index.html
แล้วหา section ที่ชื่อว่า guestbook-container
เพื่อเพิ่ม view ในส่วน guestbook ดังนี้
<section id="guestbook-container">
<h2>Discussion</h2>
<form id="leave-message">
<label>Leave a message: </label>
<input type="text" id="message">
<button type="submit">
<i class="material-icons">send</i>
<span>SEND</span>
</button>
</form>
</section>
พอได้หน้าตามาแล้ว ไป handle ปุ่มส่งข้อความกันต่อเลยจ้า ด้วย addEventListener
ที่ index.js
// Listen to the form submission
form.addEventListener("submit", (e) => {
// Prevent the default form redirect
e.preventDefault();
// Write a new message to the database collection "guestbook"
firebase.firestore().collection("guestbook").add({
text: input.value,
timestamp: Date.now(),
name: firebase.auth().currentUser.displayName,
userId: firebase.auth().currentUser.uid
})
// clear message input field
input.value = "";
// Return false to avoid redirect
return false;
});
เมื่อกดปุ่มแล้ว ข้อความที่เราพิมพ์ไป จะถูกเขียนใน collection ที่ชื่อว่า guestbook โดยเพิ่ม field ต่างๆ คือ text เป็นข้อความที่เราพิมพ์ไป timestamp ส่งเวลาตอนนี้ไป ส่วน name และ timestamp ส่งจาก user ของเราที่ login ผ่าน Firebase Authentication ไป เมื่อเพิ่มข้อมูลไปยัง Cloud Firestore เสร็จแล้ว ทำการเคลียร input ซะ
แน่นอนว่าส่วน guestbook จะให้คนมาพิมพ์ใส่ได้ เมื่อ user คนนั้น login เข้ามาในระบบแล้วเท่านั้น (ไม่งั้นจะพังเนอะ เพราะส่ง name กับ userId ไปด้วย) ดังนั้นเราจะต้องทำการซ่อน view นี้เมื่อ user ไม่ได้ login ใน onAuthStateChanged
แบบนี้
// Listen to the current Auth state
firebase.auth().onAuthStateChanged((user) => {
if (user){
startRsvpButton.textContent = "LOGOUT";
// Show guestbook to logged-in users
guestbookContainer.style.display = "block";
}
else{
startRsvpButton.textContent = "RSVP";
// Hide guestbook for non-logged-in users
guestbookContainer.style.display = "none";
}
});
ลองกดส่งข้อความดูสิ
ส่งเสร็จไปไหน ต้องไป Cloud Firestore สิเธอ พบว่าทำงานได้ถูกต้อง ตบมือไป 3 ล้านครั้ง
และเมื่อเรา logout มันต้องไม่มีช่องให้พิมพ์ comment เนอะ แบบนี้
ปล. สำหรับคนที่อาจจะพิมพ์ตามไม่ทันในสตรีมสด หรือลองทำเองแล้วตามไม่ทัน สามารถกดไปดูที่ checkpoint นะจ๊ะ
8) ที่พิมพ์ๆไป เอามาแสดงในหน้าเว็บสิ
เพิ่ม view กันสักนิด ไปที่ index.html
ใน section guestbook-container
เพิ่ม section ที่ชื่อว่า guestbook
ลงไป
<section id="guestbook-container">
<h2>Discussion</h2>
<form><!-- ... --></form>
<section id="guestbook"></section>
</section>
จากนั้นมา implement การแสดงผลใน section ที่ชื่อว่า guestbook
กันต่อ ที่ index.js
เพื่อดึง data ที่มีใน Cloud Firestore ขึ้นมาแสดง
// Create query for messages
firebase.firestore().collection("guestbook")
.orderBy("timestamp","desc")
.onSnapshot((snaps) => {
// Reset page
guestbook.innerHTML = "";
// Loop through documents in database
snaps.forEach((doc) => {
// Create an HTML entry for each document and add it to the chat
const entry = document.createElement("p");
entry.textContent = doc.data().name + ": " + doc.data().text;
guestbook.appendChild(entry);
});
});
ดึง data จาก collection guestbook
โดย order ตามวันล่าสุดลงมา โดยตอนที่ดึงจะ reset data ก่อน แล้ววน loop แสดงชื่อและ comment ขึ้นมาจนครบ แบบนี้
9) ก่อนออกสู่ production อย่าลืมแก้ security rule ก่อนนะจ๊ะ
จำได้ไหม ตอนที่เราสร้าง Cloud Firestore มันจะถามว่าเอา security rule แบบไหน และเราเลือก test mode ไป จำได้เป่าาาาา? ไม่แนะนำให้ใช้ test mode ที่ allow read และ write บน production นะ เพราะคนอื่นเขาสามารถแกะดูได้ว่าเรา config อะไรไว้
เราจะให้ user ที่ login แล้วเท่านั้น สามารถเข้าไปเขียน guestbook ได้ ดังนั้นเราใส่ match /databases/{database}/documents
ลงไป โดยคนที่อ่านได้ คือทุกคนที่ login แล้ว และคนที่เข้าไปเขียนได้ คือ user คนนั้นๆนั่นเอง สรุป คนอื่นที่ login อ่านได้หมด แต่เจ้าของข้อความเป็นคนเขียนเอง
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /guestbook/{entry} {
allow read: if request.auth.uid != null;
allow write:
if request.auth.uid == request.resource.data.userId;
}
}
}
และเพิ่มความมั่นใจกันสักนิด นอกจากจะ check userId แล้ว ยัง check name, text แบะ timestamp ด้วยเพื่อ make sure จ้า
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /guestbook/{entry} {
allow read: if request.auth.uid != null;
allow write:
if request.auth.uid == request.resource.data.userId
&& "name" in request.resource.data
&& "text" in request.resource.data
&& "timestamp" in request.resource.data;
}
}
}
จากนั้นทำการ reset listener มี best practice บอกไว้ว่าาาา เมื่อเรา add listener ไปแล้ว เราควร unsubscription เพื่อไม่ให้ทำงานไปเรื่อยๆให้เปลือง bandwidth จ้า
ดังนั้นไปสร้าง function ที่ index.js โดยตอนนี้สร้าง 2 function คือ subscribeGuestbook()
เพื่อ update message ใน guestbook
// Listen to guestbook updates
function subscribeGuestbook(){
// Create query for messages
guestbookListener = firebase.firestore().collection("guestbook")
.orderBy("timestamp","desc")
.onSnapshot((snaps) => {
// Reset page
guestbook.innerHTML = "";
// Loop through documents in database
snaps.forEach((doc) => {
// Create an HTML entry for each document and add it to the chat
const entry = document.createElement("p");
entry.textContent = doc.data().name + ": " + doc.data().text;
guestbook.appendChild(entry);
});
});
};
และ unsubscribeGuestbook()
// Unsubscribe from guestbook updates
function unsubscribeGuestbook(){
if (guestbookListener != null)
{
guestbookListener();
guestbookListener = null;
}
};
จากนั้นไปใส่ function ที่เพิ่งสร้างไว้ ไปใส่ใน onAuthStateChanged
firebase.auth().onAuthStateChanged((user) => {
if (user){
startRsvpButton.textContent = "LOGOUT";
// Show guestbook to logged-in users
guestbookContainer.style.display = "block";
// Subscribe to the guestbook collection
subscribeGuestbook();
}
else{
startRsvpButton.textContent = "RSVP";
// Hide guestbook for non-logged-in users
guestbookContainer.style.display = "none";
// Unsubscribe from the guestbook collection
unsubscribeGuestbook();
}
});
10) deploy บน Firebase Hosting เสียที ซึ่งใน Stackblitz เขาก็จัดการให้เราแล้วหล่ะ
ก่อนอื่น login github ก่อน ซึ่งเมลล์ที่ใช้ใน github นั้น จะต้องตรงกับเมลล์ที่ใช้ใน Firebase ที่เราสร้าง project กันไปเมื่อกี้น้าาาา
กดไปที่แท็ป Firebase เพื่อ Sign in เข้า Firebase จากนั้นเลือก project ของเราที่เพิ่งสร้างไปมะกี้
เมื่อเลือกโปรเจกเรียบร้อยจะมีปุ่มเชื้อเชิญมาบอกเราว่า deploy ฉันสิ~
จากนั้นก็นับหนึ่งถึงสามไม่ล้าน รอให้มัน deploy เสร็จ
จากนั้นกด Open live site ก็จะเจอเว็บที่เราทำๆกันใน Firebase Hosting แล้วจ้า
11) มี bonus ให้เพิ่มเสียหน่อย
เมื่อเราอยากรู้ว่า มีคนจะมา event ของเรากี่คน เราก็ทำปุ่มเพื่อให้สามารถ check จำนวนคนได้ว่า จะมากันกี่คน จะได้เตรียมพิซซ่าและนํ้าอัดลมกันได้ถูก (แบบอินเนอร์คนเคยจัดงาน meetup มาหนึ่งครั้งถ้วน)
เพิ่มปุ่มกันก่อน ไปที่ index.html
หา section guestbook-container
ใส่สิ่งนี้ไว้ด้านบนของ Discussion
<h2>Are you attending?</h2>
<button id="rsvp-yes">YES</button>
<button id="rsvp-no">NO</button>
น้องปุ่มมาแล้ว มา handle ตอนกดปุ่มเพิ่มกันสักหน่อย แน่นอนไปที่ index.js
เนอะ ให้แสดงจำนวนคนโดยมีค่า attending
เป็น true
// Listen for attendee list
firebase.firestore()
.collection('attendees')
.where("attending", "==", true)
.onSnapshot(snap => {
const newAttendeeCount = snap.docs.length;
numberAttending.innerHTML = newAttendeeCount+' people going';
})
อาจจะมีอาการงงๆ คืองี้ เราสร้าง collection ใหม่ขึ้นมาอีกตัวนึงชื่อว่า attendees
เอาไว้เก็บคนที่ตอบรับ และคนนั้นมาหรือไม่มางานนี้เนอะ ตัว document นั้นจะเป็น userId
ของเรานั่นเอง ซึ่งถ้ากด YES ก็จะเขียนค่า attending
เป็น true
// Listen to RSVP responses
rsvpYes.onclick = () => {
// Get a reference to the user's document in the attendees collection
const userDoc = firebase.firestore().collection('attendees').doc(firebase.auth().currentUser.uid);
// If they RSVP'd yes, save a document with attending: true
userDoc.set({
attending: true
}).catch(console.error)
}
ถ้ากด NO ก็จะเขียนค่า attending
เป็น false
rsvpNo.onclick = () => {
// Get a reference to the user's document in the attendees collection
const userDoc = firebase.firestore().collection('attendees').doc(firebase.auth().currentUser.uid);
// If they RSVP'd yes, save a document with attending: true
userDoc.set({
attending: false
}).catch(console.error)
}
ทำไมมันเร็วจังง่ะตอนกดปุ่ม สำหรับคนที่เขาเล่น Cloud Firestore จนพรุนหมดแล้ว เขาจะรู้ว่า เพราะว่ามัน write ใน local ก่อนนั่นเองงงงง~
หน้าตาก็จะประมาณนี้จ้า
และหน้าตาเว็บที่ได้แบบสมบูรณ์พูนผล
12) เรียนจบแล้วไปไหน ในนี้มีการทบทวนและสรุป และเราก็จะได้ badge มาประดับ profile ของเรา สิ่งที่เขาให้มาเพิ่ม คือ codelab Firebase อื่นๆ
และคลิป Cloud Firestore ให้เราไปฟังเพิ่มกันจ้า
ทำเสร็จแล้วยังไงต่อนะ?
พอไปถึง Congratulation ก็จะมี popup เด้งมาว่าให้ Sign in เพื่อรับ badge ซะ แน่นอนว่าขึ้นไวจนทางนี้ แคปรูปไม่ทันจ้า แงงงงงง
เมื่อกดดันจนได้ที่ เอ้ยยย กดปุ่ม Done จะพาไปหน้านี้จ้า
แล้ว badge เราจะเห็นได้ไง ก่อนอื่นกดที่ My Profile ก่อน จะมีให้กรอกชื่อ-สกุล ที่ทำงาน ให้เรียบร้อย แล้วก็เพิ่มรูป จากนั้นเราก็ allow ให้ webcam ถ่ายรูปเรา จากนั้นระบบจะทำการแปลงหน้าเราเป็น avatar ด้วย AI จ้า
เมื่อเรียบร้อยแล้วเราจะได้ avatar ใหม่จากทาง Google เพื่อเอาไปเปลี่ยนรูป profile ใน Facebook เอ้ยยย ได้หน้า My Profile ของเราพร้อม badge ที่เราทำ codelab เมื่อกี้มาเรียบร้อย
และมีกิจกรรมร่วมสนุกคือ ส่งการบ้านโดยการแปะลิ้ง url ของเว็บที่เราทำแล้ว deploy ไปยัง Firebase Hosting และแคปหน้าจอ profile ตัวเองที่มี badge ไปยังลิ้งใต้รูปล่าง ซึ่งผู้ส่งการบ้านครบ 20 คนแรกนั้น จะได้บัตรงาน Firebase Dev Day 2020 ที่จะจัดในปลายปีนี้จ้า อู้ววววววว ด้วยความที่เราแคปหลายอย่างเตรียมไว้จดบล็อก เลยส่งการบ้านได้เร็วไวเลยจ้า
และส่ง feedback ให้กับทาง Google ได้ดังนี้จ้า เพื่อให้เรามีกิจกรรมดีๆแบบนี้ในครั้งต่อไปจ้า
บ่ายวันนี้ก็สนุกสนานมาก มีไลฟ์หมุนค้างนิดหน่อย แต่ทีมงานก็แก้ไขได้รวดเร็ว และมีการย้อนไปในตรงที่หลุดด้วยจ้า ช่วงหลังๆมีการบอกว่าพี่ตี๋ไปจิบนํ้าส้มตอนไลฟ์ค้างด้วย แล้วในช่องแชทมีการเล่นมุขโน้นนี่กันด้วย จุดที่ขยี้สุดๆ ก็ตรง เมลล์พี่ตี๋ที่ในไลฟ์ใส่ @hotmail.com แล้วพี่เอกบอกว่าเมลล์แรกของพี่ตี๋น่าจะ @chaiyo.com มากกว่า เอ่อออ เราไม่คุ้นๆเลยอ่าง่า เหมือนเกิดไม่ทันอะค่าาาา (หราาาา) และทางเราตื่นเต้นว่าวันนี้จะได้อะไรกลับไป รู้แต่เขียนเว็บอ่ะวันนี้ ฮ่าๆ
ก่อนจากกัน แอบสงสัยว่าในนั้นมีอะไรให้เล่นอีกไหมนะ เข้าใจว่าน่าจะเป็นเว็บ codelab แบบใหม่ ฉบับ beta นะเออ แล้วฝั่ง Android มีอะไรให้เล่นบ้างนะ
ไส้ในแต่ละ pathways จะมี codelab ย่อยๆ แตกต่างกันไปในแต่ละเนื้อหา
กดไปดูพบว่าข้างในจะเป็น codelab เดิม อย่างอันนี้เป็น Material Design ด้วย Kotlin
ท้ายสุด รู้อะไรไม่สู้ลงมือทำจ้า เพราะหลายอย่างเราก็ไม่เคยทำจริงๆนะ ฮ่าาาๆๆ
ปล. สรุปบล็อกดันนานกว่าทำใน study jam อีกง่าาาาา
สุดท้ายฝากร้านกันสักนิด ฝากเพจด้วยนะจ๊ะ