ToolJet/frontend/src/AppBuilder/EmbedApp.jsx
Nakul Nagargade 433e1bd4c4
Enhance TypeScript support in frontend configuration (#15576)
* test: verify pre-commit hook

* fix: clean up code formatting and improve readability across multiple components

* chore: update subproject commit reference in frontend/ee

* chore: update eslint to version 9.26.0 and remove unused dependencies from package.json

fix: update submodule reference in server/ee

* chore: refactor ESLint configuration and add quiet linting script; update components to disable specific ESLint rules

* chore: add GitHub Copilot review instructions for App Builder team

Covers backward compatibility rules, styling conventions, state management,
resolution system, widget definitions, and common review flags.

* chore: add review instructions for App Builder, Data Migrations, Server Widget Config, Widget Components, and Widget Config

* Enhance TypeScript support in frontend configuration

- Added TypeScript parser and linting rules to ESLint configuration.
- Updated Babel configuration to include TypeScript preset.
- Modified package.json and package-lock.json to include TypeScript and related dependencies.
- Introduced tsconfig.json for TypeScript compiler options.
- Updated Webpack configuration to support .ts and .tsx file extensions.
- Adjusted linting and formatting scripts to include TypeScript files.

* chore: update TypeScript ESLint packages and subproject commits

---------

Co-authored-by: kavinvenkatachalam <kavin.saratha@gmail.com>
Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>
2026-03-19 12:41:32 +05:30

88 lines
2.7 KiB
JavaScript

import React, { useEffect } from 'react';
import useRouter from '@/_hooks/use-router';
import config from 'config';
import toast from 'react-hot-toast';
import './embed-loader.scss';
import Loader from '@/ToolJetUI/Loader/Loader';
// In-memory PAT token store
let inMemoryPatToken = null;
export function setPatToken(patToken) {
inMemoryPatToken = patToken;
}
export function getPatToken() {
if (inMemoryPatToken) return inMemoryPatToken;
// Fallback to window.name (persists across same-tab navigations)
if (window.name && window.name.length > 0) {
inMemoryPatToken = window.name;
return inMemoryPatToken;
}
return undefined;
}
export default function EmbedAppRedirect() {
const router = useRouter();
const { appId } = router.query;
useEffect(() => {
// 🔐 Ensure the page is embedded
if (window.self === window.top) {
// Not inside an iframe
toast.error('This page must be embedded inside a parent application.');
return;
}
const token = new URLSearchParams(window.location.search).get('personal-access-token');
if (!token || typeof appId !== 'string') {
parent?.postMessage({ type: 'TJ_EMBED_APP_LOGOUT', error: 400, message: 'Missing token or appId' }, '*');
return;
}
const initiateSession = async () => {
try {
const res = await fetch(`${config.apiUrl}/ext/users/session`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ appId, accessToken: token }),
});
if (!res.ok) {
if (res.status === 401 || res.status === 403) {
toast.error('Your pat is expired. Please refresh or contact your admin.');
// 🔔 Show toast if token is expired or invalid
parent?.postMessage(
{
type: 'TJ_EMBED_APP_LOGOUT',
error: res.status,
message: 'Your pat is expired. Please refresh or contact your admin.',
},
'*'
);
}
return;
}
const result = await res.json();
// ✅ Store PAT in memory
setPatToken(result.signedPat);
window.name = result.signedPat;
window.location.href = `applications/${appId}`;
} catch (error) {
parent?.postMessage({ type: 'TJ_EMBED_APP_LOGOUT', error: 500, message: 'Network error' }, '*');
}
};
initiateSession();
}, [appId]);
return (
<div className="embed-loader">
<div className="embed-loader__content">
<Loader width={30} absolute={false} />
<div className="embed-loader__text">Loading embedded app</div>
</div>
</div>
);
}