Skip to content

Commit 6e07e5a

Browse files
committed
frontend: Integrate with Google sign-in and new backend
1 parent 95fde7e commit 6e07e5a

File tree

2 files changed

+178
-55
lines changed

2 files changed

+178
-55
lines changed

frontend/fullstack.js

Lines changed: 128 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,159 @@
11

22
console.log("Fullstack frontend loaded");
33

4-
var images = [
5-
"https://static.wikia.nocookie.net/mlp/images/b/b2/Pinkie_Pie_ID_S4E11.png",
6-
"https://media.karousell.com/media/photos/products/2017/02/02/lego_batman_lobster_figure_1486041715_4eed985e.jpg",
7-
"https://static.dw.com/image/18463014_303.jpg",
8-
"https://static.wikia.nocookie.net/mlp/images/b/b2/Pinkie_Pie_ID_S4E11.png"
9-
]
10-
114
var users = []
5+
var logged_in = null
6+
var h_row1 = null
7+
8+
var copter_img = "https://www.puppentoys.com/WebRoot/ce_es/Shops/940395445/5320/45C4/8DBF/84BC/3270/C0A8/8010/C606/A5935-2.jpg"
9+
var nocopter_img = "http://www.skyblue-pink.com/wp-content/uploads/2013/08/sadbatman.jpg"
1210

1311
function load_copter(){
14-
var copter_img = "https://www.puppentoys.com/WebRoot/ce_es/Shops/940395445/5320/45C4/8DBF/84BC/3270/C0A8/8010/C606/A5935-2.jpg"
15-
var nocopter_img = "http://www.skyblue-pink.com/wp-content/uploads/2013/08/sadbatman.jpg"
1612
row = this.parentElement.parentElement;
17-
copter = Boolean(users[row.id - 1][2]);
18-
console.log(`Loading copter for ${row.id}. Has ponycopter? ${users[row.id - 1][2]}`);
13+
user_id = row.id;
14+
user = users[user_id];
15+
console.log(`Loading copter for user ${user_id}`)
16+
copter = Boolean(user[3]);
1917
var h_img = row.querySelector(".card-image");
2018
h_img.src = copter ? copter_img : nocopter_img;
2119
}
2220

