From e1468d020a1af36472d045e2ac545fc794a8b4f7 Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Thu, 24 Oct 2024 12:05:00 -0700 Subject: [PATCH 1/4] chore: updates internet_identity_integration with best practices --- .../src/greet_frontend/src/index.html | 11 +-- .../src/greet_frontend/src/index.js | 92 +++++++++++-------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/motoko/internet_identity_integration/src/greet_frontend/src/index.html b/motoko/internet_identity_integration/src/greet_frontend/src/index.html index b7a9ca59e..8e94e2a75 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/src/index.html +++ b/motoko/internet_identity_integration/src/greet_frontend/src/index.html @@ -11,15 +11,8 @@
DFINITY logo -
-
-
- -
-
-
- -
+ +
diff --git a/motoko/internet_identity_integration/src/greet_frontend/src/index.js b/motoko/internet_identity_integration/src/greet_frontend/src/index.js index 83ed3d655..4b46ba788 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/src/index.js +++ b/motoko/internet_identity_integration/src/greet_frontend/src/index.js @@ -1,48 +1,62 @@ -import {createActor, greet_backend} from "../../declarations/greet_backend"; -import {AuthClient} from "@dfinity/auth-client" -import {HttpAgent} from "@dfinity/agent"; - -let actor = greet_backend; +import { createActor, greet_backend } from "../../declarations/greet_backend"; +import { AuthClient } from "@dfinity/auth-client"; +import { HttpAgent } from "@dfinity/agent"; + +/** + * Put this on the window so we can access it from the console. + * This is helpful for learning, but it's recommended to keep it in a closure in a real app. + * + * We can use the default (not authenticated) greet_backend actor to call the greet method, and then update it once the authClient is ready, and again when the user logs in. + */ +window.greetActor = greet_backend; const greetButton = document.getElementById("greet"); -greetButton.onclick = async (e) => { - e.preventDefault(); +const loginButton = document.getElementById("login"); - greetButton.setAttribute("disabled", true); +AuthClient.create().then((client) => { + // Put this on the window so we can access it from the console. This is helpful for learning, but it's recommended to keep it in a closure in a real app. + window.authClient = client; + // We can use the authClient to check if the user is already authenticated + setActor(client); + + // Now that the auth client is created, we can enable the login and greet buttons + loginButton.removeAttribute("disabled"); + greetButton.removeAttribute("disabled"); +}); + +loginButton.onclick = async () => { + // start the login process and wait for it to finish + window.authClient.login({ + identityProvider: process.env.II_URL, + onSuccess: () => { + setActor(window.authClient); + }, + }); +}; - // Interact with backend actor, calling the greet method - const greeting = await actor.greet(); +greetButton.onclick = async () => { + // Disable the button to prevent multiple clicks + greetButton.setAttribute("disabled", true); - greetButton.removeAttribute("disabled"); + // Interact with backend actor, calling the greet method + const greeting = await window.greetActor.greet(); - document.getElementById("greeting").innerText = greeting; + greetButton.removeAttribute("disabled"); - return false; + document.getElementById("greeting").innerText = greeting; }; -const loginButton = document.getElementById("login"); -loginButton.onclick = async (e) => { - e.preventDefault(); - - // create an auth client - let authClient = await AuthClient.create(); - - // start the login process and wait for it to finish - await new Promise((resolve) => { - authClient.login({ - identityProvider: process.env.II_URL, - onSuccess: resolve, - }); - }); - - // At this point we're authenticated, and we can get the identity from the auth client: - const identity = authClient.getIdentity(); - // Using the identity obtained from the auth client, we can create an agent to interact with the IC. - const agent = new HttpAgent({identity}); - // Using the interface description of our webapp, we create an actor that we use to call the service methods. - actor = createActor(process.env.GREET_BACKEND_CANISTER_ID, { - agent, - }); - - return false; -}; \ No newline at end of file +/** + * Sets the actor to be used by the greet button + * @param {AuthClient} an initialized AuthClient, which will have the identity of the user (logged in or not) + */ +function setActor(authClient) { + // At this point we're authenticated, and we can get the identity from the auth client: + const identity = authClient.getIdentity(); + // Using the identity obtained from the auth client, we can create an agent to interact with the IC. + const agent = new HttpAgent({ identity }); + // Using the interface description of our webapp, we create an actor that we use to call the service methods. + window.greetActor = createActor(process.env.GREET_BACKEND_CANISTER_ID, { + agent, + }); +} From 515d670ca049545e311392db492aba8c0a927f5c Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Thu, 24 Oct 2024 12:11:59 -0700 Subject: [PATCH 2/4] parity with button styles --- .../src/greet_frontend/assets/main.css | 15 +++++++-------- .../src/greet_frontend/src/index.html | 6 ++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/motoko/internet_identity_integration/src/greet_frontend/assets/main.css b/motoko/internet_identity_integration/src/greet_frontend/assets/main.css index ccf2e6cf0..f2b1ce118 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/assets/main.css +++ b/motoko/internet_identity_integration/src/greet_frontend/assets/main.css @@ -10,20 +10,19 @@ img { margin: auto; } -form { +#buttons { display: flex; justify-content: center; - gap: 0.5em; - flex-flow: row wrap; - max-width: 40vw; - margin: auto; + gap: 1.5em; + flex-direction: column; + width: max-content; + margin: 1.5em auto; align-items: baseline; } -button[type="submit"] { +button { padding: 5px 20px; - margin: 10px auto; - float: right; + width: 100%; } #greeting { diff --git a/motoko/internet_identity_integration/src/greet_frontend/src/index.html b/motoko/internet_identity_integration/src/greet_frontend/src/index.html index 8e94e2a75..3c7683e05 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/src/index.html +++ b/motoko/internet_identity_integration/src/greet_frontend/src/index.html @@ -11,8 +11,10 @@
DFINITY logo - - +
+ + +
From 5165aec18446b0ce40ac2b99a345fe149fb970af Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Thu, 24 Oct 2024 12:28:23 -0700 Subject: [PATCH 3/4] small enhancements --- .../src/greet_frontend/src/index.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/motoko/internet_identity_integration/src/greet_frontend/src/index.js b/motoko/internet_identity_integration/src/greet_frontend/src/index.js index 4b46ba788..2b9e5508e 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/src/index.js +++ b/motoko/internet_identity_integration/src/greet_frontend/src/index.js @@ -2,13 +2,9 @@ import { createActor, greet_backend } from "../../declarations/greet_backend"; import { AuthClient } from "@dfinity/auth-client"; import { HttpAgent } from "@dfinity/agent"; -/** - * Put this on the window so we can access it from the console. - * This is helpful for learning, but it's recommended to keep it in a closure in a real app. - * - * We can use the default (not authenticated) greet_backend actor to call the greet method, and then update it once the authClient is ready, and again when the user logs in. - */ -window.greetActor = greet_backend; +// Global variables that we will set up +window.greetActor; +window.authClient; const greetButton = document.getElementById("greet"); const loginButton = document.getElementById("login"); @@ -24,13 +20,16 @@ AuthClient.create().then((client) => { greetButton.removeAttribute("disabled"); }); -loginButton.onclick = async () => { +loginButton.onclick = () => { // start the login process and wait for it to finish window.authClient.login({ identityProvider: process.env.II_URL, onSuccess: () => { setActor(window.authClient); }, + onError: (err) => { + console.error(err); + }, }); }; From 30ee45e5c65f43f36f47e22e7b040b6077a152ed Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Fri, 1 Nov 2024 11:48:30 -0700 Subject: [PATCH 4/4] discouraging use of globabl variables with comment --- .../src/greet_frontend/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/motoko/internet_identity_integration/src/greet_frontend/src/index.js b/motoko/internet_identity_integration/src/greet_frontend/src/index.js index 2b9e5508e..506800600 100644 --- a/motoko/internet_identity_integration/src/greet_frontend/src/index.js +++ b/motoko/internet_identity_integration/src/greet_frontend/src/index.js @@ -2,7 +2,7 @@ import { createActor, greet_backend } from "../../declarations/greet_backend"; import { AuthClient } from "@dfinity/auth-client"; import { HttpAgent } from "@dfinity/agent"; -// Global variables that we will set up +// Global variables for convenience while you're becoming familiar with the interface. You should use local variables or closures in production window.greetActor; window.authClient;