Skip to content

Commit

Permalink
add <DubDashboard />
Browse files Browse the repository at this point in the history
  • Loading branch information
devkiran committed Nov 22, 2024
1 parent 730e523 commit 56e25da
Show file tree
Hide file tree
Showing 19 changed files with 262 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import useWorkspace from "@/lib/swr/use-workspace";
import { RewardDashboard } from "@/ui/embed/referrals-embed";
import { DubDashboard } from "@dub/embed-react";
import { LoadingSpinner } from "@dub/ui";
import { redirect } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
Expand Down Expand Up @@ -37,8 +37,8 @@ export default function ReferralsPageClient() {
}

return publicToken ? (
<RewardDashboard
publicToken={publicToken}
<DubDashboard
linkToken={publicToken}
onTokenExpired={() => createPublicToken()}
/>
) : (
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@dub/tailwind-config": "workspace:*",
"@dub/ui": "workspace:*",
"@dub/utils": "workspace:*",
"@dub/embed-react": "workspace:*",
"@hookform/resolvers": "^3.9.0",
"@next-auth/prisma-adapter": "^1.0.5",
"@planetscale/database": "^1.18.0",
Expand Down
54 changes: 39 additions & 15 deletions apps/web/public/embed.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@


(function () {
window.Dub = window.Dub || {};

// Default configurations
Dub.options = {
linkToken: null,
widgetUrl: "http://localhost:8888/embed/widget",
dashboardUrl: "http://localhost:8888/embed/dashboard",
};

const buttonStyles = {
Expand All @@ -25,10 +29,37 @@
zIndex: "9998",
};

// Add a floating button to the page
function createFloatingButton() {
const createIframe = (iframeUrl, linkToken) => {
const iframe = document.createElement("iframe");

iframe.src = `${iframeUrl}?token=${linkToken}`;
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.setAttribute("credentialssupport", "");
iframe.setAttribute("allow", "same-origin");
iframe.crossOrigin = "use-credentials";

return iframe;
};

// Find the button that should trigger the widget open
const initializeDubButton = () => {
const button = document.querySelector("[data-dub-token]");

if (!button) {
console.log("No button found with data-dub-token");
return;
}

button.addEventListener("click", () => {
console.log("Button clicked");
});
};

// Add a floating button
const createFloatingButton = () => {
const button = document.createElement("div");
button.id = "floating-widget-button";
Object.assign(button.style, buttonStyles);

button.innerHTML = `
Expand All @@ -51,32 +82,25 @@
return;
}

// Create iframe container
const container = document.createElement("div");
container.id = "dub-widget-container";
Object.assign(container.style, containerStyles);

// Create iframe
const iframe = document.createElement("iframe");
iframe.src = `http://localhost:8888/embed/widget?token=${Dub.options.linkToken}`;
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.setAttribute("credentialssupport", "");
iframe.setAttribute("allow", "same-origin");
iframe.crossOrigin = "use-credentials";
const { iframeUrl, linkToken } = Dub.options;

const iframe = createIframe(iframeUrl, linkToken);

container.appendChild(iframe);
document.body.appendChild(container);
});

document.body.appendChild(button);
}
};

// Initialize when DOM is ready
function init() {
setTimeout(createFloatingButton, 100);
console.log("Initialized");
// setTimeout(initializeDubButton, 100);
}

if (document.readyState === "loading") {
Expand Down
10 changes: 7 additions & 3 deletions dub.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
<script async src="http://localhost:8888/embed.js"></script>
</head>
<body>
<script type="text/javascript">
<!-- <script type="text/javascript">
window.addEventListener("load", function () {
window.Dub.options = {
linkToken: "dub_embed_7cnHQVYxXxr7tzIAuuPwjDVWT5oC0rD2WyUu", // replace with token
linkToken: "dub_embed_cUWcbfn76uAwaHbgoq8yuH6QvOgIaAQb0yoc", // replace with token
};
});
</script>
</script> -->

<button data-dub-token="dub_embed_cUWcbfn76uAwaHbgoq8yuH6QvOgIaAQb0yoc">
Click Me
</button>
</body>
</html>
11 changes: 11 additions & 0 deletions packages/embeds/react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `@dub/embed-react`

`@dub/embed-react` is a library of React components that are used embed Dub's widget on third-party websites.

## Installation

To install the package, run:

```bash
pnpm i @dub/embed-react
```
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
{
"name": "@dub/widgets",
"description": "UI widgets for Dub Partners.",
"version": "0.1.66",
"name": "@dub/embed-react",
"description": "Embed React components for Dub.",
"version": "0.0.1",
"sideEffects": false,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup",
"lint": "eslint src/",
"dev": "tsup --watch",
"check-types": "tsc --noEmit"
},
"peerDependencies": {
"next": "14.2.0-canary.47",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
File renamed without changes.
48 changes: 48 additions & 0 deletions packages/embeds/react/src/dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { APP_DOMAIN } from "@dub/utils";
import { useEffect } from "react";

interface DubDashboardProps {
linkToken: string;
onTokenExpired?: () => void;
url?: string;
}

const iframeStyles = {
width: "100%",
height: "100vh",
border: "none",
};

export const DubDashboard = ({
linkToken,
onTokenExpired,
url = `${APP_DOMAIN}/embed/dashboard`,
}: DubDashboardProps) => {
// Listen for messages from the iframe
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
if (event.origin !== APP_DOMAIN) {
return;
}

if (event.data === "TOKEN_EXPIRED") {
console.error("[Dub] Link token is expired.");
onTokenExpired?.();
}
};

window.addEventListener("message", handleMessage);

return () => window.removeEventListener("message", handleMessage);
}, [onTokenExpired]);

// If no link token is provided
if (!linkToken) {
console.error("[Dub] A link token is required to embed the dashboard.");
return null;
}

const dashboardUrl = `${url}?token=${linkToken}`;

return <iframe src={dashboardUrl} style={iframeStyles} />;
};
File renamed without changes.
16 changes: 16 additions & 0 deletions packages/embeds/react/src/embed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// TODO:
// - Convert to TS
// - Add a loading state
// - Add a close button
// - Inline embed (dashboard)
// - Floating button + widget
// - Open on a button click

interface DubOptions {
linkToken: string;
widgetUrl: string;
dashboardUrl: string;
}

// <DubDashboard />
// <DubWidget />
2 changes: 2 additions & 0 deletions packages/embeds/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./dashboard";
export * from "./widget";
3 changes: 3 additions & 0 deletions packages/embeds/react/src/widget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const DubWidget = () => {
return <div>Dub Widget</div>;
};
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineConfig, Options } from "tsup";

export default defineConfig((options: Options) => ({
entry: ["src/**/*.tsx"],
entry: ["src/**/*.ts"],
format: ["esm"],
esbuildOptions(options) {
options.banner = {
Expand Down
11 changes: 0 additions & 11 deletions packages/widgets/README.md

This file was deleted.

Empty file removed packages/widgets/src/index.ts
Empty file.
Loading

0 comments on commit 56e25da

Please sign in to comment.