@atlaskit/link-create 1.2.0 → 1.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/controllers/callback-context/main.js +16 -5
  3. package/dist/cjs/controllers/form-context/main.js +15 -2
  4. package/dist/cjs/ui/create-form/main.js +11 -2
  5. package/dist/cjs/ui/link-create/confirm-dismiss-dialog/index.js +12 -0
  6. package/dist/cjs/ui/link-create/confirm-dismiss-dialog/main.js +32 -0
  7. package/dist/cjs/ui/link-create/confirm-dismiss-dialog/messages.js +29 -0
  8. package/dist/cjs/ui/link-create/main.js +42 -9
  9. package/dist/cjs/ui/main.js +1 -1
  10. package/dist/es2019/controllers/callback-context/main.js +11 -5
  11. package/dist/es2019/controllers/form-context/main.js +14 -3
  12. package/dist/es2019/ui/create-form/main.js +10 -3
  13. package/dist/es2019/ui/link-create/confirm-dismiss-dialog/index.js +1 -0
  14. package/dist/es2019/ui/link-create/confirm-dismiss-dialog/main.js +23 -0
  15. package/dist/es2019/ui/link-create/confirm-dismiss-dialog/messages.js +23 -0
  16. package/dist/es2019/ui/link-create/main.js +39 -9
  17. package/dist/es2019/ui/main.js +1 -1
  18. package/dist/esm/controllers/callback-context/main.js +16 -5
  19. package/dist/esm/controllers/form-context/main.js +16 -3
  20. package/dist/esm/ui/create-form/main.js +12 -3
  21. package/dist/esm/ui/link-create/confirm-dismiss-dialog/index.js +1 -0
  22. package/dist/esm/ui/link-create/confirm-dismiss-dialog/main.js +22 -0
  23. package/dist/esm/ui/link-create/confirm-dismiss-dialog/messages.js +23 -0
  24. package/dist/esm/ui/link-create/main.js +43 -10
  25. package/dist/esm/ui/main.js +1 -1
  26. package/dist/types/common/types.d.ts +9 -0
  27. package/dist/types/controllers/form-context/main.d.ts +3 -0
  28. package/dist/types/ui/link-create/confirm-dismiss-dialog/index.d.ts +2 -0
  29. package/dist/types/ui/link-create/confirm-dismiss-dialog/main.d.ts +7 -0
  30. package/dist/types/ui/link-create/confirm-dismiss-dialog/messages.d.ts +23 -0
  31. package/dist/types/ui/link-create/main.d.ts +3 -3
  32. package/dist/types-ts4.5/common/types.d.ts +9 -0
  33. package/dist/types-ts4.5/controllers/form-context/main.d.ts +3 -0
  34. package/dist/types-ts4.5/ui/link-create/confirm-dismiss-dialog/index.d.ts +2 -0
  35. package/dist/types-ts4.5/ui/link-create/confirm-dismiss-dialog/main.d.ts +7 -0
  36. package/dist/types-ts4.5/ui/link-create/confirm-dismiss-dialog/messages.d.ts +23 -0
  37. package/dist/types-ts4.5/ui/link-create/main.d.ts +3 -3
  38. package/example-helpers/mock-plugin-form.tsx +1 -0
  39. package/package.json +6 -2
  40. package/report.api.md +1 -0
  41. package/tmp/api-report-tmp.d.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/link-create
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#42119](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42119) [`fbb3d5ea801`](https://bitbucket.org/atlassian/atlassian-frontend/commits/fbb3d5ea801) - Displays a confirm dismiss dialog when user clicks cancel and made changes to form
8
+
9
+ ## 1.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#41722](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/41722) [`0bcdc0cc988`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0bcdc0cc988) - EDM-8055 Add ARI to link create callback
14
+
3
15
  ## 1.2.0
4
16
 
5
17
  ### Minor Changes
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.useLinkCreateCallback = exports.LinkCreateCallbackProvider = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
11
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
12
  var _react = _interopRequireWildcard(require("react"));
12
13
  var _analyticsNext = require("@atlaskit/analytics-next");
@@ -14,6 +15,8 @@ var _constants = require("../../common/constants");
14
15
  var _analytics = _interopRequireDefault(require("../../common/utils/analytics/analytics.codegen"));
15
16
  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); }
16
17
  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
+ 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; }
19
+ 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; }
17
20
  var LinkCreateCallbackContext = /*#__PURE__*/_react.default.createContext({});
18
21
  var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function LinkCreateCallbackProvider(_ref) {
19
22
  var children = _ref.children,
@@ -22,7 +25,7 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
22
25
  onCancel = _ref.onCancel;
23
26
  var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
24
27
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
25
- var value = (0, _react.useMemo)(function () {
28
+ var handleCreate = (0, _react.useMemo)(function () {
26
29
  return {
27
30
  onCreate: function () {
28
31
  var _onCreate2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(result) {
@@ -51,7 +54,11 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
51
54
  return _onCreate2.apply(this, arguments);
52
55
  }
53
56
  return onCreate;
54
- }(),
57
+ }()
58
+ };
59
+ }, [createAnalyticsEvent, _onCreate]);
60
+ var handleFailure = (0, _react.useMemo)(function () {
61
+ return {
55
62
  onFailure: function () {
56
63
  var _onFailure2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(error) {
57
64
  return _regenerator.default.wrap(function _callee2$(_context2) {
@@ -71,10 +78,14 @@ var LinkCreateCallbackProvider = exports.LinkCreateCallbackProvider = function L
71
78
  return _onFailure2.apply(this, arguments);
72
79
  }
73
80
  return onFailure;
74
- }(),
75
- onCancel: onCancel
81
+ }()
76
82
  };
77
- }, [_onFailure, onCancel, createAnalyticsEvent, _onCreate]);
83
+ }, [createAnalyticsEvent, _onFailure]);
84
+ var value = (0, _react.useMemo)(function () {
85
+ return _objectSpread(_objectSpread({
86
+ onCancel: onCancel
87
+ }, handleCreate), handleFailure);
88
+ }, [onCancel, handleCreate, handleFailure]);
78
89
  return /*#__PURE__*/_react.default.createElement(LinkCreateCallbackContext.Provider, {
79
90
  value: value
80
91
  }, children);
@@ -19,7 +19,11 @@ var FormContext = exports.FormContext = /*#__PURE__*/(0, _react.createContext)({
19
19
  return {};
20
20
  },
21
21
  setFormErrorMessage: function setFormErrorMessage() {},
22
- enableEditView: undefined
22
+ enableEditView: undefined,
23
+ setFormDirty: function setFormDirty() {},
24
+ isFormDirty: function isFormDirty() {
25
+ return false;
26
+ }
23
27
  });
