@atlaskit/link-create 1.9.5 → 1.11.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/analytics.spec.yaml +29 -3
  3. package/dist/cjs/common/messages.js +14 -0
  4. package/dist/cjs/common/ui/error-boundary-ui/index.js +4 -3
  5. package/dist/cjs/common/ui/error-boundary-ui/messages.js +0 -5
  6. package/dist/cjs/common/utils/analytics/analytics.codegen.js +1 -1
  7. package/dist/cjs/common/utils/errors/index.js +39 -0
  8. package/dist/cjs/controllers/callback-context/main.js +23 -7
  9. package/dist/cjs/controllers/experience-tracker/index.js +85 -0
  10. package/dist/cjs/index.js +7 -0
  11. package/dist/cjs/ui/create-form/async-select/main.js +62 -20
  12. package/dist/cjs/ui/create-form/form-footer/edit-button/index.js +1 -1
  13. package/dist/cjs/ui/create-form/form-footer/edit-button/messages.js +4 -4
  14. package/dist/cjs/ui/create-form/main.js +62 -7
  15. package/dist/cjs/ui/link-create/error-boundary/index.js +14 -9
  16. package/dist/cjs/ui/link-create/main.js +5 -3
  17. package/dist/cjs/ui/main.js +9 -9
  18. package/dist/es2019/common/messages.js +8 -0
  19. package/dist/es2019/common/ui/error-boundary-ui/index.js +2 -1
  20. package/dist/es2019/common/ui/error-boundary-ui/messages.js +0 -5
  21. package/dist/es2019/common/utils/analytics/analytics.codegen.js +1 -1
  22. package/dist/es2019/common/utils/errors/index.js +31 -0
  23. package/dist/es2019/controllers/callback-context/main.js +19 -3
  24. package/dist/es2019/controllers/experience-tracker/index.js +75 -0
  25. package/dist/es2019/index.js +1 -0
  26. package/dist/es2019/ui/create-form/async-select/main.js +32 -1
  27. package/dist/es2019/ui/create-form/form-footer/edit-button/index.js +1 -1
  28. package/dist/es2019/ui/create-form/form-footer/edit-button/messages.js +4 -4
  29. package/dist/es2019/ui/create-form/main.js +47 -3
  30. package/dist/es2019/ui/link-create/error-boundary/index.js +14 -9
  31. package/dist/es2019/ui/link-create/main.js +5 -3
  32. package/dist/es2019/ui/main.js +10 -9
  33. package/dist/esm/common/messages.js +8 -0
  34. package/dist/esm/common/ui/error-boundary-ui/index.js +2 -1
  35. package/dist/esm/common/ui/error-boundary-ui/messages.js +0 -5
  36. package/dist/esm/common/utils/analytics/analytics.codegen.js +1 -1
  37. package/dist/esm/common/utils/errors/index.js +32 -0
  38. package/dist/esm/controllers/callback-context/main.js +23 -7
  39. package/dist/esm/controllers/experience-tracker/index.js +75 -0
  40. package/dist/esm/index.js +1 -0
  41. package/dist/esm/ui/create-form/async-select/main.js +62 -20
  42. package/dist/esm/ui/create-form/form-footer/edit-button/index.js +1 -1
  43. package/dist/esm/ui/create-form/form-footer/edit-button/messages.js +4 -4
  44. package/dist/esm/ui/create-form/main.js +62 -7
  45. package/dist/esm/ui/link-create/error-boundary/index.js +14 -9
  46. package/dist/esm/ui/link-create/main.js +5 -3
  47. package/dist/esm/ui/main.js +10 -10
  48. package/dist/types/common/messages.d.ts +8 -0
  49. package/dist/types/common/types.d.ts +1 -1
  50. package/dist/types/common/ui/error-boundary-ui/messages.d.ts +0 -5
  51. package/dist/types/common/utils/analytics/analytics.codegen.d.ts +11 -2
  52. package/dist/types/common/utils/errors/index.d.ts +10 -0
  53. package/dist/types/controllers/callback-context/main.d.ts +1 -1
  54. package/dist/types/controllers/experience-tracker/index.d.ts +22 -0
  55. package/dist/types/index.d.ts +1 -0
  56. package/dist/types/ui/create-form/async-select/main.d.ts +1 -1
  57. package/dist/types/ui/create-form/form-footer/edit-button/messages.d.ts +1 -1
  58. package/dist/types/ui/create-form/main.d.ts +18 -1
  59. package/dist/types-ts4.5/common/messages.d.ts +8 -0
  60. package/dist/types-ts4.5/common/types.d.ts +1 -1
  61. package/dist/types-ts4.5/common/ui/error-boundary-ui/messages.d.ts +0 -5
  62. package/dist/types-ts4.5/common/utils/analytics/analytics.codegen.d.ts +11 -2
  63. package/dist/types-ts4.5/common/utils/errors/index.d.ts +10 -0
  64. package/dist/types-ts4.5/controllers/callback-context/main.d.ts +1 -1
  65. package/dist/types-ts4.5/controllers/experience-tracker/index.d.ts +22 -0
  66. package/dist/types-ts4.5/index.d.ts +1 -0
  67. package/dist/types-ts4.5/ui/create-form/async-select/main.d.ts +1 -1
  68. package/dist/types-ts4.5/ui/create-form/form-footer/edit-button/messages.d.ts +1 -1
  69. package/dist/types-ts4.5/ui/create-form/main.d.ts +18 -1
  70. package/package.json +9 -5
  71. package/report.api.md +12 -9
  72. package/tmp/api-report-tmp.d.ts +10 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # @atlaskit/link-create
