@atlaskit/editor-plugin-card 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-card
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`b9a083dc04d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/b9a083dc04d) - [ux] Adds error boundaries specific to datasource in editor and renderer. Fallback to unsupported block if no url or inline if url
8
+
9
+ ## 0.3.9
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 0.3.8
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.DatasourceErrorBoundary = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
11
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
12
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
13
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
14
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
15
+ var _react = _interopRequireDefault(require("react"));
16
+ var _adfSchema = require("@atlaskit/adf-schema");
17
+ var _doc = require("./pm-plugins/doc");
18
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
19
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /* eslint-disable @repo/internal/react/no-class-components */
20
+ var DatasourceErrorBoundary = /*#__PURE__*/function (_React$Component) {
21
+ (0, _inherits2.default)(DatasourceErrorBoundary, _React$Component);
22
+ var _super = _createSuper(DatasourceErrorBoundary);
23
+ function DatasourceErrorBoundary() {
24
+ var _this;
25
+ (0, _classCallCheck2.default)(this, DatasourceErrorBoundary);
26
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
27
+ args[_key] = arguments[_key];
28
+ }
29
+ _this = _super.call.apply(_super, [this].concat(args));
30
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", {
31
+ isError: false
32
+ });
33
+ return _this;
34
+ }
35
+ (0, _createClass2.default)(DatasourceErrorBoundary, [{
36
+ key: "componentDidCatch",
37
+ value: function componentDidCatch(error) {
38
+ this.props.handleError();
39
+ // prevent re-render children with error
40
+ if (this.state.isError) {
41
+ this.setState({
42
+ isError: true
43
+ });
44
+ }
45
+ }
46
+ }, {
47
+ key: "render",
48
+ value: function render() {
49
+ var _this$props = this.props,
50
+ url = _this$props.url,
51
+ UnsupportedComponent = _this$props.unsupportedComponent,
52
+ view = _this$props.view;
53
+ if (this.state.isError) {
54
+ if (url && (0, _adfSchema.isSafeUrl)(url)) {
55
+ return (0, _doc.setSelectedCardAppearance)('inline', undefined)(view.state, view.dispatch);
56
+ }
57
+ return /*#__PURE__*/_react.default.createElement(UnsupportedComponent, null);
58
+ }
59
+ return this.props.children;
60
+ }
61
+ }], [{
62
+ key: "getDerivedStateFromError",
63
+ value: function getDerivedStateFromError(error) {
64
+ return {
65
+ isError: true
66
+ };
67
+ }
68
+ }]);
69
+ return DatasourceErrorBoundary;
70
+ }(_react.default.Component);
71
+ exports.DatasourceErrorBoundary = DatasourceErrorBoundary;
@@ -17,12 +17,25 @@ var _react2 = require("@emotion/react");
17
17
  var _propTypes = _interopRequireDefault(require("prop-types"));
18
18
  var _reactNodeView = _interopRequireDefault(require("@atlaskit/editor-common/react-node-view"));
19
19
  var _styles = require("@atlaskit/editor-common/styles");
20
+ var _ui = require("@atlaskit/editor-common/ui");
20
21
  var _utils = require("@atlaskit/editor-common/utils");
21
22
  var _linkDatasource = require("@atlaskit/link-datasource");
23
+ var _datasourceErrorBoundary = require("../datasourceErrorBoundary");
24
+ var _doc = require("../pm-plugins/doc");
22
25
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
23
26
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
24
27
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
25
28
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /** @jsx jsx */
29
+ var getPosSafely = function getPosSafely(pos) {
30
+ if (!pos || typeof pos === 'boolean') {
31
+ return;
32
+ }
33
+ try {
34
+ return pos();
35
+ } catch (e) {
36
+ // Can blow up in rare cases, when node has been removed.
37
+ }
38
+ };
26
39
  // eslint-disable-next-line @repo/internal/react/no-class-components
27
40
  var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
28
41
  (0, _inherits2.default)(DatasourceComponent, _React$PureComponent);
@@ -31,17 +44,6 @@ var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
31
44
  var _this;
32
45
  (0, _classCallCheck2.default)(this, DatasourceComponent);
33
46
  _this = _super.call(this, props);
34
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getPosSafely", function () {
35
- var getPos = _this.props.getPos;
36
- if (!getPos || typeof getPos === 'boolean') {
37
- return;
38
- }
39
- try {
40
- return getPos();
41
- } catch (e) {
42
- // Can blow up in rare cases, when node has been removed.
43
- }
44
- });
45
47
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getDatasource", function () {
46
48
  return _this.props.node.attrs.datasource;
47
49
  });
@@ -55,7 +57,7 @@ var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
55
57
  var _this$props$view = _this.props.view,
56
58
  state = _this$props$view.state,
57
59
  dispatch = _this$props$view.dispatch;
58
- var pos = _this.getPosSafely();
60
+ var pos = getPosSafely(_this.props.getPos);
59
61
  if (pos === undefined) {
60
62
  return;
61
63
  }
@@ -78,6 +80,12 @@ var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
78
80
  tr.setMeta('scrollIntoView', false);
79
81
  dispatch(tr);
80
82
  });
83
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onError", function (_ref) {
84
+ var err = _ref.err;
85
+ if (err) {
86
+ throw err;
87
+ }
88
+ });
81
89
  return _this;
82
90
  }
83
91
  (0, _createClass2.default)(DatasourceComponent, [{
@@ -88,8 +96,8 @@ var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
88
96
  var tableView = this.getTableView();
89
97
  if (tableView) {
90
98
  var _tableView$properties;
91
- var visibleColumnKeys = (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns.map(function (_ref) {
92
- var key = _ref.key;
99
+ var visibleColumnKeys = (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns.map(function (_ref2) {
100
+ var key = _ref2.key;
93
101
  return key;
94
102
  });
95
103
 
@@ -122,10 +130,27 @@ var Datasource = /*#__PURE__*/function (_ReactNodeView) {
122
130
  var _this2;
123
131
  (0, _classCallCheck2.default)(this, Datasource);
124
132
  _this2 = _super2.call(this, props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props, undefined, true, undefined, props.hasIntlContext);
133
+ // this is necessary so that the datasource toolbar won't be rendered on error
134
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this2), "updateNodeRemoveAttrs", function () {
135
+ var url = _this2.node.attrs.url;
136
+ var _this2$view = _this2.view,
137
+ state = _this2$view.state,
138
+ dispatch = _this2$view.dispatch;
139
+ var pos = getPosSafely(_this2.getPos);
140
+ if (pos === undefined) {
141
+ return;
142
+ }
143
+ var nodeType = (0, _doc.getLinkNodeType)('inline', state.schema.nodes);
144
+ var tr = state.tr.setNodeMarkup(pos, nodeType, {
145
+ url: url
146
+ });
147
+ tr.setMeta('scrollIntoView', false);
148
+ return dispatch(tr);
149
+ });
125
150
  var sharedState = props === null || props === void 0 ? void 0 : (_props$pluginInjectio = props.pluginInjectionApi) === null || _props$pluginInjectio === void 0 ? void 0 : (_props$pluginInjectio2 = _props$pluginInjectio.dependencies) === null || _props$pluginInjectio2 === void 0 ? void 0 : (_props$pluginInjectio3 = _props$pluginInjectio2.width) === null || _props$pluginInjectio3 === void 0 ? void 0 : _props$pluginInjectio3.sharedState;
126
151
  _this2.tableWidth = sharedState === null || sharedState === void 0 ? void 0 : (_sharedState$currentS = sharedState.currentState()) === null || _sharedState$currentS === void 0 ? void 0 : _sharedState$currentS.width;
127
- sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(function (_ref2) {
128
- var nextSharedState = _ref2.nextSharedState;
152
+ sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(function (_ref3) {
153
+ var nextSharedState = _ref3.nextSharedState;
129
154
  if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.width && _this2.tableWidth !== (nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width)) {
130
155
  _this2.tableWidth = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width;
131
156
  _this2.update(_this2.node, []); // required to update the width when page is resized.
@@ -144,7 +169,12 @@ var Datasource = /*#__PURE__*/function (_ReactNodeView) {
144
169
  key: "render",
145
170
  value: function render() {
146
171
  var attrs = this.node.attrs;
147
- return (0, _react2.jsx)("div", {
172
+ return (0, _react2.jsx)(_datasourceErrorBoundary.DatasourceErrorBoundary, {
173
+ handleError: this.updateNodeRemoveAttrs,
174
+ unsupportedComponent: _ui.UnsupportedInline,
175
+ view: this.view,
176
+ url: attrs.url
177
+ }, (0, _react2.jsx)("div", {
148
178
  className: _styles.DATASOURCE_INNER_CONTAINER_CLASSNAME,
149
179
  style: {
150
180
  minWidth: (0, _utils.calcBreakoutWidth)(attrs.layout, this.tableWidth)
@@ -153,7 +183,7 @@ var Datasource = /*#__PURE__*/function (_ReactNodeView) {
153
183
  node: this.node,
154
184
  view: this.view,
155
185
  getPos: this.getPos
156
- }));
186
+ })));
157
187
  }
158
188
  }]);
159
189
  return Datasource;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.updateExistingDatasource = exports.updateCard = exports.setSelectedCardAppearance = exports.replaceQueuedUrlWithCard = exports.queueCardsFromChangedTr = exports.queueCardFromChangedTr = exports.insertDatasource = exports.handleFallbackWithAnalytics = exports.convertHyperlinkToSmartCard = exports.changeSelectedCardToText = exports.changeSelectedCardToLinkFallback = exports.changeSelectedCardToLink = void 0;
7
+ exports.updateExistingDatasource = exports.updateCard = exports.setSelectedCardAppearance = exports.replaceQueuedUrlWithCard = exports.queueCardsFromChangedTr = exports.queueCardFromChangedTr = exports.insertDatasource = exports.handleFallbackWithAnalytics = exports.getLinkNodeType = exports.convertHyperlinkToSmartCard = exports.changeSelectedCardToText = exports.changeSelectedCardToLinkFallback = exports.changeSelectedCardToLink = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
@@ -429,6 +429,7 @@ var getLinkNodeType = function getLinkNodeType(appearance, linkNodes) {
429
429
  };
430
430
 
431
431
  // Apply an update to a datasource (aka blockCard) node
432
+ exports.getLinkNodeType = getLinkNodeType;
432
433
  var updateExistingDatasource = function updateExistingDatasource(state, node, newAdf, view) {
433
434
  var tr = state.tr,
434
435
  from = state.selection.from,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-card",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,41 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ /* eslint-disable @repo/internal/react/no-class-components */
3
+ import React from 'react';
4
+ import { isSafeUrl } from '@atlaskit/adf-schema';
5
+ import { setSelectedCardAppearance } from './pm-plugins/doc';
6
+ export class DatasourceErrorBoundary extends React.Component {
7
+ constructor(...args) {
8
+ super(...args);
9
+ _defineProperty(this, "state", {
10
+ isError: false
11
+ });
12
+ }
13
+ static getDerivedStateFromError(error) {
14
+ return {
15
+ isError: true
16
+ };
17
+ }
18
+ componentDidCatch(error) {
19
+ this.props.handleError();
20
+ // prevent re-render children with error
21
+ if (this.state.isError) {
22
+ this.setState({
23
+ isError: true
24
+ });
25
+ }
26
+ }
27
+ render() {
28
+ const {
29
+ url,
30
+ unsupportedComponent: UnsupportedComponent,
31
+ view
32
+ } = this.props;
33
+ if (this.state.isError) {
34
+ if (url && isSafeUrl(url)) {
35
+ return setSelectedCardAppearance('inline', undefined)(view.state, view.dispatch);
36
+ }
37
+ return /*#__PURE__*/React.createElement(UnsupportedComponent, null);
38
+ }
39
+ return this.props.children;
40
+ }
41
+ }
@@ -5,25 +5,25 @@ import { jsx } from '@emotion/react';
5
5
  import PropTypes from 'prop-types';
6
6
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
7
7
  import { DATASOURCE_INNER_CONTAINER_CLASSNAME, SmartCardSharedCssClassName } from '@atlaskit/editor-common/styles';
8
+ import { UnsupportedInline } from '@atlaskit/editor-common/ui';
8
9
  import { calcBreakoutWidth } from '@atlaskit/editor-common/utils';
9
10
  import { DatasourceTableView } from '@atlaskit/link-datasource';
11
+ import { DatasourceErrorBoundary } from '../datasourceErrorBoundary';
12
+ import { getLinkNodeType } from '../pm-plugins/doc';
13
+ const getPosSafely = pos => {
14
+ if (!pos || typeof pos === 'boolean') {
15
+ return;
16
+ }
17
+ try {
18
+ return pos();
19
+ } catch (e) {
20
+ // Can blow up in rare cases, when node has been removed.
21
+ }
22
+ };
10
23
  // eslint-disable-next-line @repo/internal/react/no-class-components
11
24
  export class DatasourceComponent extends React.PureComponent {
12
25
  constructor(props) {
13
26
  super(props);
14
- _defineProperty(this, "getPosSafely", () => {
15
- const {
16
- getPos
17
- } = this.props;
18
- if (!getPos || typeof getPos === 'boolean') {
19
- return;
20
- }
21
- try {
22
- return getPos();
23
- } catch (e) {
24
- // Can blow up in rare cases, when node has been removed.
25
- }
26
- });
27
27
  _defineProperty(this, "getDatasource", () => this.props.node.attrs.datasource);
28
28
  _defineProperty(this, "getTableView", datasource => {
29
29
  const views = (datasource || this.getDatasource()).views;
@@ -34,7 +34,7 @@ export class DatasourceComponent extends React.PureComponent {
34
34
  state,
35
35
  dispatch
36
36
  } = this.props.view;
37
- const pos = this.getPosSafely();
37
+ const pos = getPosSafely(this.props.getPos);
38
38
  if (pos === undefined) {
39
39
  return;
40
40
  }
@@ -57,6 +57,13 @@ export class DatasourceComponent extends React.PureComponent {
57
57
  tr.setMeta('scrollIntoView', false);
58
58
  dispatch(tr);
59
59
  });
60
+ _defineProperty(this, "onError", ({
61
+ err
62
+ }) => {
63
+ if (err) {
64
+ throw err;
65
+ }
66
+ });
60
67
  }
61
68
  render() {
62
69
  const cardContext = this.context.contextAdapter ? this.context.contextAdapter.card : undefined;
@@ -90,6 +97,26 @@ export class Datasource extends ReactNodeView {
90
97
  constructor(props) {
91
98
  var _props$pluginInjectio, _props$pluginInjectio2, _props$pluginInjectio3, _sharedState$currentS;
92
99
  super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props, undefined, true, undefined, props.hasIntlContext);
100
+ // this is necessary so that the datasource toolbar won't be rendered on error
101
+ _defineProperty(this, "updateNodeRemoveAttrs", () => {
102
+ const {
103
+ url
104
+ } = this.node.attrs;
105
+ const {
106
+ state,
107
+ dispatch
108
+ } = this.view;
109
+ const pos = getPosSafely(this.getPos);
110
+ if (pos === undefined) {
111
+ return;
112
+ }
113
+ const nodeType = getLinkNodeType('inline', state.schema.nodes);
114
+ const tr = state.tr.setNodeMarkup(pos, nodeType, {
115
+ url
116
+ });
117
+ tr.setMeta('scrollIntoView', false);
118
+ return dispatch(tr);
119
+ });
93
120
  const sharedState = props === null || props === void 0 ? void 0 : (_props$pluginInjectio = props.pluginInjectionApi) === null || _props$pluginInjectio === void 0 ? void 0 : (_props$pluginInjectio2 = _props$pluginInjectio.dependencies) === null || _props$pluginInjectio2 === void 0 ? void 0 : (_props$pluginInjectio3 = _props$pluginInjectio2.width) === null || _props$pluginInjectio3 === void 0 ? void 0 : _props$pluginInjectio3.sharedState;
94
121
  this.tableWidth = sharedState === null || sharedState === void 0 ? void 0 : (_sharedState$currentS = sharedState.currentState()) === null || _sharedState$currentS === void 0 ? void 0 : _sharedState$currentS.width;
95
122
  sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(({
@@ -111,7 +138,12 @@ export class Datasource extends ReactNodeView {
111
138
  const {
112
139
  attrs
113
140
  } = this.node;
114
- return jsx("div", {
141
+ return jsx(DatasourceErrorBoundary, {
142
+ handleError: this.updateNodeRemoveAttrs,
143
+ unsupportedComponent: UnsupportedInline,
144
+ view: this.view,
145
+ url: attrs.url
146
+ }, jsx("div", {
115
147
  className: DATASOURCE_INNER_CONTAINER_CLASSNAME,
116
148
  style: {
117
149
  minWidth: calcBreakoutWidth(attrs.layout, this.tableWidth)
@@ -120,6 +152,6 @@ export class Datasource extends ReactNodeView {
120
152
  node: this.node,
121
153
  view: this.view,
122
154
  getPos: this.getPos
123
- }));
155
+ })));
124
156
  }
125
157
  }
@@ -382,7 +382,7 @@ export const setSelectedCardAppearance = (appearance, editorAnalyticsApi) => (st
382
382
  }
383
383
  return true;
384
384
  };
385
- const getLinkNodeType = (appearance, linkNodes) => {
385
+ export const getLinkNodeType = (appearance, linkNodes) => {
386
386
  switch (appearance) {
387
387
  case 'inline':
388
388
  return linkNodes.inlineCard;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-card",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,64 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
6
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
7
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
8
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
9
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
10
+ /* eslint-disable @repo/internal/react/no-class-components */
11
+ import React from 'react';
12
+ import { isSafeUrl } from '@atlaskit/adf-schema';
13
+ import { setSelectedCardAppearance } from './pm-plugins/doc';
14
+ export var DatasourceErrorBoundary = /*#__PURE__*/function (_React$Component) {
15
+ _inherits(DatasourceErrorBoundary, _React$Component);
16
+ var _super = _createSuper(DatasourceErrorBoundary);
17
+ function DatasourceErrorBoundary() {
18
+ var _this;
19
+ _classCallCheck(this, DatasourceErrorBoundary);
20
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
21
+ args[_key] = arguments[_key];
22
+ }
23
+ _this = _super.call.apply(_super, [this].concat(args));
24
+ _defineProperty(_assertThisInitialized(_this), "state", {
25
+ isError: false
26
+ });
27
+ return _this;
28
+ }
29
+ _createClass(DatasourceErrorBoundary, [{
30
+ key: "componentDidCatch",
31
+ value: function componentDidCatch(error) {
32
+ this.props.handleError();
33
+ // prevent re-render children with error
34
+ if (this.state.isError) {
35
+ this.setState({
36
+ isError: true
37
+ });
38
+ }
39
+ }
40
+ }, {
41
+ key: "render",
42
+ value: function render() {
43
+ var _this$props = this.props,
44
+ url = _this$props.url,
45
+ UnsupportedComponent = _this$props.unsupportedComponent,
46
+ view = _this$props.view;
47
+ if (this.state.isError) {
48
+ if (url && isSafeUrl(url)) {
49
+ return setSelectedCardAppearance('inline', undefined)(view.state, view.dispatch);
50
+ }
51
+ return /*#__PURE__*/React.createElement(UnsupportedComponent, null);
52
+ }
53
+ return this.props.children;
54
+ }
55
+ }], [{
56
+ key: "getDerivedStateFromError",
57
+ value: function getDerivedStateFromError(error) {
58
+ return {
59
+ isError: true
60
+ };
61
+ }
62
+ }]);
63
+ return DatasourceErrorBoundary;
64
+ }(React.Component);
@@ -15,8 +15,21 @@ import { jsx } from '@emotion/react';
15
15
  import PropTypes from 'prop-types';
16
16
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
17
17
  import { DATASOURCE_INNER_CONTAINER_CLASSNAME, SmartCardSharedCssClassName } from '@atlaskit/editor-common/styles';
18
+ import { UnsupportedInline } from '@atlaskit/editor-common/ui';
18
19
  import { calcBreakoutWidth } from '@atlaskit/editor-common/utils';
19
20
  import { DatasourceTableView } from '@atlaskit/link-datasource';
21
+ import { DatasourceErrorBoundary } from '../datasourceErrorBoundary';
22
+ import { getLinkNodeType } from '../pm-plugins/doc';
23
+ var getPosSafely = function getPosSafely(pos) {
24
+ if (!pos || typeof pos === 'boolean') {
25
+ return;
26
+ }
27
+ try {
28
+ return pos();
29
+ } catch (e) {
30
+ // Can blow up in rare cases, when node has been removed.
31
+ }
32
+ };
20
33
  // eslint-disable-next-line @repo/internal/react/no-class-components
21
34
  export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
22
35
  _inherits(DatasourceComponent, _React$PureComponent);
@@ -25,17 +38,6 @@ export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
25
38
  var _this;
26
39
  _classCallCheck(this, DatasourceComponent);
27
40
  _this = _super.call(this, props);
28
- _defineProperty(_assertThisInitialized(_this), "getPosSafely", function () {
29
- var getPos = _this.props.getPos;
30
- if (!getPos || typeof getPos === 'boolean') {
31
- return;
32
- }
33
- try {
34
- return getPos();
35
- } catch (e) {
36
- // Can blow up in rare cases, when node has been removed.
37
- }
38
- });
39
41
  _defineProperty(_assertThisInitialized(_this), "getDatasource", function () {
40
42
  return _this.props.node.attrs.datasource;
41
43
  });
@@ -49,7 +51,7 @@ export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
49
51
  var _this$props$view = _this.props.view,
50
52
  state = _this$props$view.state,
51
53
  dispatch = _this$props$view.dispatch;
52
- var pos = _this.getPosSafely();
54
+ var pos = getPosSafely(_this.props.getPos);
53
55
  if (pos === undefined) {
54
56
  return;
55
57
  }
@@ -72,6 +74,12 @@ export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
72
74
  tr.setMeta('scrollIntoView', false);
73
75
  dispatch(tr);
74
76
  });
77
+ _defineProperty(_assertThisInitialized(_this), "onError", function (_ref) {
78
+ var err = _ref.err;
79
+ if (err) {
80
+ throw err;
81
+ }
82
+ });
75
83
  return _this;
76
84
  }
77
85
  _createClass(DatasourceComponent, [{
@@ -82,8 +90,8 @@ export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
82
90
  var tableView = this.getTableView();
83
91
  if (tableView) {
84
92
  var _tableView$properties;
85
- var visibleColumnKeys = (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns.map(function (_ref) {
86
- var key = _ref.key;
93
+ var visibleColumnKeys = (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns.map(function (_ref2) {
94
+ var key = _ref2.key;
87
95
  return key;
88
96
  });
89
97
 
@@ -115,10 +123,27 @@ export var Datasource = /*#__PURE__*/function (_ReactNodeView) {
115
123
  var _this2;
116
124
  _classCallCheck(this, Datasource);
117
125
  _this2 = _super2.call(this, props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props, undefined, true, undefined, props.hasIntlContext);
126
+ // this is necessary so that the datasource toolbar won't be rendered on error
127
+ _defineProperty(_assertThisInitialized(_this2), "updateNodeRemoveAttrs", function () {
128
+ var url = _this2.node.attrs.url;
129
+ var _this2$view = _this2.view,
130
+ state = _this2$view.state,
131
+ dispatch = _this2$view.dispatch;
132
+ var pos = getPosSafely(_this2.getPos);
133
+ if (pos === undefined) {
134
+ return;
135
+ }
136
+ var nodeType = getLinkNodeType('inline', state.schema.nodes);
137
+ var tr = state.tr.setNodeMarkup(pos, nodeType, {
138
+ url: url
139
+ });
140
+ tr.setMeta('scrollIntoView', false);
141
+ return dispatch(tr);
142
+ });
118
143
  var sharedState = props === null || props === void 0 ? void 0 : (_props$pluginInjectio = props.pluginInjectionApi) === null || _props$pluginInjectio === void 0 ? void 0 : (_props$pluginInjectio2 = _props$pluginInjectio.dependencies) === null || _props$pluginInjectio2 === void 0 ? void 0 : (_props$pluginInjectio3 = _props$pluginInjectio2.width) === null || _props$pluginInjectio3 === void 0 ? void 0 : _props$pluginInjectio3.sharedState;
119
144
  _this2.tableWidth = sharedState === null || sharedState === void 0 ? void 0 : (_sharedState$currentS = sharedState.currentState()) === null || _sharedState$currentS === void 0 ? void 0 : _sharedState$currentS.width;
120
- sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(function (_ref2) {
121
- var nextSharedState = _ref2.nextSharedState;
145
+ sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(function (_ref3) {
146
+ var nextSharedState = _ref3.nextSharedState;
122
147
  if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.width && _this2.tableWidth !== (nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width)) {
123
148
  _this2.tableWidth = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width;
124
149
  _this2.update(_this2.node, []); // required to update the width when page is resized.
@@ -137,7 +162,12 @@ export var Datasource = /*#__PURE__*/function (_ReactNodeView) {
137
162
  key: "render",
138
163
  value: function render() {
139
164
  var attrs = this.node.attrs;
140
- return jsx("div", {
165
+ return jsx(DatasourceErrorBoundary, {
166
+ handleError: this.updateNodeRemoveAttrs,
167
+ unsupportedComponent: UnsupportedInline,
168
+ view: this.view,
169
+ url: attrs.url
170
+ }, jsx("div", {
141
171
  className: DATASOURCE_INNER_CONTAINER_CLASSNAME,
142
172
  style: {
143
173
  minWidth: calcBreakoutWidth(attrs.layout, this.tableWidth)
@@ -146,7 +176,7 @@ export var Datasource = /*#__PURE__*/function (_ReactNodeView) {
146
176
  node: this.node,
147
177
  view: this.view,
148
178
  getPos: this.getPos
149
- }));
179
+ })));
150
180
  }
151
181
  }]);
152
182
  return Datasource;
@@ -400,7 +400,7 @@ export var setSelectedCardAppearance = function setSelectedCardAppearance(appear
400
400
  return true;
401
401
  };
402
402
  };
403
- var getLinkNodeType = function getLinkNodeType(appearance, linkNodes) {
403
+ export var getLinkNodeType = function getLinkNodeType(appearance, linkNodes) {
404
404
  switch (appearance) {
405
405
  case 'inline':
406
406
  return linkNodes.inlineCard;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-card",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { APIError } from '@atlaskit/smart-card';
3
+ import { DatasourceProps } from './nodeviews/datasource';
4
+ export declare class DatasourceErrorBoundary extends React.Component<{
5
+ url?: string;
6
+ unsupportedComponent: React.ComponentType;
7
+ handleError: () => void;
8
+ view: DatasourceProps['view'];
9
+ }> {
10
+ state: {
11
+ isError: boolean;
12
+ };
13
+ static getDerivedStateFromError(error: Error | APIError): {
14
+ isError: boolean;
15
+ };
16
+ componentDidCatch(error: Error | APIError): void;
17
+ render(): React.ReactNode;
18
+ }
@@ -9,7 +9,7 @@ import { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
9
9
  import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
10
10
  import { EditorView } from '@atlaskit/editor-prosemirror/view';
11
11
  import type { cardPlugin } from '../index';
12
- interface DatasourceProps extends ReactComponentProps {
12
+ export interface DatasourceProps extends ReactComponentProps {
13
13
  node: PMNode;
14
14
  view: EditorView;
15
15
  getPos: getPosHandler;
@@ -25,15 +25,18 @@ export declare class DatasourceComponent extends React.PureComponent<DatasourceC
25
25
  contextAdapter: PropTypes.Requireable<object>;
26
26
  };
27
27
  constructor(props: DatasourceComponentProps);
28
- private getPosSafely;
29
28
  private getDatasource;
30
29
  private getTableView;
31
30
  handleColumnChange: (columnKeys: string[]) => void;
31
+ onError: ({ err }: {
32
+ err?: Error | undefined;
33
+ }) => void;
32
34
  render(): jsx.JSX.Element | null;
33
35
  }
34
36
  export declare class Datasource extends ReactNodeView<DatasourceProps> {
35
37
  private tableWidth;
36
38
  constructor(props: DatasourceProps);
39
+ updateNodeRemoveAttrs: () => void;
37
40
  createDomRef(): HTMLElement;
38
41
  render(): jsx.JSX.Element;
39
42
  }
@@ -3,7 +3,7 @@ import { ACTION, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { CardReplacementInputMethod } from '@atlaskit/editor-common/card';
4
4
  import { CardAdf, CardAppearance, DatasourceAdf } from '@atlaskit/editor-common/provider-factory';
5
5
  import type { Command } from '@atlaskit/editor-common/types';
6
- import { Node } from '@atlaskit/editor-prosemirror/model';
6
+ import { Node, NodeType } from '@atlaskit/editor-prosemirror/model';
7
7
  import { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
8
8
  import { EditorView } from '@atlaskit/editor-prosemirror/view';
9
9
  import type { InlineCardAdf } from '@atlaskit/smart-card';
@@ -18,5 +18,9 @@ export declare const changeSelectedCardToLinkFallback: (text?: string, href?: st
18
18
  export declare const updateCard: (href: string, sourceEvent?: UIAnalyticsEvent | null | undefined) => Command;
19
19
  export declare const changeSelectedCardToText: (text: string, editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
20
20
  export declare const setSelectedCardAppearance: (appearance: CardAppearance, editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
21
+ export type LinkNodes = {
22
+ [key in 'inlineCard' | 'blockCard' | 'embedCard']: NodeType;
23
+ };
24
+ export declare const getLinkNodeType: (appearance: CardAppearance, linkNodes: LinkNodes) => NodeType;
21
25
  export declare const updateExistingDatasource: (state: EditorState, node: Node, newAdf: DatasourceAdf | InlineCardAdf, view: EditorView) => void;
22
26
  export declare const insertDatasource: (state: EditorState, adf: DatasourceAdf | InlineCardAdf, view: EditorView) => void;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { APIError } from '@atlaskit/smart-card';
3
+ import { DatasourceProps } from './nodeviews/datasource';
4
+ export declare class DatasourceErrorBoundary extends React.Component<{
5
+ url?: string;
6
+ unsupportedComponent: React.ComponentType;
7
+ handleError: () => void;
8
+ view: DatasourceProps['view'];
9
+ }> {
10
+ state: {
11
+ isError: boolean;
12
+ };
13
+ static getDerivedStateFromError(error: Error | APIError): {
14
+ isError: boolean;
15
+ };
16
+ componentDidCatch(error: Error | APIError): void;
17
+ render(): React.ReactNode;
18
+ }
@@ -9,7 +9,7 @@ import { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
9
9
  import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
10
10
  import { EditorView } from '@atlaskit/editor-prosemirror/view';
11
11
  import type { cardPlugin } from '../index';
12
- interface DatasourceProps extends ReactComponentProps {
12
+ export interface DatasourceProps extends ReactComponentProps {
13
13
  node: PMNode;
14
14
  view: EditorView;
15
15
  getPos: getPosHandler;
@@ -25,15 +25,18 @@ export declare class DatasourceComponent extends React.PureComponent<DatasourceC
25
25
  contextAdapter: PropTypes.Requireable<object>;
26
26
  };
27
27
  constructor(props: DatasourceComponentProps);
28
- private getPosSafely;
29
28
  private getDatasource;
30
29
  private getTableView;
31
30
  handleColumnChange: (columnKeys: string[]) => void;
31
+ onError: ({ err }: {
32
+ err?: Error | undefined;
33
+ }) => void;
32
34
  render(): jsx.JSX.Element | null;
33
35
  }
34
36
  export declare class Datasource extends ReactNodeView<DatasourceProps> {
35
37
  private tableWidth;
36
38
  constructor(props: DatasourceProps);
39
+ updateNodeRemoveAttrs: () => void;
37
40
  createDomRef(): HTMLElement;
38
41
  render(): jsx.JSX.Element;
39
42
  }
@@ -3,7 +3,7 @@ import { ACTION, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { CardReplacementInputMethod } from '@atlaskit/editor-common/card';
4
4
  import { CardAdf, CardAppearance, DatasourceAdf } from '@atlaskit/editor-common/provider-factory';
5
5
  import type { Command } from '@atlaskit/editor-common/types';
6
- import { Node } from '@atlaskit/editor-prosemirror/model';
6
+ import { Node, NodeType } from '@atlaskit/editor-prosemirror/model';
7
7
  import { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
8
8
  import { EditorView } from '@atlaskit/editor-prosemirror/view';
9
9
  import type { InlineCardAdf } from '@atlaskit/smart-card';
@@ -18,5 +18,9 @@ export declare const changeSelectedCardToLinkFallback: (text?: string, href?: st
18
18
  export declare const updateCard: (href: string, sourceEvent?: UIAnalyticsEvent | null | undefined) => Command;
19
19
  export declare const changeSelectedCardToText: (text: string, editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
20
20
  export declare const setSelectedCardAppearance: (appearance: CardAppearance, editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
21
+ export type LinkNodes = {
22
+ [key in 'inlineCard' | 'blockCard' | 'embedCard']: NodeType;
23
+ };
24
+ export declare const getLinkNodeType: (appearance: CardAppearance, linkNodes: LinkNodes) => NodeType;
21
25
  export declare const updateExistingDatasource: (state: EditorState, node: Node, newAdf: DatasourceAdf | InlineCardAdf, view: EditorView) => void;
22
26
  export declare const insertDatasource: (state: EditorState, adf: DatasourceAdf | InlineCardAdf, view: EditorView) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-card",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "Card plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,9 +31,9 @@
31
31
  ".": "./src/index.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@atlaskit/adf-schema": "^26.4.0",
34
+ "@atlaskit/adf-schema": "^27.0.0",
35
35
  "@atlaskit/analytics-next": "^9.1.0",
36
- "@atlaskit/editor-common": "^74.34.0",
36
+ "@atlaskit/editor-common": "^74.36.0",
37
37
  "@atlaskit/editor-plugin-analytics": "^0.1.0",
38
38
  "@atlaskit/editor-plugin-decorations": "^0.1.0",
39
39
  "@atlaskit/editor-plugin-feature-flags": "^0.1.0",
@@ -42,12 +42,12 @@
42
42
  "@atlaskit/editor-plugin-hyperlink": "^0.2.0",
43
43
  "@atlaskit/editor-plugin-width": "^0.1.0",
44
44
  "@atlaskit/editor-prosemirror": "1.0.2",
45
- "@atlaskit/editor-shared-styles": "^2.5.0",
45
+ "@atlaskit/editor-shared-styles": "^2.6.0",
46
46
  "@atlaskit/icon": "^21.12.0",
47
47
  "@atlaskit/link-analytics": "^8.2.0",
48
48
  "@atlaskit/link-datasource": "^0.33.0",
49
49
  "@atlaskit/platform-feature-flags": "^0.2.0",
50
- "@atlaskit/smart-card": "^26.14.0",
50
+ "@atlaskit/smart-card": "^26.15.0",
51
51
  "@atlaskit/theme": "^12.5.0",
52
52
  "@atlaskit/tokens": "^1.14.0",
53
53
  "@babel/runtime": "^7.0.0",