24
28
  var FormContextProvider = exports.FormContextProvider = function FormContextProvider(_ref) {
25
29
  var enableEditView = _ref.enableEditView,
@@ -32,6 +36,13 @@ var FormContextProvider = exports.FormContextProvider = function FormContextProv
32
36
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
33
37
  validators = _useState4[0],
34
38
  setValidators = _useState4[1];
39
+ var dirty = (0, _react.useRef)(false);
40
+ var isFormDirty = (0, _react.useCallback)(function () {
41
+ return dirty.current;
42
+ }, [dirty]);
43
+ var setFormDirty = (0, _react.useCallback)(function (isDirty) {
44
+ dirty.current = !!isDirty;
45
+ }, [dirty]);
35
46
 
36
47
  // Add validators to the form
37
48
  var assignValidator = (0, _react.useCallback)(function (name, fieldValidators) {
@@ -55,7 +66,9 @@ var FormContextProvider = exports.FormContextProvider = function FormContextProv
55
66
  getValidators: getValidators,
56
67
  setFormErrorMessage: setFormErrorMessage,
57
68
  formErrorMessage: error,
58
- enableEditView: enableEditView
69
+ enableEditView: enableEditView,
70
+ setFormDirty: setFormDirty,
71
+ isFormDirty: isFormDirty
59
72
  }
60
73
  }, children);
61
74
  };
@@ -12,6 +12,7 @@ var _react = require("react");
12
12
  var _react2 = require("@emotion/react");
13
13
  var _reactFinalForm = require("react-final-form");
14
14
  var _analyticsNext = require("@atlaskit/analytics-next");
15
+ var _primitives = require("@atlaskit/primitives");
15
16
  var _constants = require("../../common/constants");
16
17
  var _analytics = _interopRequireDefault(require("../../common/utils/analytics/analytics.codegen"));
17
18
  var _formContext = require("../../controllers/form-context");
@@ -39,7 +40,8 @@ var CreateForm = exports.CreateForm = function CreateForm(_ref) {
39
40
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
40
41
  var _useFormContext = (0, _formContext.useFormContext)(),
41
42
  getValidators = _useFormContext.getValidators,
42
- formErrorMessage = _useFormContext.formErrorMessage;
43
+ formErrorMessage = _useFormContext.formErrorMessage,
44
+ setFormDirty = _useFormContext.setFormDirty;
43
45
  var handleSubmit = (0, _react.useCallback)( /*#__PURE__*/function () {
44
46
  var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(data) {
45
47
  var validators, errors;
@@ -94,7 +96,14 @@ var CreateForm = exports.CreateForm = function CreateForm(_ref) {
94
96
  name: "link-create-form",
95
97
  "data-testid": testId,
96
98
  css: formStyles
97
- }, (0, _react2.jsx)("div", null, children), !hideFooter && (0, _react2.jsx)(_formFooter.CreateFormFooter, {
99
+ }, (0, _react2.jsx)(_reactFinalForm.FormSpy, {
100
+ subscription: {
101
+ dirty: true
102
+ },
103
+ onChange: function onChange(state) {
104
+ return setFormDirty(state.dirty);
105
+ }
106
+ }), (0, _react2.jsx)(_primitives.Box, null, children), !hideFooter && (0, _react2.jsx)(_formFooter.CreateFormFooter, {
98
107
  formErrorMessage: formErrorMessage,
99
108
  handleCancel: handleCancel,
100
109
  submitting: submitting,
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "ConfirmDismissDialog", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _main.ConfirmDismissDialog;
10
+ }
11
+ });
12
+ var _main = require("./main");
@@ -0,0 +1,32 @@
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.ConfirmDismissDialog = void 0;
9
+ var _react = _interopRequireDefault(require("react"));
10
+ var _reactIntlNext = require("react-intl-next");
11
+ var _button = _interopRequireDefault(require("@atlaskit/button"));
12
+ var _modalDialog = _interopRequireWildcard(require("@atlaskit/modal-dialog"));
13
+ var _messages = _interopRequireDefault(require("./messages"));
14
+ 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
+ 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; }
16
+ var ConfirmDismissDialog = exports.ConfirmDismissDialog = function ConfirmDismissDialog(_ref) {
17
+ var active = _ref.active,
18
+ onCancelDismiss = _ref.onCancelDismiss,
19
+ onConfirmDismiss = _ref.onConfirmDismiss;
20
+ var intl = (0, _reactIntlNext.useIntl)();
21
+ return /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTransition, null, active && /*#__PURE__*/_react.default.createElement(_modalDialog.default, {
22
+ testId: "link-create-confirm-dismiss-dialog",
23
+ onClose: onCancelDismiss,
24
+ width: "small"
25
+ }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, null, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, null, intl.formatMessage(_messages.default.title))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, intl.formatMessage(_messages.default.description)), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalFooter, null, /*#__PURE__*/_react.default.createElement(_button.default, {
26
+ appearance: "subtle",
27
+ onClick: onCancelDismiss
28
+ }, intl.formatMessage(_messages.default.cancelButtonLabel)), /*#__PURE__*/_react.default.createElement(_button.default, {
29
+ appearance: "primary",
30
+ onClick: onConfirmDismiss
31
+ }, intl.formatMessage(_messages.default.confirmButtonLabel)))));
32
+ };
@@ -0,0 +1,29 @@
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
+ title: {
10
+ id: 'linkCreate.confirm-dismiss-dialog.modal.title',
11
+ defaultMessage: 'Your changes won’t be saved',
12
+ description: 'Title for confirm-dismiss modal popup'
13
+ },
14
+ cancelButtonLabel: {
15
+ id: 'linkCreate.confirm-dismiss-dialog.modal.cancel-button-label',
16
+ defaultMessage: 'Go back',
17
+ description: 'Label for secondary button for confirm-dismiss modal popup'
18
+ },
19
+ confirmButtonLabel: {
20
+ id: 'linkCreate.confirm-dismiss-dialog.modal.confirm-button-label',
21
+ defaultMessage: 'Discard',
22
+ description: 'Label for primary button for confirm-dismiss modal popup'
23
+ },
24
+ description: {
25
+ id: 'linkCreate.confirm-dismiss-dialog.modal.description',
26
+ defaultMessage: 'We won’t be able to save your information if you move away from this page.',
27
+ description: 'Description for confirm-dismiss modal popup'
28
+ }
29
+ });
@@ -7,20 +7,25 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = exports.TEST_ID = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
13
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
14
  var _react = require("react");
13
15
  var _react2 = require("@emotion/react");
14
16
  var _reactIntlNext = require("react-intl-next");
15
17
  var _modalDialog = _interopRequireWildcard(require("@atlaskit/modal-dialog"));
18
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
19
+ var _primitives = require("@atlaskit/primitives");
16
20
  var _constants = require("../../common/constants");