2
2
 
3
+ ## 1.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#43513](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43513) [`3b056e3b332`](https://bitbucket.org/atlassian/atlassian-frontend/commits/3b056e3b332) - ### Improved Observability
8
+
9
+ Improves observability over failure cases when plugins call `onFailure()`, or throw an error to be caught by `<LinkCreate />`'s internal error boundary.
10
+
11
+ When `platform.linking-platform.link-create.better-observability` feature flag is enabled, errors provided via `onFailure()` from plugins no longer play a role in displaying an error message to users in the `<CreateForm />`.
12
+
13
+ ### Improved Create Form error handling
14
+
15
+ Allows plugins to return an object of error messages in the `onSubmit()` handler provided to the `CreateForm`.
16
+ To set a generic error, use the newly exposed `FORM_ERROR` [see react-final-form](https://final-form.org/docs/react-final-form/types/FormProps#submission-errors) to define an error message on the object resolved `onSubmit`.
17
+
18
+ Example:
19
+
20
+ ```tsx
21
+ import { FORM_ERROR } from '@atlaskit/link-create'
22
+
23
+ <CreateForm onSubmit={(data) => {
24
+ return {
25
+ [FORM_ERROR]: "Something bad happened!"
26
+ }
27
+ } />
28
+ ```
29
+
30
+ The error message returned by the plugin will be displayed in the form footer when the `platform.linking-platform.link-create.better-observability` feature flag is enabled.
31
+
32
+ ### Patch Changes
33
+
34
+ - Updated dependencies
35
+
36
+ ## 1.10.0
37
+
38
+ ### Minor Changes
39
+
40
+ - [#43692](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43692) [`6f2a46c60f3`](https://bitbucket.org/atlassian/atlassian-frontend/commits/6f2a46c60f3) - NOISSUE Make undefinable ari optional in link create payload
41
+
42
+ ### Patch Changes
43
+
44
+ - [#43685](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43685) [`315e88c6400`](https://bitbucket.org/atlassian/atlassian-frontend/commits/315e88c6400) - EDM-8558: rename label of edit button to 'create + open'
45
+
3
46
  ## 1.9.5
4
47
 
5
48
  ### Patch Changes
@@ -10,9 +10,9 @@ context:
10
10
  packageVersion:
11
11
  type: string
12
12
  description: version of the package the event was fired from
13
- source:
13
+ component:
14
14
  type: ['linkCreate']
15
- description: the name of the ui source the event originated from (linkCreate)
15
+ description: the name of the component the event originated from (linkCreate)
16
16
  componentName:
17
17
  type: ['linkCreate']
18
18
  description: the name of the component the event originated from (linkCreate)
@@ -122,9 +122,35 @@ events:
122
122
 
123
123
  - object createFailed (linkCreate):
124
124
  type: track
125
- description: fired when the object creation fails
125
+ description: "[DEPRECATED] prefer `operation failed (linkCreate)` — fired when the object creation fails"
126
126
  attributes:
127
127
  <<: *PackageMetaDataContext
128
128
  failureType:
129
129
  type: string
130
130
  description: the name of the failure
131
+
132
+ - operation failed (linkCreate):
133
+ type: operational
134
+ description: fired when a failure has occured in the link create experience
135
+ attributes:
136
+ <<: *PackageMetaDataContext
137
+ errorType:
138
+ type: string
139
+ description: the name of the error
140
+ required: false
141
+ experienceStatus:
142
+ type: ['SUCCEEDED', 'FAILED']
143
+ previousExperienceStatus:
144
+ type: ['STARTED', 'SUCCEEDED', 'FAILED']
145
+ path:
146
+ type: string
147
+ required: false
148
+ description: The path of the network request if the failure is a Reponse
149
+ status:
150
+ type: number
151
+ required: false
152
+ description: The status code returned for the network request if the failure is a Response
153
+ traceId:
154
+ type: string
155
+ required: false
156
+ description: The x-trace-id header associated with the network request if the failure is a Response
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _reactIntlNext = require("react-intl-next");
8
+ var _default = exports.default = (0, _reactIntlNext.defineMessages)({
9
+ genericErrorMessage: {
10
+ id: 'link-create.unknown-error.heading',
11
+ defaultMessage: 'Something went wrong',
12
+ description: 'Message when an unknown error occurs'
13
+ }
14
+ });
@@ -10,16 +10,17 @@ var _react = _interopRequireDefault(require("react"));
10
10
  var _reactIntlNext = require("react-intl-next");
11
11
  var _button = _interopRequireDefault(require("@atlaskit/button"));
12
12
  var _emptyState = _interopRequireDefault(require("@atlaskit/empty-state"));
13
+ var _messages = _interopRequireDefault(require("../../messages"));
13
14
  var _errorSvg = _interopRequireDefault(require("./error-svg"));
14
- var _messages = _interopRequireDefault(require("./messages"));
15
+ var _messages2 = _interopRequireDefault(require("./messages"));
15
16
  var CONTACT_SUPPORT_LINK = exports.CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
16
17
  var ErrorBoundaryUI = exports.ErrorBoundaryUI = function ErrorBoundaryUI() {
17
18
  var intl = (0, _reactIntlNext.useIntl)();
18
19
  return /*#__PURE__*/_react.default.createElement(_emptyState.default, {
19
20
  maxImageWidth: 82,
20
21
  testId: 'link-create-error-boundary-ui',
21
- header: intl.formatMessage(_messages.default.heading),
22
- description: /*#__PURE__*/_react.default.createElement(_reactIntlNext.FormattedMessage, (0, _extends2.default)({}, _messages.default.description, {
22
+ header: intl.formatMessage(_messages.default.genericErrorMessage),
23
+ description: /*#__PURE__*/_react.default.createElement(_reactIntlNext.FormattedMessage, (0, _extends2.default)({}, _messages2.default.description, {
23
24
  values: {
24
25
  a: function a(label) {
25
26
  return /*#__PURE__*/_react.default.createElement(_button.default, {
@@ -6,11 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _reactIntlNext = require("react-intl-next");
8
8
  var _default = exports.default = (0, _reactIntlNext.defineMessages)({
9
- heading: {
10
- id: 'link-create.unknown-error.heading',
11
- defaultMessage: 'Something went wrong',
12
- description: 'Heading when an unknown error occurs'
13
- },
14
9
  description: {
15
10
  id: 'link-create.unknown-error.description',
16
11
  defaultMessage: 'Refresh the page, or contact <a>Atlassian Support</a> if this keeps happening.',
@@ -11,7 +11,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
11
11
  *
12
12
  * Generates Typescript types for analytics events from analytics.spec.yaml
13
13
  *
14
- * @codegen <<SignedSource::be704bbbca0e49c927d1268b9a0f1d6a>>
14
+ * @codegen <<SignedSource::20562f2db603daab7d5b7a5c5ba1c04b>>
15
15
  * @codegenCommand yarn workspace @atlaskit/link-create run codegen-analytics
16
16
  */
17
17
 
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getNetworkFields = exports.getErrorType = void 0;
8
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
9
+ var _utils = require("@atlaskit/linking-common/utils");
10
+ var getUrlPath = function getUrlPath(url) {
11
+ try {
12
+ return new URL(url).pathname;
13
+ } catch (_unused) {
14
+ return 'Failed to parse pathname from url';
15
+ }
16
+ };
17
+ var getNetworkFields = exports.getNetworkFields = function getNetworkFields(error) {
18
+ if (error instanceof Response) {
19
+ return {
20
+ traceId: (0, _utils.getTraceId)(error),
21
+ status: error.status,
22
+ path: getUrlPath(error.url)
23
+ };
24
+ }
25
+ return {
26
+ traceId: null,
27
+ status: null,
28
+ path: null
29
+ };
30
+ };
31
+ var getErrorType = exports.getErrorType = function getErrorType(error) {
32
+ if (error instanceof Response) {
33
+ return 'NetworkError';
34
+ }
35
+ if (error instanceof Error) {
36
+ return error.name;
37
+ }
38
+ return (0, _typeof2.default)(error);
39
+ };
@@ -11,8 +11,11 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
11
11
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
13
  var _analyticsNext = require("@atlaskit/analytics-next");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
14
15
  var _constants = require("../../common/constants");
15
16
  var _analytics = _interopRequireDefault(require("../../common/utils/analytics/analytics.codegen"));
17
+ var _errors = require("../../common/utils/errors");
18
+ var _experienceTracker = require("../experience-tracker");
16
19
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
21
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -25,6 +28,9 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
25
28
  onCancel = _ref.onCancel;
26
29
  var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
27
30
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
31
+ var experience = (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.better-observability') ?
32
+ // eslint-disable-next-line react-hooks/rules-of-hooks
33
+ (0, _experienceTracker.useExperience)() : null;
28
34
  var handleCreate = (0, _react.useMemo)(function () {
29
35
  return {
30
36
  onCreate: function () {
@@ -33,18 +39,25 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
33
39
  return _regenerator.default.wrap(function _callee$(_context) {
34
40
  while (1) switch (_context.prev = _context.next) {
35
41
  case 0:
42
+ if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.better-observability')) {
43
+ /**
44
+ * We consider the experience successful once we have
45
+ * successfully created an object
46
+ */
47
+ experience === null || experience === void 0 || experience.success();
48
+ }
36
49
  objectId = result.objectId, objectType = result.objectType;
37
50
  createAnalyticsEvent((0, _analytics.default)('track.object.created.linkCreate', {
38
51
  objectId: objectId,
39
52
  objectType: objectType
40
53
  })).fire(_constants.ANALYTICS_CHANNEL);
41
54
  if (!_onCreate) {
42
- _context.next = 5;
55
+ _context.next = 6;
43
56
  break;
44
57
  }
45
- _context.next = 5;
58
+ _context.next = 6;
46
59
  return _onCreate(result);
47
- case 5:
60
+ case 6:
48
61
  case "end":
49
62
  return _context.stop();
50
63
  }
@@ -56,7 +69,7 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
56
69
  return onCreate;
57
70
  }()
58
71
  };
59
- }, [createAnalyticsEvent, _onCreate]);
72
+ }, [createAnalyticsEvent, _onCreate, experience]);
60
73
  var handleFailure = (0, _react.useMemo)(function () {
61
74
  return {
62
75
  onFailure: function () {
@@ -65,10 +78,13 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
65
78
  while (1) switch (_context2.prev = _context2.next) {
66
79
  case 0:
67
80
  createAnalyticsEvent((0, _analytics.default)('track.object.createFailed.linkCreate', {
68
- failureType: error.name
81
+ failureType: (0, _errors.getErrorType)(error)
69
82
  })).fire(_constants.ANALYTICS_CHANNEL);
83
+ if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.better-observability')) {
84
+ experience === null || experience === void 0 || experience.failure(error);
85
+ }
70
86
  _onFailure && _onFailure(error);
71
- case 2:
87
+ case 3:
72
88
  case "end":
73
89
  return _context2.stop();
74
90
  }
@@ -80,7 +96,7 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
80
96
  return onFailure;
81
97
  }()
82
98
  };
83
- }, [createAnalyticsEvent, _onFailure]);
99
+ }, [createAnalyticsEvent, _onFailure, experience]);
84
100
  var value = (0, _react.useMemo)(function () {
85
101
  return _objectSpread(_objectSpread({
86
102
  onCancel: onCancel
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useExperience = exports.Experience = void 0;
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _react = _interopRequireWildcard(require("react"));
11
+ var _analyticsNext = require("@atlaskit/analytics-next");
12
+ var _sentry = require("@atlaskit/linking-common/sentry");
13
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
14
+ var _constants = require("../../common/constants");
15
+ var _analytics = _interopRequireDefault(require("../../common/utils/analytics/analytics.codegen"));
16
+ var _errors = require("../../common/utils/errors");
17
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
18
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
20
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
21
+ var ExperienceContext = /*#__PURE__*/(0, _react.createContext)({
22
+ success: function success() {},
23
+ failure: function failure() {}
24
+ });
25
+
26
+ /**
27
+ * Experience provider that simply keeps track of the state of the experience.
28
+ * Fires an operational event when experience state changes to FAILED.
29
+ */
30
+ var Experience = exports.Experience = function Experience(_ref) {
31
+ var children = _ref.children;
32
+ var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
33
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
34
+ var experience = (0, _react.useRef)('STARTED');
35
+ var value = (0, _react.useMemo)(function () {
36
+ return {
37
+ success: function success() {
38
+ if (experience.current !== 'SUCCEEDED') {
39
+ experience.current = 'SUCCEEDED';
40
+ }
41
+ },
42
+ /**
43
+ * Indicate the experience has failed and capture exception information
44
+ * @param error Typically an Error class or Response class
45
+ */
46
+ failure: function failure(error) {
47
+ var experienceStatus = 'FAILED';
48
+
49
+ /**
50
+ * Always capture an event to Splunk
51
+ */
52
+ createAnalyticsEvent((0, _analytics.default)('operational.operation.failed.linkCreate', _objectSpread({
53
+ /**
54
+ * The type of error that has failed the experience
55
+ */
56
+ errorType: (0, _errors.getErrorType)(error),
57
+ /**
58
+ * The current status of the experience (has failed)
59
+ */
60
+ experienceStatus: experienceStatus,
61
+ /**
62
+ * Previous experience status indicates whether the experience
63
+ * has just failed now, or has already failing
64
+ */
65
+ previousExperienceStatus: experience.current
66
+ }, (0, _errors.getNetworkFields)(error)))).fire(_constants.ANALYTICS_CHANNEL);
67
+ if (error instanceof Error) {
68
+ if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.enable-sentry-client')) {
69
+ // Capture exception to Sentry
70
+ (0, _sentry.captureException)(error, 'link-create');
71
+ }
72
+ }
73
+ if (experience.current !== experienceStatus) {
74
+ experience.current = experienceStatus;
75
+ }
76
+ }
77
+ };
78
+ }, [experience, createAnalyticsEvent]);
79
+ return /*#__PURE__*/_react.default.createElement(ExperienceContext.Provider, {
80
+ value: value
81
+ }, children);
82
+ };
83
+ var useExperience = exports.useExperience = function useExperience() {
84
+ return (0, _react.useContext)(ExperienceContext);
85
+ };
package/dist/cjs/index.js CHANGED
@@ -22,6 +22,12 @@ Object.defineProperty(exports, "CreateFormLoader", {
22
22
  return _index.CreateFormLoader;
23
23
  }
24
24
  });
25
+ Object.defineProperty(exports, "FORM_ERROR", {
26
+ enumerable: true,
27
+ get: function get() {
28
+ return _finalForm.FORM_ERROR;
29
+ }
30
+ });
25
31
  Object.defineProperty(exports, "FormSpy", {
26
32
  enumerable: true,
27
33
  get: function get() {
@@ -58,6 +64,7 @@ Object.defineProperty(exports, "useLinkCreateCallback", {
58
64
  return _callbackContext.useLinkCreateCallback;
59
65
  }
60
66
  });
67
+ var _finalForm = require("final-form");
61
68
  var _index = _interopRequireWildcard(require("./ui/index"));
62
69
  var _callbackContext = require("./controllers/callback-context");
63
70
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -15,8 +15,13 @@ var _react = require("react");
15
15
  var _react2 = require("@emotion/react");
16
16
  var _debouncePromise = _interopRequireDefault(require("debounce-promise"));
17
17
  var _reactFinalForm = require("react-final-form");
18
+ var _reactIntlNext = require("react-intl-next");
19
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
18
20
  var _select = require("@atlaskit/select");
21
+ var _messages = _interopRequireDefault(require("../../../common/messages"));
22
+ var _callbackContext = require("../../../controllers/callback-context");
19
23
  var _createField = require("../../../controllers/create-field");
24
+ var _formContext = require("../../../controllers/form-context");
20
25
  var _excluded = ["id", "name", "label", "isRequired", "validators", "validationHelpText", "testId", "defaultOption", "loadOptions"],
21
26
  _excluded2 = ["fieldId"];
22
27
  /** @jsx jsx */
@@ -38,10 +43,15 @@ function AsyncSelect(_ref) {
38
43
  _ref$testId = _ref.testId,
39
44
  testId = _ref$testId === void 0 ? TEST_ID : _ref$testId,
40
45
  propsDefaultValue = _ref.defaultOption,
41
- loadOptions = _ref.loadOptions,
46
+ loadOptionsFn = _ref.loadOptions,
42
47
  restProps = (0, _objectWithoutProperties2.default)(_ref, _excluded);
43
48
  var _useForm = (0, _reactFinalForm.useForm)(),
44
49
  mutators = _useForm.mutators;
50
+ var _useLinkCreateCallbac = (0, _callbackContext.useLinkCreateCallback)(),
51
+ onFailure = _useLinkCreateCallbac.onFailure;
52
+ var _useFormContext = (0, _formContext.useFormContext)(),
53
+ setFormErrorMessage = _useFormContext.setFormErrorMessage;
54
+ var intl = (0, _reactIntlNext.useIntl)();
45
55
  var _useState = (0, _react.useState)(propsDefaultValue),
46
56
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
47
57
  defaultValue = _useState2[0],
@@ -54,24 +64,56 @@ function AsyncSelect(_ref) {
54
64
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
55
65
  defaultOptions = _useState6[0],
56
66
  setDefaultOptions = _useState6[1];
67
+
68
+ /**
69
+ * This binds experience to fail if async fetch ever fails to load
70
+ */
71
+ var loadOptions = (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.better-observability') ?
72
+ // eslint-disable-next-line react-hooks/rules-of-hooks
73
+ (0, _react.useMemo)(function () {
74
+ if (loadOptionsFn) {
75
+ return /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
76
+ var _args = arguments;
77
+ return _regenerator.default.wrap(function _callee$(_context) {
78
+ while (1) switch (_context.prev = _context.next) {
79
+ case 0:
80
+ _context.prev = 0;
81
+ _context.next = 3;
82
+ return loadOptionsFn.apply(void 0, _args);
83
+ case 3:
84
+ return _context.abrupt("return", _context.sent);
85
+ case 6:
86
+ _context.prev = 6;
87
+ _context.t0 = _context["catch"](0);
88
+ onFailure === null || onFailure === void 0 || onFailure(_context.t0);
89
+ setFormErrorMessage(intl.formatMessage(_messages.default.genericErrorMessage));
90
+ return _context.abrupt("return", []);
91
+ case 11:
92
+ case "end":
93
+ return _context.stop();
94
+ }
95
+ }, _callee, null, [[0, 6]]);
96
+ }));
97
+ }
98
+ }, [intl, onFailure, loadOptionsFn, setFormErrorMessage]) : loadOptionsFn;
57
99
  (0, _react.useEffect)(function () {
58
100
  var current = true;
59
101
  var fetch = /*#__PURE__*/function () {
60
- var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
102
+ var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
61
103
  var query,
62
104
  options,
63
- _args = arguments;
64
- return _regenerator.default.wrap(function _callee$(_context) {
65
- while (1) switch (_context.prev = _context.next) {
105
+ _args2 = arguments;
106
+ return _regenerator.default.wrap(function _callee2$(_context2) {
107
+ while (1) switch (_context2.prev = _context2.next) {
66
108
  case 0:
67
- query = _args.length > 0 && _args[0] !== undefined ? _args[0] : '';
109
+ query = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : '';
68
110
  if (loadOptions) {
69
- _context.next = 3;
111
+ _context2.next = 3;
70
112
  break;
71
113
  }
72
- return _context.abrupt("return");
114
+ return _context2.abrupt("return");
73
115
  case 3:
74
- _context.prev = 3;
116
+ _context2.prev = 3;
75
117
  /**
76
118
  * If we are fetching default options, clear the
77
119
  * value the user has set
@@ -81,30 +123,30 @@ function AsyncSelect(_ref) {
81
123
  }
82
124
  setIsLoadingDefaultOptions(true);
83
125
  setDefaultOptions([]);
84
- _context.next = 9;
126
+ _context2.next = 9;
85
127
  return loadOptions(query);
86
128
  case 9:
87
- options = _context.sent;
129
+ options = _context2.sent;
88
130
  if (current) {
89
131
  setDefaultOptions(options);
90
132
  setIsLoadingDefaultOptions(false);
91
133
  }
92
- _context.next = 16;
134
+ _context2.next = 16;
93
135
  break;
94
136
  case 13:
95
- _context.prev = 13;
96
- _context.t0 = _context["catch"](3);
137
+ _context2.prev = 13;
138
+ _context2.t0 = _context2["catch"](3);
97
139
  if (current) {
98
140
  setIsLoadingDefaultOptions(false);
99
141
  }
100
142
  case 16:
101
143
  case "end":
102
- return _context.stop();
144
+ return _context2.stop();
103
145
  }
104
- }, _callee, null, [[3, 13]]);
146
+ }, _callee2, null, [[3, 13]]);
105
147
  }));
106
148
  return function fetch() {
107
- return _ref2.apply(this, arguments);
149
+ return _ref3.apply(this, arguments);
108
150
  };
109
151
  }();
110
152
  fetch();
@@ -135,9 +177,9 @@ function AsyncSelect(_ref) {
135
177
  validators: validators,
136
178
  validationHelpText: validationHelpText,
137
179
  testId: testId
138
- }, function (_ref3) {
139
- var fieldId = _ref3.fieldId,
140
- fieldProps = (0, _objectWithoutProperties2.default)(_ref3, _excluded2);
180
+ }, function (_ref4) {
181
+ var fieldId = _ref4.fieldId,
182
+ fieldProps = (0, _objectWithoutProperties2.default)(_ref4, _excluded2);
141
183
  return (0, _react2.jsx)(_select.AsyncSelect, (0, _extends2.default)({
142
184
  inputId: fieldId
143
185
  }, fieldProps, restProps, {
@@ -52,6 +52,6 @@ var EditButton = exports.EditButton = function EditButton() {
52
52
  (_mutators$setField = mutators.setField) === null || _mutators$setField === void 0 || _mutators$setField.call(mutators, _constants.LINK_CREATE_FORM_POST_CREATE_FIELD, true);
53
53
  submit();
54
54
  }
55
- }, intl.formatMessage(_messages.messages.edit));
55
+ }, intl.formatMessage(_messages.messages.createAndOpen));
56
56
  });
57
57
  };
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.messages = void 0;
7
7
  var _reactIntlNext = require("react-intl-next");
8
8
  var messages = exports.messages = (0, _reactIntlNext.defineMessages)({
9
- edit: {
10
- id: 'linkCreate.createForm.button.edit',
11
- defaultMessage: 'Edit',
12
- description: 'Button to edit the Create object'
9
+ createAndOpen: {
10
+ id: 'linkCreate.createForm.button.createAndOpen',
11
+ defaultMessage: 'Create + Open',
12
+ description: 'Button to create the object and subsequently open a screen to edit'
13
13
  }
14
14
  });