rusackas commented on code in PR #41285:
URL: https://github.com/apache/superset/pull/41285#discussion_r4243318147
##########
superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx:
##########
@@ -94,6 +99,199 @@ const TabTitle = styled.span`
// Get the user's OS
const userOS = detectOS();
+const PlusIcon = (
+ <Icons.PlusOutlined
+ iconSize="l"
+ css={css`
+ vertical-align: middle;
+ `}
+ data-test="add-tab-icon"
+ />
+);
+
+// Shown in place of PlusIcon while extensions are still loading — see the
+// extensionsReady guard in NewTabButton below.
+const LoadingIcon = (
+ <Icons.LoadingOutlined
+ iconSize="l"
+ css={css`
+ vertical-align: middle;
+ `}
+ data-test="add-tab-icon"
+ />
+);
+
+function NewTabButton({ onAddSqlEditor }: { onAddSqlEditor: () => void }) {
+ const [open, setOpen] = useState(false);
+ // Until this is true, menus.getMenu(sqllab.newTab) can't be trusted to
+ // reflect the final set of contributions — an extension that hasn't
+ // finished loading yet looks identical to "no extensions at all". Without
+ // this, clicking "+" during that window fell back to adding a plain SQL
+ // tab instead of waiting to show the real dropdown.
+ const extensionsReady = useExtensionsReady();
+
+ // Resolved at render time rather than module load so `t()` runs after the
+ // translator has been configured.
+ const newTabTooltip = !extensionsReady
+ ? t('Loading…')
Review Comment:
Done, switched to `Loading...`. Thanks @EnxDev.
##########
superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx:
##########
@@ -219,23 +422,11 @@ function TabbedSqlEditors({
const emptyTab = (
<StyledTab>
<TabTitle>{t('Add a new tab')}</TabTitle>
- <Tooltip
- id="add-tab"
- placement="bottom"
- title={
- userOS === 'Windows'
- ? t('New tab (Ctrl + q)')
- : t('New tab (Ctrl + t)')
- }
- >
- <Icons.PlusCircleOutlined
- iconSize="s"
- css={css`
- vertical-align: middle;
- `}
- data-test="add-tab-icon"
- />
- </Tooltip>
+ {/* Reuses the toolbar's own add-tab control (dropdown when an
+ extension contributes to sqllab.newTab, plain create otherwise)
+ instead of a bare icon, so this empty-state entry point offers the
+ same choices as the "+" in the tab bar once tabs exist. */}
+ <NewTabButton onAddSqlEditor={newQueryEditor} />
Review Comment:
Good catch. The empty state now falls back to the anchor itself when there
is no antd button, and I added a zero-editor test. Not run locally, so CI will
confirm.
##########
superset-frontend/src/extensions/ExtensionsLoader.ts:
##########
@@ -100,22 +112,61 @@ class ExtensionsLoader {
const results = await Promise.all(
extensions.map(ext => this.initializeExtension(ext)),
);
- if (results.every(Boolean)) {
+ const failed = extensions
+ .filter((_, index) => !results[index])
+ .map(ext => ext.name);
+ if (failed.length === 0) {
logging.info('Extensions initialized successfully.');
} else {
- const failedCount = results.filter(succeeded => !succeeded).length;
logging.info(
- `Extensions initialized with ${failedCount} of ` +
+ `Extensions initialized with ${failed.length} of ` +
`${extensions.length} extension(s) failing. See errors above.`,
);
}
+ return failed;
} catch (error) {
+ // Reset so a later call can retry, and rethrow so callers (e.g.
+ // ExtensionsStartup) can surface the failure instead of it being
+ // swallowed here and the success path running regardless.
+ this.initializationPromise = null;
logging.error('Error setting up extensions:', error);
+ throw error;
}
})();
+ // Attached separately (not reassigning this.initializationPromise) so
+ // ready-tracking is purely a side effect and every caller still sees the
+ // original promise's own resolve/reject value.
+ this.initializationPromise.finally(() => this.markReady());
Review Comment:
Done, both branches are handled now via `.then(onOk, onErr)`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]