17
21
  var _callbackContext = require("../../controllers/callback-context");
18
22
  var _formContext = require("../../controllers/form-context");
23
+ var _confirmDismissDialog = require("./confirm-dismiss-dialog");
19
24
  var _errorBoundary = require("./error-boundary");
20
25
  var _messages = require("./messages");
21
26
  var _trackMount = _interopRequireDefault(require("./track-mount"));
22
27
  var _excluded = ["testId", "onCreate", "onFailure", "onCancel", "triggeredFrom"],
23
- _excluded2 = ["active", "modalTitle", "onOpenComplete", "onCloseComplete"];
28
+ _excluded2 = ["active", "modalTitle", "onCancel", "onOpenComplete", "onCloseComplete"];
24
29
  /** @jsx jsx */
25
30
  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); }
26
31
  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; }
@@ -36,7 +41,7 @@ var LinkCreateContent = function LinkCreateContent(_ref) {
36
41
  }
37
42
  return (0, _react2.jsx)(_react.Fragment, null, chosenOne.form);
38
43
  };
39
- var LinkCreate = (0, _formContext.withLinkCreateFormContext)(function (_ref2) {
44
+ var LinkCreate = function LinkCreate(_ref2) {
40
45
  var _ref2$testId = _ref2.testId,
41
46
  testId = _ref2$testId === void 0 ? TEST_ID : _ref2$testId,
42
47
  onCreate = _ref2.onCreate,
@@ -74,28 +79,56 @@ var LinkCreate = (0, _formContext.withLinkCreateFormContext)(function (_ref2) {
74
79
  setFormErrorMessage(error.message);
75
80
  onFailure && onFailure(error);
76
81
  }, [onFailure, setFormErrorMessage]);
77
- return (0, _react2.jsx)("div", {
78
- "data-testid": testId
82
+ return (0, _react2.jsx)(_primitives.Box, {
83
+ testId: testId
79
84
  }, (0, _react2.jsx)(_errorBoundary.ErrorBoundary, null, (0, _react2.jsx)(_callbackContext.LinkCreateCallbackProvider, {
80
85
  onCancel: onCancel,
81
86
  onCreate: handleCreate,
82
87
  onFailure: handleFailure
83
88
  }, (0, _react2.jsx)(_trackMount.default, null), (0, _react2.jsx)(LinkCreateContent, restProps))));
84
- });
89
+ };
85
90
  var LinkCreateWithModal = function LinkCreateWithModal(_ref4) {
86
91
  var active = _ref4.active,
87
92
  modalTitle = _ref4.modalTitle,
93
+ onCancel = _ref4.onCancel,
88
94
  onOpenComplete = _ref4.onOpenComplete,
89
95
  onCloseComplete = _ref4.onCloseComplete,
90
96
  createProps = (0, _objectWithoutProperties2.default)(_ref4, _excluded2);
97
+ var _useState = (0, _react.useState)(false),
98
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
99
+ dismissDialog = _useState2[0],
100
+ setDismissDialog = _useState2[1];
101
+ var _useFormContext2 = (0, _formContext.useFormContext)(),
102
+ isFormDirty = _useFormContext2.isFormDirty;
91
103
  var intl = (0, _reactIntlNext.useIntl)();
92
- return (0, _react2.jsx)(_modalDialog.ModalTransition, null, !!active && (0, _react2.jsx)(_modalDialog.default, {
104
+ var handleCancel = (0, _react.useCallback)(function () {
105
+ if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
106
+ if (isFormDirty()) {
107
+ return setDismissDialog(true);
108
+ }
109
+ }
110
+ onCancel && onCancel();
111
+ }, [onCancel, isFormDirty]);
112
+ var handleCancelDismiss = (0, _react.useCallback)(function () {
113
+ setDismissDialog(false);
114
+ }, []);
115
+ var handleConfirmDismiss = (0, _react.useCallback)(function () {
116
+ setDismissDialog(false);
117
+ onCancel && onCancel();
118
+ }, [onCancel]);
119
+ return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_modalDialog.ModalTransition, null, !!active && (0, _react2.jsx)(_modalDialog.default, {
93
120
  testId: "link-create-modal",
94
- onClose: createProps.onCancel,
121
+ onClose: handleCancel,
95
122
  shouldScrollInViewport: true,
96
123
  onOpenComplete: onOpenComplete,
97
124
  onCloseComplete: onCloseComplete,
98
125
  width: "".concat(_constants.CREATE_FORM_MAX_WIDTH_IN_PX, "px")
99
- }, (0, _react2.jsx)(_modalDialog.ModalHeader, null, (0, _react2.jsx)(_modalDialog.ModalTitle, null, modalTitle || intl.formatMessage(_messages.messages.heading))), (0, _react2.jsx)(_modalDialog.ModalBody, null, (0, _react2.jsx)(LinkCreate, createProps))));
126
+ }, (0, _react2.jsx)(_modalDialog.ModalHeader, null, (0, _react2.jsx)(_modalDialog.ModalTitle, null, modalTitle || intl.formatMessage(_messages.messages.heading))), (0, _react2.jsx)(_modalDialog.ModalBody, null, (0, _react2.jsx)(LinkCreate, (0, _extends2.default)({}, createProps, {
127
+ onCancel: handleCancel
128
+ }))))), (0, _react2.jsx)(_confirmDismissDialog.ConfirmDismissDialog, {
129
+ active: dismissDialog,
130
+ onCancelDismiss: handleCancelDismiss,
131
+ onConfirmDismiss: handleConfirmDismiss
132
+ }));
100
133
  };
101
- var _default = exports.default = LinkCreateWithModal;
134
+ var _default = exports.default = (0, _formContext.withLinkCreateFormContext)(LinkCreateWithModal);
@@ -24,7 +24,7 @@ var LinkCreateWithAnalyticsContext = (0, _analytics.withLinkCreateAnalyticsConte
24
24
  }));
25
25
  var PACKAGE_DATA = exports.PACKAGE_DATA = {
26
26
  packageName: "@atlaskit/link-create" || '',
27
- packageVersion: "1.2.0" || '',
27
+ packageVersion: "1.4.0" || '',
28
28
  componentName: _constants.COMPONENT_NAME,
29
29
  source: _constants.COMPONENT_NAME
30
30
  };
