@atlaskit/editor-plugin-card
Version:
Card plugin for @atlaskit/editor-core
315 lines (314 loc) • 11.9 kB
JavaScript
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { useCallback, useMemo, useRef, useState } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
import { css, jsx } from '@emotion/react';
import { FormattedMessage } from 'react-intl';
import { linkToolbarMessages, cardMessages as messages } from '@atlaskit/editor-common/messages';
import { FloatingToolbarButton as Button, FloatingToolbarSeparator as Separator } from '@atlaskit/editor-common/ui';
import { ArrowKeyNavigationType, DropdownContainer as UiDropdown } from '@atlaskit/editor-common/ui-menu';
import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
import { useSmartLinkContext } from '@atlaskit/link-provider';
import { ButtonItem } from '@atlaskit/menu';
import { Flex } from '@atlaskit/primitives/compiled';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { focusEditorView, isDatasourceConfigEditable } from '../../pm-plugins/utils';
import { editDatasource } from '../editDatasourceAction';
import { useFetchDatasourceDataInfo } from '../useFetchDatasourceDataInfo';
import { useFetchDatasourceInfo } from '../useFetchDatasourceInfo';
import EditToolbarButtonPresentation from './EditToolbarButtonPresentation';
const dropdownExpandContainer = css({
margin: `0px ${"var(--ds-space-negative-050, -4px)"}`
});
const EditToolbarButtonWithCardContext = props => {
var _response$datasourceI;
const {
cardContext,
currentAppearance,
editorAnalyticsApi,
editorView,
intl,
onLinkEditClick,
url,
areAnyNewToolbarFlagsEnabled
} = props;
const {
extensionKey,
...response
} = useFetchDatasourceInfo({
isRegularCardNode: true,
url,
cardContext
});
const datasourceId = (_response$datasourceI = response.datasourceId) !== null && _response$datasourceI !== void 0 ? _response$datasourceI : props.datasourceId;
const [isOpen, setIsOpen] = useState(false);
const containerRef = useRef();
const toggleOpen = () => setIsOpen(open => !open);
const onClose = () => setIsOpen(false);
const onEditLink = useCallback(() => {
if (editorView) {
onLinkEditClick(editorView.state, editorView.dispatch);
focusEditorView(editorView);
}
}, [editorView, onLinkEditClick]);
const editVariant = useMemo(() => {
const hasUrl = url !== null && url !== undefined;
if (!datasourceId || !isDatasourceConfigEditable(datasourceId)) {
if (hasUrl) {
return 'edit-link';
}
return 'none';
}
if (hasUrl) {
var _cardContext$store, _urlState$error;
const urlState = cardContext === null || cardContext === void 0 ? void 0 : (_cardContext$store = cardContext.store) === null || _cardContext$store === void 0 ? void 0 : _cardContext$store.getState()[url];
if ((urlState === null || urlState === void 0 ? void 0 : (_urlState$error = urlState.error) === null || _urlState$error === void 0 ? void 0 : _urlState$error.kind) === 'fatal') {
return 'edit-link';
}
return 'edit-dropdown';
} else {
return 'edit-datasource';
}
}, [cardContext === null || cardContext === void 0 ? void 0 : cardContext.store, datasourceId, url]);
const onEditDatasource = useCallback(() => {
if (editorView && datasourceId) {
editDatasource(datasourceId, editorAnalyticsApi, currentAppearance, extensionKey)(editorView.state, editorView.dispatch);
focusEditorView(editorView);
}
}, [currentAppearance, datasourceId, editorAnalyticsApi, editorView, extensionKey]);
switch (editVariant) {
case 'edit-link':
{
return jsx(Flex, {
gap: "space.050"
}, jsx(Button, {
testId: "edit-link",
onClick: onEditLink,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
}, jsx(FormattedMessage
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, linkToolbarMessages.editLink)), !editorExperiment('platform_editor_controls', 'variant1') && jsx(Separator, {
areAnyNewToolbarFlagsEnabled: false
}));
}
case 'edit-datasource':
{
return jsx(Flex, {
gap: "space.050"
}, jsx(Button, {
testId: "edit-datasource",
tooltipContent: intl.formatMessage(linkToolbarMessages.editDatasourceStandaloneTooltip),
onClick: onEditDatasource,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
}, jsx(FormattedMessage
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, linkToolbarMessages.editDatasourceStandalone)), !editorExperiment('platform_editor_controls', 'variant1') && jsx(Separator, {
areAnyNewToolbarFlagsEnabled: false
}));
}
case 'edit-dropdown':
{
const trigger = jsx(Flex, {
gap: "space.050"
}, jsx(Button, {
testId: "edit-dropdown-trigger",
iconAfter: jsx("span", {
css: dropdownExpandContainer
}, jsx(ChevronDownIcon, {
label: intl.formatMessage(messages.editDropdownTriggerTitle),
size: "small"
})),
onClick: toggleOpen,
selected: isOpen,
disabled: false,
ariaHasPopup: true,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
}, jsx(FormattedMessage
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, messages.editDropdownTriggerTitle)), !editorExperiment('platform_editor_controls', 'variant1') && jsx(Separator, {
areAnyNewToolbarFlagsEnabled: false
}));
return jsx(Flex, {
ref: containerRef
}, jsx(UiDropdown, {
mountTo: containerRef.current,
isOpen: isOpen,
handleClickOutside: onClose,
handleEscapeKeydown: onClose,
trigger: trigger,
scrollableElement: containerRef.current
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
arrowKeyNavigationProviderOptions: {
type: ArrowKeyNavigationType.MENU
}
}, jsx(ButtonItem, {
key: "edit.link",
onClick: onEditLink,
testId: "edit-dropdown-edit-link-item"
}, jsx(FormattedMessage
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, messages.editDropdownEditLinkTitle)), jsx(ButtonItem, {
key: "edit.datasource",
onClick: onEditDatasource,
testId: "edit-dropdown-edit-datasource-item"
}, jsx(FormattedMessage
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, messages.editDropdownEditDatasourceTitle))));
}
case 'none':
default:
return null;
}
};
const EditToolbarButtonWithUrl = props => {
const {
cardContext,
currentAppearance,
datasourceId: datasourceIdFromAdf,
editorAnalyticsApi,
editorView,
intl,
onLinkEditClick,
url,
areAnyNewToolbarFlagsEnabled
} = props;
const {
extensionKey,
datasourceId: datasourceIdFromUrl
} = useFetchDatasourceInfo({
isRegularCardNode: true,
url,
cardContext
});
const datasourceId = datasourceIdFromUrl !== null && datasourceIdFromUrl !== void 0 ? datasourceIdFromUrl : datasourceIdFromAdf;
const editVariant = useMemo(() => {
var _cardContext$store2, _urlState$error2;
if (!datasourceId || !isDatasourceConfigEditable(datasourceId)) {
return 'edit-link';
}
const urlState = cardContext === null || cardContext === void 0 ? void 0 : (_cardContext$store2 = cardContext.store) === null || _cardContext$store2 === void 0 ? void 0 : _cardContext$store2.getState()[url];
if ((urlState === null || urlState === void 0 ? void 0 : (_urlState$error2 = urlState.error) === null || _urlState$error2 === void 0 ? void 0 : _urlState$error2.kind) === 'fatal') {
return 'edit-link';
}
return 'edit-dropdown';
}, [cardContext === null || cardContext === void 0 ? void 0 : cardContext.store, datasourceId, url]);
return jsx(EditToolbarButtonPresentation, {
datasourceId: datasourceId,
currentAppearance: currentAppearance,
editorAnalyticsApi: editorAnalyticsApi,
editVariant: editVariant,
editorView: editorView,
extensionKey: extensionKey,
onLinkEditClick: onLinkEditClick,
intl: intl,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
});
};
const EditToolbarButtonWithDatasourceId = props => {
const {
currentAppearance,
editorAnalyticsApi,
editorView,
intl,
onLinkEditClick,
datasourceId,
node,
areAnyNewToolbarFlagsEnabled
} = props;
const fetchData = useMemo(() => {
try {
var _attrs$datasource$vie, _attrs$datasource$vie2;
const attrs = node.attrs;
const parameters = attrs.datasource.parameters;
const visibleColumnKeys = (_attrs$datasource$vie = attrs.datasource.views[0]) === null || _attrs$datasource$vie === void 0 ? void 0 : (_attrs$datasource$vie2 = _attrs$datasource$vie.properties) === null || _attrs$datasource$vie2 === void 0 ? void 0 : _attrs$datasource$vie2.columns.map(c => c.key);
return {
parameters,
visibleColumnKeys
};
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
}, [node.attrs]);
const {
extensionKey
} = useFetchDatasourceDataInfo({
datasourceId,
parameters: fetchData === null || fetchData === void 0 ? void 0 : fetchData.parameters,
visibleColumnKeys: fetchData === null || fetchData === void 0 ? void 0 : fetchData.visibleColumnKeys
});
const editVariant = useMemo(() => {
if (!datasourceId || !isDatasourceConfigEditable(datasourceId)) {
return 'none';
}
return 'edit-datasource';
}, [datasourceId]);
return jsx(EditToolbarButtonPresentation, {
datasourceId: datasourceId,
currentAppearance: currentAppearance,
editorAnalyticsApi: editorAnalyticsApi,
editVariant: editVariant,
editorView: editorView,
extensionKey: extensionKey,
onLinkEditClick: onLinkEditClick,
intl: intl,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
});
};
export const EditToolbarButton = props => {
const {
currentAppearance,
datasourceId,
editorAnalyticsApi,
editorView,
intl,
onLinkEditClick,
url,
areAnyNewToolbarFlagsEnabled
} = props;
const cardContext = useSmartLinkContext();
if (props.url) {
return jsx(EditToolbarButtonWithUrl, {
datasourceId: datasourceId,
url: props.url,
intl: intl,
editorAnalyticsApi: editorAnalyticsApi,
editorView: editorView,
cardContext: cardContext,
onLinkEditClick: onLinkEditClick,
currentAppearance: currentAppearance,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
});
}
if (props.datasourceId && props.node) {
return jsx(EditToolbarButtonWithDatasourceId, {
datasourceId: props.datasourceId,
node: props.node,
intl: intl,
editorAnalyticsApi: editorAnalyticsApi,
editorView: editorView,
onLinkEditClick: onLinkEditClick,
currentAppearance: currentAppearance,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
});
}
return jsx(EditToolbarButtonWithCardContext, {
datasourceId: datasourceId,
url: url,
intl: intl,
editorAnalyticsApi: editorAnalyticsApi,
editorView: editorView,
cardContext: cardContext,
onLinkEditClick: onLinkEditClick,
currentAppearance: currentAppearance,
areAnyNewToolbarFlagsEnabled: areAnyNewToolbarFlagsEnabled
});
};