@atlaskit/editor-plugin-extension
Version:
editor-plugin-extension plugin for @atlaskit/editor-core
152 lines (149 loc) • 6.62 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import React, { useEffect, useState } from 'react';
import { bind } from 'bind-event-listener';
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import ConfigPanel from './ConfigPanel';
import { useStateFromPromise } from './use-state-from-promise';
var getFieldsDefinitionFn = function getFieldsDefinitionFn(extensionManifest, nodeKey) {
if (extensionManifest && extensionManifest.modules.nodes && extensionManifest.modules.nodes[nodeKey] && extensionManifest.modules.nodes[nodeKey].getFieldsDefinition) {
return extensionManifest.modules.nodes[nodeKey].getFieldsDefinition;
}
};
// having the default value in the props instead of a reference will cause excessive rerenders
var defaultEmptyObject = {};
var FieldDefinitionsPromiseResolver = function FieldDefinitionsPromiseResolver(props) {
var extensionManifest = props.extensionManifest,
nodeKey = props.nodeKey,
extensionParameters = props.extensionParameters,
setErrorMessage = props.setErrorMessage;
var _useState = useState(undefined),
_useState2 = _slicedToArray(_useState, 2),
fields = _useState2[0],
setFields = _useState2[1];
// Event listener for Forge apps that have macro config.
// When an app generates a new config schema, we need to force a re-render
// of the config panel so that the UI reflects the new schema.
// Otherwise the panel renders a stale schema.
var _useState3 = useState(new Date()),
_useState4 = _slicedToArray(_useState3, 2),
forgeAppConfigLastUpdated = _useState4[0],
setForgeAppConfigLastUpdated = _useState4[1];
useEffect(function () {
if (extensionParameters !== null && extensionParameters !== void 0 && extensionParameters.extensionId && extensionParameters !== null && extensionParameters !== void 0 && extensionParameters.localId) {
var extensionId = extensionParameters.extensionId,
localId = extensionParameters.localId;
var id = "".concat(extensionId, "-").concat(localId);
var eventName = "forge.bridge.CONFIG_FORGE_DOC_UPDATED_".concat(id);
var handleForgeConfigUpdated = function handleForgeConfigUpdated() {
setForgeAppConfigLastUpdated(new Date());
};
var unbind = bind(window.document, {
type: eventName,
listener: handleForgeConfigUpdated
});
return function () {
unbind();
};
}
}, [extensionParameters]);
// Resolve the promise
// useStateFromPromise() has an issue which isn't compatible with
// DynamicFieldDefinitions when it returns a function as setState()
// will immediately run the function returned and pass it the currentState.
useEffect(function () {
if (!extensionManifest) {
return;
}
var promiseFn = getFieldsDefinitionFn(extensionManifest, nodeKey);
if (typeof promiseFn !== 'function') {
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
setFields(undefined);
return;
}
promiseFn(extensionParameters).catch(function (err) {
if (err && typeof err.message === 'string') {
setErrorMessage(err.message);
}
setFields(undefined);
}).then(function (value) {
if (Array.isArray(value)) {
// value: FieldDefinition[]
setFields(value);
} else if (typeof value === 'function') {
try {
// value: DynamicFieldDefinitions
var dynamicFields = value(extensionParameters);
setFields(dynamicFields);
} catch (err) {
if (err instanceof Error) {
setErrorMessage(err.message);
}
setFields(undefined);
}
} else {
// value: undefined
setFields(undefined);
}
});
}, [extensionManifest, nodeKey, extensionParameters, setErrorMessage, forgeAppConfigLastUpdated]);
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children(fields));
};
export default function FieldsLoader(_ref) {
var extensionType = _ref.extensionType,
extensionKey = _ref.extensionKey,
nodeKey = _ref.nodeKey,
extensionProvider = _ref.extensionProvider,
_ref$extensionParamet = _ref.extensionParameters,
extensionParameters = _ref$extensionParamet === void 0 ? defaultEmptyObject : _ref$extensionParamet,
_ref$parameters = _ref.parameters,
parameters = _ref$parameters === void 0 ? defaultEmptyObject : _ref$parameters,
autoSaveTrigger = _ref.autoSaveTrigger,
autoSaveReject = _ref.autoSaveReject,
closeOnEsc = _ref.closeOnEsc,
showHeader = _ref.showHeader,
featureFlags = _ref.featureFlags,
onChange = _ref.onChange,
onCancel = _ref.onCancel,
api = _ref.api,
usingObjectSidebarPanel = _ref.usingObjectSidebarPanel;
var _useStateFromPromise = useStateFromPromise(function () {
return extensionProvider.getExtension(extensionType, extensionKey);
}, [extensionProvider, extensionType, extensionKey]),
_useStateFromPromise2 = _slicedToArray(_useStateFromPromise, 1),
extensionManifest = _useStateFromPromise2[0];
var _useState5 = useState(null),
_useState6 = _slicedToArray(_useState5, 2),
errorMessage = _useState6[0],
setErrorMessage = _useState6[1];
var connectivityState = useSharedPluginStateSelector(api, 'connectivity.mode', {
disabled: editorExperiment('platform_editor_offline_editing_web', false)
});
return /*#__PURE__*/React.createElement(FieldDefinitionsPromiseResolver, {
setErrorMessage: setErrorMessage,
extensionManifest: extensionManifest,
nodeKey: nodeKey,
extensionParameters: extensionParameters
}, function (fields) {
return /*#__PURE__*/React.createElement(ConfigPanel, {
api: api,
extensionManifest: extensionManifest,
isLoading: !extensionManifest || errorMessage === null && !fields,
fields: fields,
parameters: parameters,
autoSaveTrigger: autoSaveTrigger,
autoSaveReject: autoSaveReject,
closeOnEsc: closeOnEsc,
showHeader: showHeader,
onChange: onChange,
onCancel: onCancel,
errorMessage: errorMessage,
featureFlags: featureFlags
// Remove below prop when cleaning platform_editor_ai_object_sidebar_injection FG
,
usingObjectSidebarPanel: usingObjectSidebarPanel,
disableFields: isOfflineMode(connectivityState)
});
});
}