@@ -12,7 +12,7 @@ const LinkCreateCallbackProvider = ({
12
12
  const {
13
13
  createAnalyticsEvent
14
14
  } = useAnalyticsEvents();
15
- const value = useMemo(() => ({
15
+ const handleCreate = useMemo(() => ({
16
16
  onCreate: async result => {
17
17
  const {
18
18
  objectId,
@@ -25,15 +25,21 @@ const LinkCreateCallbackProvider = ({
25
25
  if (onCreate) {
26
26
  await onCreate(result);
27
27
  }
28
- },
28
+ }
29
+ }), [createAnalyticsEvent, onCreate]);
30
+ const handleFailure = useMemo(() => ({
29
31
  onFailure: async error => {
30
32
  createAnalyticsEvent(createEventPayload('track.object.createFailed.linkCreate', {
31
33
  failureType: error.name
32
34
  })).fire(ANALYTICS_CHANNEL);
33
35
  onFailure && onFailure(error);
34
- },
35
- onCancel
36
- }), [onFailure, onCancel, createAnalyticsEvent, onCreate]);
36
+ }
37
+ }), [createAnalyticsEvent, onFailure]);
38
+ const value = useMemo(() => ({
39
+ onCancel,
40
+ ...handleCreate,
41
+ ...handleFailure
42
+ }), [onCancel, handleCreate, handleFailure]);
37
43
  return /*#__PURE__*/React.createElement(LinkCreateCallbackContext.Provider, {
38
44
  value: value
39
45
  }, children);
@@ -1,9 +1,11 @@
1
- import React, { createContext, useCallback, useContext, useState } from 'react';
1
+ import React, { createContext, useCallback, useContext, useRef, useState } from 'react';
2
2
  export const FormContext = /*#__PURE__*/createContext({
3
3
  assignValidator: () => {},
4
4
  getValidators: () => ({}),
5
5
  setFormErrorMessage: () => {},
6
- enableEditView: undefined
6
+ enableEditView: undefined,
7
+ setFormDirty: () => {},
8
+ isFormDirty: () => false
7
9
  });
8
10
  const FormContextProvider = ({
9
11
  enableEditView,
@@ -11,6 +13,13 @@ const FormContextProvider = ({
11
13
  }) => {
12
14
  const [error, setError] = useState();
13
15
  const [validators, setValidators] = useState({});
16
+ const dirty = useRef(false);
17
+ const isFormDirty = useCallback(() => {
18
+ return dirty.current;
19
+ }, [dirty]);
20
+ const setFormDirty = useCallback(isDirty => {
21
+ dirty.current = !!isDirty;
22
+ }, [dirty]);
14
23
 
15
24
  // Add validators to the form
16
25
  const assignValidator = useCallback((name, fieldValidators) => {
@@ -35,7 +44,9 @@ const FormContextProvider = ({
35
44
  getValidators,
36
45
  setFormErrorMessage,
37
46
  formErrorMessage: error,
38
- enableEditView
47
+ enableEditView,
48
+ setFormDirty,
49
+ isFormDirty
39
50
  }
40
51
  }, children);
41
52
  };
@@ -1,8 +1,9 @@
1
1
  /** @jsx jsx */
2
2
  import { useCallback } from 'react';
3
3
  import { css, jsx } from '@emotion/react';
4
- import { Form } from 'react-final-form';
4
+ import { Form, FormSpy } from 'react-final-form';
5
5
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
6
+ import { Box } from '@atlaskit/primitives';
6
7
  import { ANALYTICS_CHANNEL, CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
7
8
  import createEventPayload from '../../common/utils/analytics/analytics.codegen';
8
9
  import { useFormContext } from '../../controllers/form-context';
@@ -29,7 +30,8 @@ export const CreateForm = ({
29
30
  } = useAnalyticsEvents();
30
31
  const {
31
32
  getValidators,
32
- formErrorMessage
33
+ formErrorMessage,
34
+ setFormDirty
33
35
  } = useFormContext();
34
36
  const handleSubmit = useCallback(async data => {
35
37
  createAnalyticsEvent(createEventPayload('ui.button.clicked.create', {})).fire(ANALYTICS_CHANNEL);
@@ -67,7 +69,12 @@ export const CreateForm = ({
67
69
  name: "link-create-form",
68
70
  "data-testid": testId,
69
71
  css: formStyles
70
- }, jsx("div", null, children), !hideFooter && jsx(CreateFormFooter, {
72
+ }, jsx(FormSpy, {
73
+ subscription: {
74
+ dirty: true
75
+ },
76
+ onChange: state => setFormDirty(state.dirty)
77
+ }), jsx(Box, null, children), !hideFooter && jsx(CreateFormFooter, {
71
78
  formErrorMessage: formErrorMessage,
72
79
  handleCancel: handleCancel,
73
80
  submitting: submitting,
@@ -0,0 +1 @@
1
+ export { ConfirmDismissDialog } from './main';
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import Button from '@atlaskit/button';
4
+ import Modal, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
5
+ import messages from './messages';
6
+ export const ConfirmDismissDialog = ({
7
+ active,
8
+ onCancelDismiss,
9
+ onConfirmDismiss
10
+ }) => {
11
+ const intl = useIntl();
12
+ return /*#__PURE__*/React.createElement(ModalTransition, null, active && /*#__PURE__*/React.createElement(Modal, {
13
+ testId: "link-create-confirm-dismiss-dialog",
14
+ onClose: onCancelDismiss,
15
+ width: "small"
16
+ }, /*#__PURE__*/React.createElement(ModalHeader, null, /*#__PURE__*/React.createElement(ModalTitle, null, intl.formatMessage(messages.title))), /*#__PURE__*/React.createElement(ModalBody, null, intl.formatMessage(messages.description)), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, {
17
+ appearance: "subtle",
18
+ onClick: onCancelDismiss
19
+ }, intl.formatMessage(messages.cancelButtonLabel)), /*#__PURE__*/React.createElement(Button, {
20
+ appearance: "primary",
21
+ onClick: onConfirmDismiss
22
+ }, intl.formatMessage(messages.confirmButtonLabel)))));
23
+ };
@@ -0,0 +1,23 @@
1
+ import { defineMessages } from 'react-intl-next';
2
+ export default defineMessages({
3
+ title: {
4
+ id: 'linkCreate.confirm-dismiss-dialog.modal.title',
5
+ defaultMessage: 'Your changes won’t be saved',
6
+ description: 'Title for confirm-dismiss modal popup'
7
+ },
8
+ cancelButtonLabel: {
9
+ id: 'linkCreate.confirm-dismiss-dialog.modal.cancel-button-label',
10
+ defaultMessage: 'Go back',
11
+ description: 'Label for secondary button for confirm-dismiss modal popup'
12
+ },
13
+ confirmButtonLabel: {
14
+ id: 'linkCreate.confirm-dismiss-dialog.modal.confirm-button-label',
15
+ defaultMessage: 'Discard',
16
+ description: 'Label for primary button for confirm-dismiss modal popup'
17
+ },
18
+ description: {
19
+ id: 'linkCreate.confirm-dismiss-dialog.modal.description',
20
+ defaultMessage: 'We won’t be able to save your information if you move away from this page.',
21
+ description: 'Description for confirm-dismiss modal popup'
22
+ }
23
+ });
@@ -1,11 +1,15 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  /** @jsx jsx */
2
- import { Fragment, useCallback } from 'react';
3
+ import { Fragment, useCallback, useState } from 'react';
3
4
  import { jsx } from '@emotion/react';
4
5
  import { useIntl } from 'react-intl-next';
5
6
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
7
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
8
+ import { Box } from '@atlaskit/primitives';
6
9
  import { CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
7
10
  import { LinkCreateCallbackProvider } from '../../controllers/callback-context';
8
11
  import { useFormContext, withLinkCreateFormContext } from '../../controllers/form-context';
12
+ import { ConfirmDismissDialog } from './confirm-dismiss-dialog';
9
13
  import { ErrorBoundary } from './error-boundary';
10
14
  import { messages } from './messages';
11
15
  import TrackMount from './track-mount';
@@ -20,7 +24,7 @@ const LinkCreateContent = ({
20
24
  }
21
25
  return jsx(Fragment, null, chosenOne.form);
22
26
  };
23
- const LinkCreate = withLinkCreateFormContext(({
27
+ const LinkCreate = ({
24
28
  testId = TEST_ID,
25
29
  onCreate,
26
30
  onFailure,
@@ -43,29 +47,55 @@ const LinkCreate = withLinkCreateFormContext(({
43
47
  setFormErrorMessage(error.message);
44
48
  onFailure && onFailure(error);
45
49
  }, [onFailure, setFormErrorMessage]);
46
- return jsx("div", {
47
- "data-testid": testId
50
+ return jsx(Box, {
51
+ testId: testId
48
52
  }, jsx(ErrorBoundary, null, jsx(LinkCreateCallbackProvider, {
49
53
  onCancel: onCancel,
50
54
  onCreate: handleCreate,
51
55
  onFailure: handleFailure
52
56
  }, jsx(TrackMount, null), jsx(LinkCreateContent, restProps))));
53
- });
57
+ };
54
58
  const LinkCreateWithModal = ({
55
59
  active,
56
60
  modalTitle,
61
+ onCancel,
57
62
  onOpenComplete,
58
63
  onCloseComplete,
59
64
  ...createProps
60
65
  }) => {
66
+ const [dismissDialog, setDismissDialog] = useState(false);
67
+ const {
68
+ isFormDirty
69
+ } = useFormContext();
61
70
  const intl = useIntl();
62
- return jsx(ModalTransition, null, !!active && jsx(Modal, {
71
+ const handleCancel = useCallback(() => {
72
+ if (getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
73
+ if (isFormDirty()) {
74
+ return setDismissDialog(true);
75
+ }
76
+ }
77
+ onCancel && onCancel();
78
+ }, [onCancel, isFormDirty]);
79
+ const handleCancelDismiss = useCallback(() => {
80
+ setDismissDialog(false);
81
+ }, []);
82
+ const handleConfirmDismiss = useCallback(() => {
83
+ setDismissDialog(false);
84
+ onCancel && onCancel();
85
+ }, [onCancel]);
86
+ return jsx(Fragment, null, jsx(ModalTransition, null, !!active && jsx(Modal, {
63
87
  testId: "link-create-modal",
64
- onClose: createProps.onCancel,
88
+ onClose: handleCancel,
65
89
  shouldScrollInViewport: true,
66
90
  onOpenComplete: onOpenComplete,
67
91
  onCloseComplete: onCloseComplete,
68
92
  width: `${CREATE_FORM_MAX_WIDTH_IN_PX}px`
69
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, createProps))));
93
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, _extends({}, createProps, {
94
+ onCancel: handleCancel
95
+ }))))), jsx(ConfirmDismissDialog, {
96
+ active: dismissDialog,
97
+ onCancelDismiss: handleCancelDismiss,
98
+ onConfirmDismiss: handleConfirmDismiss
99
+ }));
70
100
  };
71
- export default LinkCreateWithModal;
101
+ export default withLinkCreateFormContext(LinkCreateWithModal);
@@ -15,7 +15,7 @@ const LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE
15
15
  }));
16
16
  export const PACKAGE_DATA = {
17
17
  packageName: "@atlaskit/link-create" || '',
18
- packageVersion: "1.2.0" || '',
18
+ packageVersion: "1.4.0" || '',
19
19
  componentName: COMPONENT_NAME,
20
20
  source: COMPONENT_NAME
21
21
  };
@@ -1,4 +1,7 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
2
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ 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; }
4
+ 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) { _defineProperty(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; }
2
5
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
6
  import React, { useContext, useMemo } from 'react';
4
7
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
@@ -12,7 +15,7 @@ var LinkCreateCallbackProvider = function LinkCreateCallbackProvider(_ref) {
12
15
  onCancel = _ref.onCancel;
13
16
  var _useAnalyticsEvents = useAnalyticsEvents(),
14
17
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
15
- var value = useMemo(function () {
18
+ var handleCreate = useMemo(function () {
16
19
  return {
17
20
  onCreate: function () {
18
21
  var _onCreate2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(result) {
@@ -41,7 +44,11 @@ var LinkCreateCallbackProvider = function LinkCreateCallbackProvider(_ref) {
41
44
  return _onCreate2.apply(this, arguments);
42
45
  }
43
46
  return onCreate;
44
- }(),
47
+ }()
48
+ };
49
+ }, [createAnalyticsEvent, _onCreate]);
50
+ var handleFailure = useMemo(function () {
51
+ return {
45
52
  onFailure: function () {
46
53
  var _onFailure2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(error) {
47
54
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
@@ -61,10 +68,14 @@ var LinkCreateCallbackProvider = function LinkCreateCallbackProvider(_ref) {
61
68
  return _onFailure2.apply(this, arguments);
62
69
  }
63
70
  return onFailure;
64
- }(),
65
- onCancel: onCancel
71
+ }()
66
72
  };
67
- }, [_onFailure, onCancel, createAnalyticsEvent, _onCreate]);
73
+ }, [createAnalyticsEvent, _onFailure]);
74
+ var value = useMemo(function () {
75
+ return _objectSpread(_objectSpread({
76
+ onCancel: onCancel
77
+ }, handleCreate), handleFailure);
78
+ }, [onCancel, handleCreate, handleFailure]);
68
79
  return /*#__PURE__*/React.createElement(LinkCreateCallbackContext.Provider, {
69
80
  value: value
70
81
  }, children);
@@ -2,14 +2,18 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  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; }
4
4
  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) { _defineProperty(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; }
5
- import React, { createContext, useCallback, useContext, useState } from 'react';
5
+ import React, { createContext, useCallback, useContext, useRef, useState } from 'react';
6
6
  export var FormContext = /*#__PURE__*/createContext({
7
7
  assignValidator: function assignValidator() {},
8
8
  getValidators: function getValidators() {
9
9
  return {};
10
10
  },
11
11
  setFormErrorMessage: function setFormErrorMessage() {},
12
- enableEditView: undefined
12
+ enableEditView: undefined,
13
+ setFormDirty: function setFormDirty() {},
14
+ isFormDirty: function isFormDirty() {
15
+ return false;
16
+ }
13
17
  });
14
18
  var FormContextProvider = function FormContextProvider(_ref) {
15
19
  var enableEditView = _ref.enableEditView,
@@ -22,6 +26,13 @@ var FormContextProvider = function FormContextProvider(_ref) {
22
26
  _useState4 = _slicedToArray(_useState3, 2),
23
27
  validators = _useState4[0],
24
28
  setValidators = _useState4[1];
29
+ var dirty = useRef(false);
30
+ var isFormDirty = useCallback(function () {
31
+ return dirty.current;
32
+ }, [dirty]);
33
+ var setFormDirty = useCallback(function (isDirty) {
34
+ dirty.current = !!isDirty;
35
+ }, [dirty]);
25
36
 
26
37
  // Add validators to the form
27
38
  var assignValidator = useCallback(function (name, fieldValidators) {
@@ -45,7 +56,9 @@ var FormContextProvider = function FormContextProvider(_ref) {
45
56
  getValidators: getValidators,
46
57
  setFormErrorMessage: setFormErrorMessage,
47
58
  formErrorMessage: error,
48
- enableEditView: enableEditView
59
+ enableEditView: enableEditView,
60
+ setFormDirty: setFormDirty,
61
+ isFormDirty: isFormDirty
49
62
  }
50
63
  }, children);
51
64
  };
@@ -5,8 +5,9 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
5
5
  /** @jsx jsx */
6
6
  import { useCallback } from 'react';
7
7
  import { css, jsx } from '@emotion/react';
8
- import { Form } from 'react-final-form';
8
+ import { Form, FormSpy } from 'react-final-form';
9
9
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
10
+ import { Box } from '@atlaskit/primitives';
10
11
  import { ANALYTICS_CHANNEL, CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
11
12
  import createEventPayload from '../../common/utils/analytics/analytics.codegen';
12
13
  import { useFormContext } from '../../controllers/form-context';
@@ -32,7 +33,8 @@ export var CreateForm = function CreateForm(_ref) {
32
33
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
33
34
  var _useFormContext = useFormContext(),
34
35
  getValidators = _useFormContext.getValidators,
35
- formErrorMessage = _useFormContext.formErrorMessage;
36
+ formErrorMessage = _useFormContext.formErrorMessage,
37
+ setFormDirty = _useFormContext.setFormDirty;
36
38
  var handleSubmit = useCallback( /*#__PURE__*/function () {
37
39
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(data) {
38
40
  var validators, errors;
@@ -87,7 +89,14 @@ export var CreateForm = function CreateForm(_ref) {
87
89
  name: "link-create-form",
88
90
  "data-testid": testId,
89
91
  css: formStyles
90
- }, jsx("div", null, children), !hideFooter && jsx(CreateFormFooter, {
92
+ }, jsx(FormSpy, {
93
+ subscription: {
94
+ dirty: true
95
+ },
96
+ onChange: function onChange(state) {
97
+ return setFormDirty(state.dirty);
98
+ }
99
+ }), jsx(Box, null, children), !hideFooter && jsx(CreateFormFooter, {
91
100
  formErrorMessage: formErrorMessage,
92
101
  handleCancel: handleCancel,
93
102
  submitting: submitting,
@@ -0,0 +1 @@
1
+ export { ConfirmDismissDialog } from './main';
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import Button from '@atlaskit/button';
4
+ import Modal, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
5
+ import messages from './messages';
6
+ export var ConfirmDismissDialog = function ConfirmDismissDialog(_ref) {
7
+ var active = _ref.active,
8
+ onCancelDismiss = _ref.onCancelDismiss,
9
+ onConfirmDismiss = _ref.onConfirmDismiss;
10
+ var intl = useIntl();
11
+ return /*#__PURE__*/React.createElement(ModalTransition, null, active && /*#__PURE__*/React.createElement(Modal, {
12
+ testId: "link-create-confirm-dismiss-dialog",
13
+ onClose: onCancelDismiss,
14
+ width: "small"
15
+ }, /*#__PURE__*/React.createElement(ModalHeader, null, /*#__PURE__*/React.createElement(ModalTitle, null, intl.formatMessage(messages.title))), /*#__PURE__*/React.createElement(ModalBody, null, intl.formatMessage(messages.description)), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, {
16
+ appearance: "subtle",
17
+ onClick: onCancelDismiss
18
+ }, intl.formatMessage(messages.cancelButtonLabel)), /*#__PURE__*/React.createElement(Button, {
19
+ appearance: "primary",
20
+ onClick: onConfirmDismiss
21
+ }, intl.formatMessage(messages.confirmButtonLabel)))));
22
+ };
@@ -0,0 +1,23 @@
1
+ import { defineMessages } from 'react-intl-next';
2
+ export default defineMessages({
3
+ title: {
4
+ id: 'linkCreate.confirm-dismiss-dialog.modal.title',
5
+ defaultMessage: 'Your changes won’t be saved',
6
+ description: 'Title for confirm-dismiss modal popup'
7
+ },
8
+ cancelButtonLabel: {
9
+ id: 'linkCreate.confirm-dismiss-dialog.modal.cancel-button-label',
10
+ defaultMessage: 'Go back',
11
+ description: 'Label for secondary button for confirm-dismiss modal popup'
12
+ },
13
+ confirmButtonLabel: {
14
+ id: 'linkCreate.confirm-dismiss-dialog.modal.confirm-button-label',
15
+ defaultMessage: 'Discard',
16
+ description: 'Label for primary button for confirm-dismiss modal popup'
17
+ },
18
+ description: {
19
+ id: 'linkCreate.confirm-dismiss-dialog.modal.description',
20
+ defaultMessage: 'We won’t be able to save your information if you move away from this page.',
21
+ description: 'Description for confirm-dismiss modal popup'
22
+ }
23
+ });
@@ -1,16 +1,21 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
5
  var _excluded = ["testId", "onCreate", "onFailure", "onCancel", "triggeredFrom"],
4
- _excluded2 = ["active", "modalTitle", "onOpenComplete", "onCloseComplete"];
6
+ _excluded2 = ["active", "modalTitle", "onCancel", "onOpenComplete", "onCloseComplete"];
5
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
6
8
  /** @jsx jsx */
7
- import { Fragment, useCallback } from 'react';
9
+ import { Fragment, useCallback, useState } from 'react';
8
10
  import { jsx } from '@emotion/react';
9
11
  import { useIntl } from 'react-intl-next';
10
12
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
13
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
14
+ import { Box } from '@atlaskit/primitives';
11
15
  import { CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
12
16
  import { LinkCreateCallbackProvider } from '../../controllers/callback-context';
13
17
  import { useFormContext, withLinkCreateFormContext } from '../../controllers/form-context';
18
+ import { ConfirmDismissDialog } from './confirm-dismiss-dialog';
14
19
  import { ErrorBoundary } from './error-boundary';
15
20
  import { messages } from './messages';
16
21
  import TrackMount from './track-mount';
@@ -26,7 +31,7 @@ var LinkCreateContent = function LinkCreateContent(_ref) {
26
31
  }
27
32
  return jsx(Fragment, null, chosenOne.form);
28
33
  };
29
- var LinkCreate = withLinkCreateFormContext(function (_ref2) {
34
+ var LinkCreate = function LinkCreate(_ref2) {
30
35
  var _ref2$testId = _ref2.testId,
31
36
  testId = _ref2$testId === void 0 ? TEST_ID : _ref2$testId,
32
37
  onCreate = _ref2.onCreate,
@@ -64,28 +69,56 @@ var LinkCreate = withLinkCreateFormContext(function (_ref2) {
64
69
  setFormErrorMessage(error.message);
65
70
  onFailure && onFailure(error);
66
71
  }, [onFailure, setFormErrorMessage]);
67
- return jsx("div", {
68
- "data-testid": testId
72
+ return jsx(Box, {
73
+ testId: testId
69
74
  }, jsx(ErrorBoundary, null, jsx(LinkCreateCallbackProvider, {
70
75
  onCancel: onCancel,
71
76
  onCreate: handleCreate,
72
77
  onFailure: handleFailure
73
78
  }, jsx(TrackMount, null), jsx(LinkCreateContent, restProps))));
74
- });
79
+ };
75
80
  var LinkCreateWithModal = function LinkCreateWithModal(_ref4) {
76
81
  var active = _ref4.active,
77
82
  modalTitle = _ref4.modalTitle,
83
+ onCancel = _ref4.onCancel,
78
84
  onOpenComplete = _ref4.onOpenComplete,
79
85
  onCloseComplete = _ref4.onCloseComplete,
80
86
  createProps = _objectWithoutProperties(_ref4, _excluded2);
87
+ var _useState = useState(false),
88
+ _useState2 = _slicedToArray(_useState, 2),
89
+ dismissDialog = _useState2[0],
90
+ setDismissDialog = _useState2[1];
91
+ var _useFormContext2 = useFormContext(),
92
+ isFormDirty = _useFormContext2.isFormDirty;
81
93
  var intl = useIntl();
82
- return jsx(ModalTransition, null, !!active && jsx(Modal, {
94
+ var handleCancel = useCallback(function () {
95
+ if (getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
96
+ if (isFormDirty()) {
97
+ return setDismissDialog(true);
98
+ }
99
+ }
100
+ onCancel && onCancel();
101
+ }, [onCancel, isFormDirty]);
102
+ var handleCancelDismiss = useCallback(function () {
103
+ setDismissDialog(false);
104
+ }, []);
105
+ var handleConfirmDismiss = useCallback(function () {
106
+ setDismissDialog(false);
107
+ onCancel && onCancel();
108
+ }, [onCancel]);
109
+ return jsx(Fragment, null, jsx(ModalTransition, null, !!active && jsx(Modal, {
83
110
  testId: "link-create-modal",
84
- onClose: createProps.onCancel,
111
+ onClose: handleCancel,
85
112
  shouldScrollInViewport: true,
86
113
  onOpenComplete: onOpenComplete,
87
114
  onCloseComplete: onCloseComplete,
88
115
  width: "".concat(CREATE_FORM_MAX_WIDTH_IN_PX, "px")
89
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, createProps))));
116
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, _extends({}, createProps, {
117
+ onCancel: handleCancel
118
+ }))))), jsx(ConfirmDismissDialog, {
119
+ active: dismissDialog,
120
+ onCancelDismiss: handleCancelDismiss,
121
+ onConfirmDismiss: handleConfirmDismiss
122
+ }));
90
123
  };
91
- export default LinkCreateWithModal;
124
+ export default withLinkCreateFormContext(LinkCreateWithModal);
@@ -16,7 +16,7 @@ var LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE__
16
16
  }));
17
17
  export var PACKAGE_DATA = {
18
18
  packageName: "@atlaskit/link-create" || '',
19
- packageVersion: "1.2.0" || '',
19
+ packageVersion: "1.4.0" || '',
20
20
  componentName: COMPONENT_NAME,
21
21
  source: COMPONENT_NAME
22
22
  };
@@ -48,6 +48,15 @@ export interface LinkCreatePlugin {
48
48
  export type CreatePayload = {
49
49
  /** The url to the resource created by the create plugin */
50
50
  url: string;
51
+ /**
52
+ * ARI of the created resource.
53
+ * https://developer.atlassian.com/platform/atlassian-resource-identifier/spec/ari-latest/
54
+ *
55
+ * It should be returned but it's not required to be on the Jira side:
56
+ * https://stash.atlassian.com/projects/JIRACLOUD/repos/jira-frontend/browse/src/packages/issue-create/issue-create-embed/src/ui/index.tsx
57
+ * https://stash.atlassian.com/projects/JIRACLOUD/repos/jira-frontend/pull-requests/103587/overview?commentId=5778323
58
+ */
59
+ ari: string | undefined;
51
60
  /** The object identifier for the resource created by the create plugin (for analytics) */
52
61
  objectId: string;
53
62
  /** The type of object created (for analytics) */
@@ -4,6 +4,8 @@ interface FormContextType {
4
4
  getValidators: () => ValidatorMap;
5
5
  assignValidator: (name: string, validators: Validator[]) => void;
6
6
  setFormErrorMessage: (errorMessage?: string) => void;
7
+ setFormDirty: (dirty?: boolean) => void;
8
+ isFormDirty: () => boolean;
7
9
  formErrorMessage?: string;
8
10
  /**
9
11
  * Callback that updates link create to tell it that it should/should not open the current plugins
@@ -11,6 +13,7 @@ interface FormContextType {
11
13
  * is not defined as a prop at the `LinkCreate` props level
12
14
  */
13
15
  enableEditView?: ((editButtonClicked: boolean) => void) | undefined;
16
+ formDirty?: boolean;
14
17
  }
15
18
  export declare const FormContext: React.Context<FormContextType>;
16
19
  declare const FormContextProvider: React.FC<{
@@ -0,0 +1,2 @@
1
+ export { ConfirmDismissDialog } from './main';
2
+ export type { ConfirmDismissDialogProps } from './main';
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ export type ConfirmDismissDialogProps = {
3
+ active: boolean;
4
+ onCancelDismiss?: () => void;
5
+ onConfirmDismiss?: () => void;
6
+ };
7
+ export declare const ConfirmDismissDialog: ({ active, onCancelDismiss, onConfirmDismiss, }: ConfirmDismissDialogProps) => JSX.Element;
@@ -0,0 +1,23 @@
1
+ declare const _default: {
2
+ title: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ cancelButtonLabel: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ confirmButtonLabel: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ description: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ };
23
+ export default _default;
@@ -1,5 +1,5 @@
1
- import { jsx } from '@emotion/react';
1
+ /// <reference types="react" />
2
2
  import { LinkCreateWithModalProps } from '../../common/types';
3
3
  export declare const TEST_ID = "link-create";
4
- declare const LinkCreateWithModal: ({ active, modalTitle, onOpenComplete, onCloseComplete, ...createProps }: LinkCreateWithModalProps) => jsx.JSX.Element;
5
- export default LinkCreateWithModal;
4
+ declare const _default: (props: LinkCreateWithModalProps) => JSX.Element;
5
+ export default _default;
@@ -48,6 +48,15 @@ export interface LinkCreatePlugin {
48
48
  export type CreatePayload = {
49
49
  /** The url to the resource created by the create plugin */
50
50
  url: string;
51
+ /**
52
+ * ARI of the created resource.
53
+ * https://developer.atlassian.com/platform/atlassian-resource-identifier/spec/ari-latest/
54
+ *
55
+ * It should be returned but it's not required to be on the Jira side:
56
+ * https://stash.atlassian.com/projects/JIRACLOUD/repos/jira-frontend/browse/src/packages/issue-create/issue-create-embed/src/ui/index.tsx
57
+ * https://stash.atlassian.com/projects/JIRACLOUD/repos/jira-frontend/pull-requests/103587/overview?commentId=5778323
58
+ */
59
+ ari: string | undefined;
51
60
  /** The object identifier for the resource created by the create plugin (for analytics) */
52
61
  objectId: string;
53
62
  /** The type of object created (for analytics) */
@@ -4,6 +4,8 @@ interface FormContextType {
4
4
  getValidators: () => ValidatorMap;
5
5
  assignValidator: (name: string, validators: Validator[]) => void;
6
6
  setFormErrorMessage: (errorMessage?: string) => void;
7
+ setFormDirty: (dirty?: boolean) => void;
8
+ isFormDirty: () => boolean;
7
9
  formErrorMessage?: string;
8
10
  /**
9
11
  * Callback that updates link create to tell it that it should/should not open the current plugins
@@ -11,6 +13,7 @@ interface FormContextType {
11
13
  * is not defined as a prop at the `LinkCreate` props level
12
14
  */
13
15
  enableEditView?: ((editButtonClicked: boolean) => void) | undefined;
16
+ formDirty?: boolean;
14
17
  }
15
18
  export declare const FormContext: React.Context<FormContextType>;
16
19
  declare const FormContextProvider: React.FC<{
@@ -0,0 +1,2 @@
1
+ export { ConfirmDismissDialog } from './main';
2
+ export type { ConfirmDismissDialogProps } from './main';
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ export type ConfirmDismissDialogProps = {
3
+ active: boolean;
4
+ onCancelDismiss?: () => void;
5
+ onConfirmDismiss?: () => void;
6
+ };
7
+ export declare const ConfirmDismissDialog: ({ active, onCancelDismiss, onConfirmDismiss, }: ConfirmDismissDialogProps) => JSX.Element;
@@ -0,0 +1,23 @@
1
+ declare const _default: {
2
+ title: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ cancelButtonLabel: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ confirmButtonLabel: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ description: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ };
23
+ export default _default;
@@ -1,5 +1,5 @@
1
- import { jsx } from '@emotion/react';
1
+ /// <reference types="react" />
2
2
  import { LinkCreateWithModalProps } from '../../common/types';
3
3
  export declare const TEST_ID = "link-create";
4
- declare const LinkCreateWithModal: ({ active, modalTitle, onOpenComplete, onCloseComplete, ...createProps }: LinkCreateWithModalProps) => jsx.JSX.Element;
5
- export default LinkCreateWithModal;
4
+ declare const _default: (props: LinkCreateWithModalProps) => JSX.Element;
5
+ export default _default;
@@ -28,6 +28,7 @@ export function MockPluginForm({ shouldThrowError }: pluginProps) {
28
28
  objectId: 'new-object-id',
29
29
  objectType: 'object-type',
30
30
  data: {},
31
+ ari: 'example-ari',
31
32
  });
32
33
  }
33
34
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-create",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "The driver component of meta creation flow",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -42,6 +42,7 @@
42
42
  "@atlaskit/intl-messages-provider": "^1.0.0",
43
43
  "@atlaskit/modal-dialog": "^12.8.0",
44
44
  "@atlaskit/platform-feature-flags": "^0.2.1",
45
+ "@atlaskit/primitives": "^1.6.0",
45
46
  "@atlaskit/select": "^16.7.0",
46
47
  "@atlaskit/spinner": "^15.6.0",
47
48
  "@atlaskit/textfield": "^5.6.0",
@@ -61,7 +62,7 @@
61
62
  "@atlaskit/link-test-helpers": "^6.2.0",
62
63
  "@atlaskit/visual-regression": "*",
63
64
  "@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
64
- "@atlassian/feature-flags-test-utils": "^0.1.2",
65
+ "@atlassian/feature-flags-test-utils": "*",
65
66
  "@testing-library/react": "^12.1.5",
66
67
  "@testing-library/user-event": "^14.4.3",
67
68
  "@types/debounce-promise": "^3.1.2",
@@ -113,6 +114,9 @@
113
114
  "platform-feature-flags": {
114
115
  "platform.linking-platform.link-create.enable-edit": {
115
116
  "type": "boolean"
117
+ },
118
+ "platform.linking-platform.link-create.confirm-dismiss-dialog": {
119
+ "type": "boolean"
116
120
  }
117
121
  }
118
122
  }
package/report.api.md CHANGED
@@ -100,6 +100,7 @@ export interface CreateFormProps<FormData> {
100
100
  // @public
101
101
  export type CreatePayload = {
102
102
  url: string;
103
+ ari: string | undefined;
103
104
  objectId: string;
104
105
  objectType: string;
105
106
  data?: Record<string, unknown>;
@@ -63,6 +63,7 @@ export interface CreateFormProps<FormData> {
63
63
  // @public
64
64
  export type CreatePayload = {
65
65
  url: string;
66
+ ari: string | undefined;
66
67
  objectId: string;
67
68
  objectType: string;
68
69
  data?: Record<string, unknown>;