21+
function remove_users(){
22+
var h_list = document.getElementById("user_list");
23+
var rows = h_list.querySelectorAll(".row");
24+
console.log(`Removign users: ${rows}`);
25+
rows.forEach(node => {
26+
console.log(`removing row ${node.id}`);
27+
node.remove();
28+
});
29+
}
30+
2331
function render_users(data){
2432
console.log(`Rendering ${data}`)
33+
2534
var h_list = document.getElementById("user_list");
26-
var h_row1 = document.getElementById("first_row");
35+
if (h_row1 == null) {
36+
h_row1 = document.getElementById("first_row");
37+
}
2738
console.log(`My DOM list: ${h_list}`)
28-
for (i in data){
29-
users[i] = data[i];
30-
[id, n, copter] = data[i];
39+
console.log(`data length: ${data.length} data: ${data}`)
40+
41+
for (var i = 0; i < data.length; i++){
42+
console.log(`Rendering element ${data[i]}\n\n`);
43+
44+
// NOTE: This is very brittle - objects with named keys are better
45+
[id, n, email, copter, access, img] = data[i];
46+
47+
/* Add information from the google profile if this is
48+
the logged in user */
49+
if (logged_in && email == logged_in.getEmail()){
50+
n = logged_in.getName();
51+
img = logged_in.getImageUrl();
52+
// Google has a nice API for resizing images
53+
// from https://developers.google.com/people/image-sizing
54+
img = img.split("=")[0]+"=s300";
55+
}
56+
57+
console.log(`Image: ${img}`)
3158

3259
var cloned_row = h_row1.cloneNode(true);
33-
cloned_row.id = id;
60+
cloned_row.id = i;
3461

3562
var h_title = cloned_row.querySelector(".card-title");
3663
h_title.innerHTML = id.toString() + ". Name: " + n;
37-
64+
3865
var h_img = cloned_row.querySelector(".card-image");
39-
h_img.src = images[id - 1];
66+
h_img.src = img
4067

4168
var h_btn = cloned_row.querySelector(".btn");
4269
h_btn.onclick = load_copter;
43-
console.log(`Added onclick: ${h_btn.onclick}`)
44-
70+
console.log(`Added onclick`)
4571
console.log(`ID: ${id}, Name: ${n}, Copter? ${Boolean(copter)}`);
46-
h_list.appendChild(cloned_row);
72+
73+
if(logged_in && logged_in.getEmail() == email){
74+
h_list.insertBefore(cloned_row, h_list.querySelector(".row"))
75+
} else {
76+
h_list.appendChild(cloned_row);
77+
}
4778

4879
}
4980
h_row1.remove();
5081
}
5182

52-
fetch("./api/users")
53-
.then(response => response.json())
54-
.then(data => render_users(data));
83+
function load_users(){
84+
users = []
85+
fetch("./api/users")
86+
.then(response => response.json())
87+
.then(data => {
88+
users = data;
89+
90+
if (h_row1 != null){
91+
remove_users();
92+
}
93+
render_users(data)
94+
});
95+
96+
console.log("Fetch in progress");
97+
}
98+
99+
load_users();
100+
101+
// Google sign-on
102+
console.log("Signin javascript loading");
103+
104+
var id_token = null;
105+
106+
function onSignIn(googleUser) {
107+
var profile = googleUser.getBasicProfile();
108+
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
109+
console.log('Name: ' + profile.getName());
110+
console.log('Image URL: ' + profile.getImageUrl());
111+
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
112+
113+
id_token = googleUser.getAuthResponse().id_token;
114+
console.log(`ID Token to pass to server: ${id_token}`)
115+
116+
logged_in = profile;
117+
118+
// Render again to get the logged in users card
119+
// updated from the google profile
120+
remove_users();
121+
render_users(users);
122+
}
123+
124+
console.log("Adding signOut function");
125+
function signOut() {
126+
var auth2 = gapi.auth2.getAuthInstance();
127+
auth2.signOut().then(function () {
128+
console.log('User signed out.');
129+
logged_in = null;
130+
remove_users();
131+
load_users();
132+
});
133+
id_token = null;
134+
}
135+
136+
137+
function danger_return(data){
138+
console.log("Authenticated request returned");
139+
console.log(data);
140+
remove_users();
141+
render_users(data);
142+
}
143+
144+
function danger(){
145+
console.log("Danger!");
146+
if (id_token == null) {
147+
alert("ILLEGAL ACCESS ATTEMPT REGISTERED");
148+
return;
149+
}
150+
151+
fetch("./api/users", {
152+
headers: {
153+
'Authorization' : id_token
154+
}
155+
}).then(response => response.json())
156+
.then(data => danger_return(data));
157+
158+
}
55159

56-
console.log("Fetch in progress");

frontend/index.html

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
<head>
44
<title>Fullstack example</title>
55

6+
<!-- Google sign-in stuff -->
7+
<script src="https://apis.google.com/js/platform.js" async defer></script>
8+
<!-- NOTE: Replace "content" with your own client ID -->
9+
<meta name="google-signin-client_id" content="42.apps.googleusercontent.com">
10+
611
<!-- From https://mdbootstrap.com/docs/standard/getting-started/installation/-->
712
<!-- Font Awesome -->
813
<link
@@ -21,53 +26,68 @@
2126
/>
2227

2328
<!-- MDB -->
24-
<script
29+
<script
2530
type="text/javascript"
2631
src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.3.0/mdb.min.js"
2732
></script>
2833

2934
<script src="fullstack.js"></script>
3035

31-
36+
3237
</head>
3338
<body>
39+
<main class="my-5">
40+
<!-- Google sign-in -->
41+
<div class="container">
42+
<div class="row">
43+
<div class="col">
44+
<div class="g-signin2" data-onsuccess="onSignIn"></div>
45+
</div>
46+
<div class="col">
47+
<button type="button" class="btn btn-primary" onclick="signOut(this)">Sign out</button>
48+
</div>
49+
<div class="col"></div>
50+
<div class="col"></div>
51+
<div class="col"></div>
52+
<div class="col">
53+
<button type="button" class="btn btn-danger" onclick="danger(this)">Secrets</button>
54+
</div>
55+
56+
</div>
57+
</div>
58+
<!-- // Google sign-in -->
59+
60+
<hr/>
3461

35-
36-
<!-- <h1>Fullstack example</h1>
37-
Inspect the API directly as well!-->
38-
39-
<main class="my-5">
4062
<div class="container" id="user_list">
41-
63+
4264
<section class="text-center text-md-start">
4365
<h4 class="mb-5">
4466
A fullstack example
4567
</h4>
46-
47-
<div class="row" id="first_row">
48-
<div class="col-md-4 mb-4">
49-
<div class="bg-image hover-overlay shadow-1-strong rounded ripple" data-mdb-ripple-color="light">
50-
<img src="https://mdbootstrap.com/img/new/standard/nature/184.jpg"
51-
class="img-fluid card-image"
52-
style="width: 300px;height: 150px; object-fit: cover;" />
53-
<a href="#!">
54-
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
55-
</a>
56-
</div>
57-
</div>
58-
<div class="col-md-8 mb-4">
59-
<h5 class="card-title">Very long post title</h5>
60-
<p>
61-
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus ratione
62-
necessitatibus itaque error alias repellendus nemo reiciendis aperiam quisquam minus
63-
ipsam reprehenderit commodi ducimus, in dicta aliquam eveniet dignissimos magni.
64-
</p>
65-
<button type="button" class="btn btn-primary" onclick="load_copter(this)">Load Ponycopter</button>
68+
</section>
69+
<div class="row" id="first_row">
70+
<div class="col-md-4 mb-4">
71+
<div class="bg-image hover-overlay shadow-1-strong rounded ripple" data-mdb-ripple-color="light">
72+
<img src="https://mdbootstrap.com/img/new/standard/nature/184.jpg"
73+
class="img-fluid card-image"
74+
style="width: 300px;height: 150px; object-fit: cover;" />
75+
<a href="#!">
76+
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
77+
</a>
6678
</div>
6779
</div>
68-
</section>
80+
<div class="col-md-8 mb-4">
81+
<h5 class="card-title">Very long post title</h5>
82+
<p>
83+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus ratione
84+
necessitatibus itaque error alias repellendus nemo reiciendis aperiam quisquam minus
85+
ipsam reprehenderit commodi ducimus, in dicta aliquam eveniet dignissimos magni.
86+
</p>
87+
<button type="button" class="btn btn-primary" onclick="load_copter(this)">Load Ponycopter</button>
88+
</div>
89+
</div>
6990
</div>
7091
</main>
71-
-->
7292
</body>
7393
</html>

0 commit comments

Comments
 (0)