Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add embed link sharing #17

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added embedding/sigma_embed_link_sharing/.DS_Store
Binary file not shown.
15 changes: 15 additions & 0 deletions embedding/sigma_embed_link_sharing/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Sigma Embed Configuration
EMBED_PATH={url path to embed}
CLIENT_ID={your client id}
EMBED_SECRET={your embed secret}

# Required Parameters
EMAIL={your embed test user email address}
EXTERNAL_USER_ID=123
EXTERNAL_USER_TEAM=Sales_People
ACCOUNT_TYPE=Pro
MODE=userbacked
SESSION_LENGTH=600

# Server Configuration
PORT=3000
93 changes: 93 additions & 0 deletions embedding/sigma_embed_link_sharing/embed-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SIGMA EMBED LINK SHARING QUICKSTART
// embed-api.js

// 1: Require necessary Node.js modules
const express = require("express");
const crypto = require("crypto");
require("dotenv").config(); // Load environment variables from .env file

// 2: Initialize an Express application
const app = express();

// 3: Fetch configuration variables from .env file
const EMBED_PATH = process.env.EMBED_PATH; // Base URL for Sigma embedding
const EXPLORE_EMBED_PATH = process.env.EXPLORE_EMBED_PATH; // Base URL for exploration embedding
const EMBED_SECRET = process.env.EMBED_SECRET; // Secret key for signing the embed URL
const CLIENT_ID = process.env.CLIENT_ID; // Client ID for Sigma API
const EMAIL = process.env.EMAIL; // Email associated with the Sigma user
const EXTERNAL_USER_ID = process.env.EXTERNAL_USER_ID; // External user ID
const EXTERNAL_USER_TEAM = process.env.EXTERNAL_USER_TEAM; // Team associated with the external user
const ACCOUNT_TYPE = process.env.ACCOUNT_TYPE; // Account type (e.g., viewer, creator)
const MODE = process.env.MODE; // Mode (e.g., userbacked)
const SESSION_LENGTH = process.env.SESSION_LENGTH; // Session length in seconds
const PORT = process.env.PORT || 3000; // Default port is 3000

// 4: Serve static files from the root directory
app.use(express.static(__dirname)); // Serve index.html and other static files

// 5: Define a route handler for generating Sigma embed URLs
app.get("/api/generate-embed-url", (req, res) => {
try {
// Generate a unique nonce using crypto's UUID
const nonce = crypto.randomUUID();
let searchParams = `?:nonce=${nonce}`;

// Add required search parameters using .env variables
searchParams += `&:client_id=${CLIENT_ID}`;
searchParams += `&:email=${EMAIL}`;
searchParams += `&:external_user_id=${EXTERNAL_USER_ID}`;
searchParams += `&:external_user_team=${EXTERNAL_USER_TEAM}`;
searchParams += `&:account_type=${ACCOUNT_TYPE}`;
searchParams += `&:mode=${MODE}`;
searchParams += `&:session_length=${SESSION_LENGTH}`;
searchParams += `&:time=${Math.floor(new Date().getTime() / 1000)}`; // Current time in seconds

// Handle exploreKey if present in the query parameters
const exploreKey = req.query.exploreKey;

// Append exploreKey to the URL if present
if (exploreKey) {
searchParams += `&:explore=${exploreKey}`;
}

// Handle bookmarkId if present in the query parameters
const bookmarkId = req.query.bookmarkId;

// Append bookmarkId to the URL if present
if (bookmarkId) {
searchParams += `&:bookmark=${bookmarkId}`;
}

// Construct the URL with search parameters and generate a signature
const URL_WITH_SEARCH_PARAMS = EMBED_PATH + searchParams;
const SIGNATURE = crypto
.createHmac("sha256", Buffer.from(EMBED_SECRET, "utf8"))
.update(Buffer.from(URL_WITH_SEARCH_PARAMS, "utf8"))
.digest("hex");
const URL_TO_SEND = `${URL_WITH_SEARCH_PARAMS}&:signature=${SIGNATURE}`;

// Send the final URL to the requester
res.status(200).json({ url: URL_TO_SEND });
} catch (error) {
// Log and send error if URL generation fails
console.error("Error generating embed URL:", error.message);
res.status(500).send("Internal Server Error");
}
});

// 6: Define a route to serve the exploration embed URL from .env
app.get("/api/get-explore-embed-url", (req, res) => {
try {
const exploreEmbedUrl = EXPLORE_EMBED_PATH;
res.status(200).json({ url: exploreEmbedUrl });
} catch (error) {
// Log and send error if retrieval fails
console.error("Error retrieving explore embed URL:", error.message);
res.status(500).send("Internal Server Error");
}
});

// 7: Start the server
app.listen(PORT, () => {
console.log(`Node Express Server listening on port ${PORT}`);
});
147 changes: 147 additions & 0 deletions embedding/sigma_embed_link_sharing/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en" style="height: 100%; margin: 0; padding: 0;">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sigma - Embed Link Sharing Sample</title>
<style>
body, html {
height: 100%;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
}
h2 {
margin: 0;
padding: 10px;
text-align: center;
background: #f0f0f0;
}
iframe {
flex-grow: 1;
width: 100%;
border: none;
}
</style>
</head>
<body>
<h2>Sigma - Embed Link Sharing Sample</h2>
<iframe id="sigmaDashboard" frameborder="0"></iframe>

