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

feat: Add shared objects to embed-widget #2189

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
109 changes: 95 additions & 14 deletions packages/embed-widget/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,17 @@
function App(): JSX.Element {
const [error, setError] = useState<string>();
const [definition, setDefinition] = useState<dh.ide.VariableDefinition>();
const [sharedReady, setSharedReady] = useState<boolean>(false);
const searchParams = useMemo(
() => new URLSearchParams(window.location.search),
[]
);
// Get the widget name from the query param `name`.
const name = searchParams.get('name');
// Get the type of shared object from the query param,
// which is necessary if the widget is shared.
const type = searchParams.get('type');
const isShared = searchParams.get('isShared');
const api = useApi();
const connection = useConnection();
const client = useClient();
Expand Down Expand Up @@ -115,34 +120,86 @@
)
);

log.debug(`Loading widget definition for ${name}...`);
if (isShared === 'true') {
log.debug(`Checking if shared parameters are valid...`);

const newDefinition = await fetchVariableDefinition(connection, name);
if (type == null) {
throw new Error('Missing URL parameter "type"');
}

setDefinition(newDefinition);
setSharedReady(true);

log.debug(`Widget definition successfully loaded for ${name}`);
log.debug(`Shared parameters are valid`);
} else {
log.debug(`Loading widget definition for ${name}...`);

const newDefinition = await fetchVariableDefinition(
connection,
name
);

setDefinition(newDefinition);

log.debug(`Widget definition successfully loaded for ${name}`);
}
} catch (e: unknown) {
log.error(`Unable to load widget definition for ${name}`, e);
setError(`${e}`);
}
}
initApp();
},
[api, client, connection, dispatch, name, serverConfig, user]
[
api,
client,
connection,
dispatch,
name,
serverConfig,
user,
isShared,
type,
]
);

const isLoaded = definition != null && error == null;
const isLoading = definition == null && error == null;
const isLoaded =
(definition != null || sharedReady != false) && error == null;

Check failure on line 166 in packages/embed-widget/src/App.tsx

View workflow job for this annotation

GitHub Actions / unit

Expected '!==' and instead saw '!='
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(definition != null || sharedReady != false) && error == null;
(definition != null || sharedReady) && error == null;

const isLoading = definition == null && sharedReady == false && error == null;

Check failure on line 167 in packages/embed-widget/src/App.tsx

View workflow job for this annotation

GitHub Actions / unit

Expected '===' and instead saw '=='
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const isLoading = definition == null && sharedReady == false && error == null;
const isLoading = definition == null && !sharedReady && error == null;


type ConnectionWithGetSharedObject = dh.IdeConnection & {
getSharedObject(name: string, type: string): Promise<unknown>;

Check failure on line 170 in packages/embed-widget/src/App.tsx

View workflow job for this annotation

GitHub Actions / unit

Shorthand method signature is forbidden. Use a function property instead
};

function isConnectionWithGetSharedObject(
connection: dh.IdeConnection

Check failure on line 174 in packages/embed-widget/src/App.tsx

View workflow job for this annotation

GitHub Actions / unit

'connection' is already declared in the upper scope on line 78 column 9
): connection is ConnectionWithGetSharedObject {
return (
'getSharedObject' in connection &&
typeof connection.getSharedObject === 'function'
);
}
Comment on lines +169 to +180
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the type definition and typePredicate outside of/above this functional component.


const fetch = useMemo(() => {
if (definition == null) {
if (definition == null && !sharedReady) {
return async () => {
throw new Error('Definition is null');
};
}
return () => connection.getObject(definition);
}, [connection, definition]);
return () => {
if (name != null && type != null) {
if (isConnectionWithGetSharedObject(connection)) {
return connection.getSharedObject(name, type);
}
throw new Error(
'Connection does not have getSharedObject method. Cannot fetch shared object.'
);
}
if (definition != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally put the definition != null case first.

return connection.getObject(definition);
}
throw new Error('Definition is null or shared parameters are not set');
};
}, [connection, definition, sharedReady, name, type]);

Check warning on line 202 in packages/embed-widget/src/App.tsx

View workflow job for this annotation

GitHub Actions / unit

React Hook useMemo has a missing dependency: 'isConnectionWithGetSharedObject'. Either include it or remove the dependency array

const [goldenLayout, setGoldenLayout] = useState<GoldenLayout | null>(null);
const [dashboardId, setDashboardId] = useState('default-embed-widget'); // Can't be DEFAULT_DASHBOARD_ID because its dashboard layout is not stored in dashboardData
Expand Down Expand Up @@ -175,16 +232,40 @@
const [hasEmittedWidget, setHasEmittedWidget] = useState(false);

const handleDashboardInitialized = useCallback(() => {
if (goldenLayout == null || definition == null || hasEmittedWidget) {
if (
goldenLayout == null ||
(definition == null && sharedReady == null) ||
hasEmittedWidget
) {
return;
}

setHasEmittedWidget(true);

let widget = null;
if (sharedReady != null) {
widget = {
type,
name,
} as dh.ide.VariableDescriptor;
} else if (definition != null) {
widget = getVariableDescriptor(definition);
} else {
return;
}

emitPanelOpen(goldenLayout.eventHub, {
fetch,
widget: getVariableDescriptor(definition),
widget,
});
}, [goldenLayout, definition, fetch, hasEmittedWidget]);
}, [
goldenLayout,
definition,
fetch,
hasEmittedWidget,
name,
type,
sharedReady,
]);

const allDashboardData = useSelector(getAllDashboardsData);

Expand Down
Loading