-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Allow GraphiQL apps control over closing tabs #3563
Conversation
🦋 Changeset detectedLatest commit: be49600 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3563 +/- ##
==========================================
- Coverage 67.60% 67.30% -0.31%
==========================================
Files 121 121
Lines 6968 7016 +48
Branches 2251 2243 -8
==========================================
+ Hits 4711 4722 +11
- Misses 2240 2277 +37
Partials 17 17
|
if (editorContext.activeTabIndex === index) { | ||
executionContext.stop(); | ||
onClick={async () => { | ||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should move all of this into closeTab
itself, even what was directly in the handler here before, making it async. i see no reason to let this be an implementation detail for sdk users, as if the context they are using has this logic they would expect this as as an internal detail of the method if it's exposed to the user yeah?
const closeTab = useCallback<EditorContextType['closeTab']>(
async index => {
if (await closeTabConfirmation(index)) {
// this could be a breaking change for users who are already stopping
// execution manually like graphiql does, however stopping execution twice should not
// cause any errors?
if (index === tabState.activeTabIndex) {
stop();
}
setTabState(current => {
const updated = {
tabs: current.tabs.filter((_tab, i) => index !== i),
activeTabIndex: Math.max(current.activeTabIndex - 1, 0),
};
storeTabs(updated);
setEditorValues(updated.tabs[updated.activeTabIndex]);
onTabChange?.(updated);
return updated;
});
}
},
[
onTabChange,
setEditorValues,
storeTabs,
closeTabConfirmation,
tabState.activeTabIndex,
],
);
and then here in graphiql:
<Tab.Close
onClick={async () => editorContext.closeTab(index)}
/>
so then sdk users have this in const { openTab, closeTab } = useEditorContext()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is awesome, and makes a lot of sense! i'm glad you're able to achieve this with your app. just the one change,,I hope that's ok!
Absolutely, I don't mind a little boy scouting, looks much cleaner now overall. I think this looks good to go now. PS:
Yea, it totally works - but... Since the plugin is handling its own state management and its own data fetching, it is a bit tricky, since I need the top level component that mounts
|
@acao Are we good to go? |
fbb81ad
to
5b37ed0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is awesome, I would love to hear from my colleauges first as well, but if not I think we can merge soon!
@thomasheyenbrock can you take a look at this as well? 🙏 |
ef9e787
to
09ed3a6
Compare
09ed3a6
to
8175e00
Compare
5544802
to
0387001
Compare
async function confirmCloseTab(_index) { | ||
// eslint-disable-next-line no-alert | ||
if (window.confirm('Are you sure you want to close this tab?')) { | ||
return true; | ||
} | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Close tab | ||
// Close tab (this will get rejected) | ||
cy.get('#graphiql-session-tab-1 + .graphiql-tab-close').click(); | ||
|
||
// Tab is still visible | ||
cy.get('#graphiql-session-tab-1 + .graphiql-tab-close').should('exist'); | ||
|
||
// Close tab (this will get accepted) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is better to add independent test for confirmation, and not merge it with existent one
@@ -498,6 +541,7 @@ export function EditorContextProvider(props: EditorContextProviderProps) { | |||
addTab, | |||
changeTab, | |||
moveTab, | |||
closeTabConfirmation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we need to pass this function to context? It’s used only in this component
async index => { | ||
if (await closeTabConfirmation(index)) { | ||
if (index === tabState.activeTabIndex) { | ||
executionContext?.stop(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will never be called, because we can't use execution context inside the editor context, because we already use editor context inside execution context. to reproduce it simply change
executionContext?.stop(); | |
executionContext!.stop(); |
and use useExecutionContext({ notNull: true });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added e2e tests, some refactoring of moving executionContext.stop()
can be done after moving to zustand
Allow GraphiQL apps control over closing tabs
This feature is about closing tabs.
Current functionality:
Requested functionality
In our case, we are working on a Collection plugin that you can click to read saved queries / variables / headers from a DB, and this opens it in a new tab. So we need to sync tabState with the list of Collection items. And if a user starts to change a Collection item, we want to warn the user that changes will be lost.
It is the same as if the user selected a file in a code editor, started to change it, and then tries to close the tab.
Mock screenshots