<script>
// Base URL for API requests
const API_BASE_URL = window.location.origin;

// Reference to the Sigma iframe
const iframe = document.getElementById("sigmaDashboard");

// Variables to store current exploreKey and bookmarkId
let currentExploreKey = null;
let currentBookmarkId = null;

// Parse query parameters from the current URL
const urlParams = new URLSearchParams(window.location.search);
const exploreKey = urlParams.get("exploreKey");
const bookmarkId = urlParams.get("bookmarkId");

// Function to generate the fetch URL for the server request
function generateFetchUrl(exploreKey, bookmarkId) {
let url = `${API_BASE_URL}/api/generate-embed-url?`; // Base API URL
if (exploreKey) url += `exploreKey=${exploreKey}`;
if (bookmarkId) url += `&bookmarkId=${bookmarkId}`;
console.log("Generated fetch URL:", url); // Log the generated URL for debugging
return url; // Return the constructed URL
}

// Function to fetch the signed embed URL from the server
async function fetchEmbedUrl(exploreKey, bookmarkId) {
try {
// Generate the URL with the correct parameters
const newUrl = generateFetchUrl(exploreKey, bookmarkId);
console.log("Fetching new URL:", newUrl); // Log the URL being fetched
const response = await fetch(newUrl);
const data = await response.json();

if (response.ok) {
// Set the iframe src to the retrieved embed URL
iframe.src = data.url;
console.log("Updated iframe src to:", data.url);
} else {
console.error("Error fetching embed URL:", data.error);
}
} catch (error) {
console.error("Error fetching embed URL:", error);
}
}

// Function to update the browser URL without reloading the page
function updateBrowserUrl(exploreKey, bookmarkId) {
const params = new URLSearchParams();
if (exploreKey) params.append("exploreKey", exploreKey);
if (bookmarkId) params.append("bookmarkId", bookmarkId);

const newUrl = `${window.location.origin}${window.location.pathname}?${params.toString()}`;
window.history.pushState({}, '', newUrl);
}

// Function to send sharing links back to Sigma
function sendSharingLinks() {
const baseUrl = window.location.origin + window.location.pathname;
const finalSharingLink = currentExploreKey || currentBookmarkId
? `${baseUrl}?${currentExploreKey ? `exploreKey=${currentExploreKey}` : ''}${currentBookmarkId ? `&bookmarkId=${currentBookmarkId}` : ''}`
: baseUrl;

const sharingExplorationLink = currentExploreKey
? currentBookmarkId
? `${baseUrl}?exploreKey=${currentExploreKey}&bookmarkId=${currentBookmarkId}`
: `${baseUrl}?exploreKey=${currentExploreKey}`
: null;

console.log("Sending sharing links to Sigma:");
console.log("Final Sharing Link:", finalSharingLink);
console.log("Sharing Exploration Link:", sharingExplorationLink);

iframe.contentWindow.postMessage(
{
type: "workbook:sharinglink:update",
sharingLink: finalSharingLink,
sharingExplorationLink: sharingExplorationLink,
},
"https://app.sigmacomputing.com"
);
}

// Event listener for messages from the Sigma iframe
window.addEventListener("message", (event) => {
if (event.source === iframe.contentWindow && event.origin === "https://app.sigmacomputing.com") {
const eventData = event.data;

// Handle exploreKey changes
if (eventData.type === "workbook:exploreKey:onchange") {
currentExploreKey = eventData.exploreKey;
console.log("Explore Key Updated:", currentExploreKey); // Log the exploreKey update
updateBrowserUrl(currentExploreKey, currentBookmarkId); // Update the browser URL
sendSharingLinks(); // Send the sharing link back to Sigma
}

// Handle bookmarkId changes
if (eventData.type === "workbook:bookmark:onchange") {
currentBookmarkId = eventData.bookmarkId;
console.log("Bookmark ID Updated:", currentBookmarkId); // Log the bookmarkId update
updateBrowserUrl(currentExploreKey, currentBookmarkId); // Update the browser URL
sendSharingLinks(); // Send the sharing link back to Sigma
}

// Handle workbook loaded events
if (eventData.type === "workbook:loaded" || eventData.type === "workbook:dataloaded") {
sendSharingLinks(); // Send the sharing link back to Sigma
}
}
});

// Initial fetch of the embed URL and setting the iframe src
fetchEmbedUrl(exploreKey, bookmarkId);
</script>
</body>
</html>
6 changes: 6 additions & 0 deletions embedding/sigma_embed_link_sharing/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": [".env", ".js", "html"],
"ext": "js, env, html",
"ignore": ["node_modules"],
"exec": "node embed-api.js"
}
11 changes: 11 additions & 0 deletions embedding/sigma_embed_link_sharing/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "sigma_embed_link_sharing",
"version": "1.0.0",
"main": "embed-api.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}