@atlaskit/editor-plugin-media-insert 2.1.2 → 2.2.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-media-insert
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#134463](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/134463)
8
+ [`d20ae898369bc`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/d20ae898369bc) -
9
+ [ux] [ED-24326] Add local file upload tab to media insert popup
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 2.1.2
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.LocalMedia = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _react = _interopRequireDefault(require("react"));
11
+ var _reactIntlNext = require("react-intl-next");
12
+ var _new = _interopRequireDefault(require("@atlaskit/button/new"));
13
+ var _messages = require("@atlaskit/editor-common/messages");
14
+ var _upload = _interopRequireDefault(require("@atlaskit/icon/glyph/upload"));
15
+ var _mediaPicker = require("@atlaskit/media-picker");
16
+ var _primitives = require("@atlaskit/primitives");
17
+ var _sectionMessage = _interopRequireDefault(require("@atlaskit/section-message"));
18
+ var _useAnalyticsEvents2 = require("./useAnalyticsEvents");
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 INITIAL_UPLOAD_STATE = Object.freeze({
22
+ isOpen: false,
23
+ error: null
24
+ });
25
+ var uploadReducer = function uploadReducer(state, action) {
26
+ switch (action.type) {
27
+ case 'open':
28
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
29
+ isOpen: true
30
+ });
31
+ case 'close':
32
+ // This is the only case where we don't reset state. This is because
33
+ // onClose gets called for cancel _and_ upload, so we don't want to
34
+ // reset any loading or error states that may have occured
35
+ return _objectSpread(_objectSpread({}, state), {}, {
36
+ isOpen: false
37
+ });
38
+ case 'error':
39
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
40
+ error: action.error
41
+ });
42
+ case 'reset':
43
+ return INITIAL_UPLOAD_STATE;
44
+ }
45
+ };
46
+ var isImagePreview = function isImagePreview(preview) {
47
+ return 'dimensions' in preview;
48
+ };
49
+ var LocalMedia = exports.LocalMedia = function LocalMedia(_ref) {
50
+ var mediaProvider = _ref.mediaProvider,
51
+ onInsert = _ref.onInsert,
52
+ dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
53
+ var intl = (0, _reactIntlNext.useIntl)();
54
+ var strings = {
55
+ upload: intl.formatMessage(_messages.mediaInsertMessages.upload),
56
+ networkError: intl.formatMessage(_messages.mediaInsertMessages.localFileNetworkErrorMessage),
57
+ genericError: intl.formatMessage(_messages.mediaInsertMessages.localFileErrorMessage)
58
+ };
59
+ var _useAnalyticsEvents = (0, _useAnalyticsEvents2.useAnalyticsEvents)(dispatchAnalyticsEvent),
60
+ onUploadButtonClickedAnalytics = _useAnalyticsEvents.onUploadButtonClickedAnalytics,
61
+ onUploadCommencedAnalytics = _useAnalyticsEvents.onUploadCommencedAnalytics,
62
+ onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
63
+ onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
64
+ var _React$useReducer = _react.default.useReducer(uploadReducer, INITIAL_UPLOAD_STATE),
65
+ _React$useReducer2 = (0, _slicedToArray2.default)(_React$useReducer, 2),
66
+ uploadState = _React$useReducer2[0],
67
+ dispatch = _React$useReducer2[1];
68
+ var onUpload = function onUpload(_ref2) {
69
+ var _mediaProvider$upload;
70
+ var file = _ref2.file,
71
+ preview = _ref2.preview;
72
+ onUploadSuccessAnalytics('local');
73
+ var insertPayload = {
74
+ id: file.id,
75
+ collection: (_mediaProvider$upload = mediaProvider.uploadParams) === null || _mediaProvider$upload === void 0 ? void 0 : _mediaProvider$upload.collection,
76
+ occurrenceKey: file.occurrenceKey
77
+ };
78
+ if (isImagePreview(preview)) {
79
+ insertPayload.height = preview.dimensions.height;
80
+ insertPayload.width = preview.dimensions.width;
81
+ }
82
+ onInsert(insertPayload);
83
+
84
+ // Probably not needed but I guess it _could_ fail to close for some reason
85
+ dispatch({
86
+ type: 'reset'
87
+ });
88
+ };
89
+ var uploadParams = mediaProvider.uploadParams,
90
+ uploadMediaClientConfig = mediaProvider.uploadMediaClientConfig;
91
+ return /*#__PURE__*/_react.default.createElement(_primitives.Stack, {
92
+ grow: "fill",
93
+ space: "space.200"
94
+ }, uploadState.error && /*#__PURE__*/_react.default.createElement(_sectionMessage.default, {
95
+ appearance: "error"
96
+ }, uploadState.error === 'upload_fail' ? strings.networkError : strings.genericError), /*#__PURE__*/_react.default.createElement(_new.default, {
97
+ iconBefore: _upload.default,
98
+ shouldFitContainer: true,
99
+ isDisabled: !uploadMediaClientConfig || !uploadParams,
100
+ onClick: function onClick() {
101
+ onUploadButtonClickedAnalytics();
102
+ dispatch({
103
+ type: 'open'
104
+ });
105
+ },
106
+ autoFocus: true
107
+ }, strings.upload), uploadMediaClientConfig && uploadParams && /*#__PURE__*/_react.default.createElement(_mediaPicker.Browser, {
108
+ isOpen: uploadState.isOpen,
109
+ config: {
110
+ uploadParams: uploadParams
111
+ },
112
+ mediaClientConfig: uploadMediaClientConfig,
113
+ onUploadsStart: function onUploadsStart() {
114
+ onUploadCommencedAnalytics('local');
115
+ },
116
+ onPreviewUpdate: onUpload
117
+ // NOTE: this will fire for some errors like network failures, but not
118
+ // for others like empty files. Those have their own feedback toast
119
+ // owned by media.
120
+ ,
121
+ onError: function onError(payload) {
122
+ onUploadFailureAnalytics(payload.error.name, 'local');
123
+ dispatch({
124
+ type: 'error',
125
+ error: payload.error.name
126
+ });
127
+ },
128
+ onClose: function onClose() {
129
+ dispatch({
130
+ type: 'close'
131
+ });
132
+ }
133
+ }));
134
+ };
@@ -82,8 +82,8 @@ function MediaFromURL(_ref) {
82
82
  insert: intl.formatMessage(_messages.mediaInsertMessages.insert),
83
83
  pasteLinkToUpload: intl.formatMessage(_messages.mediaInsertMessages.pasteLinkToUpload),
84
84
  cancel: intl.formatMessage(_messages.mediaInsertMessages.cancel),
85
- errorMessage: intl.formatMessage(_messages.mediaInsertMessages.errorMessage),
86
- warning: intl.formatMessage(_messages.mediaInsertMessages.warning)
85
+ errorMessage: intl.formatMessage(_messages.mediaInsertMessages.fromUrlErrorMessage),
86
+ warning: intl.formatMessage(_messages.mediaInsertMessages.fromUrlWarning)
87
87
  };
88
88
  var _React$useState = _react.default.useState(''),
89
89
  _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
@@ -95,7 +95,8 @@ function MediaFromURL(_ref) {
95
95
  dispatch = _React$useReducer2[1];
96
96
  var pasteFlag = _react.default.useRef(false);
97
97
  var _useAnalyticsEvents = (0, _useAnalyticsEvents2.useAnalyticsEvents)(dispatchAnalyticsEvent),
98
- onUploadAnalytics = _useAnalyticsEvents.onUploadAnalytics,
98
+ onUploadButtonClickedAnalytics = _useAnalyticsEvents.onUploadButtonClickedAnalytics,
99
+ onUploadCommencedAnalytics = _useAnalyticsEvents.onUploadCommencedAnalytics,
99
100
  onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
100
101
  onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
101
102
  var uploadExternalMedia = _react.default.useCallback( /*#__PURE__*/function () {
@@ -104,27 +105,28 @@ function MediaFromURL(_ref) {
104
105
  return _regenerator.default.wrap(function _callee$(_context) {
105
106
  while (1) switch (_context.prev = _context.next) {
106
107
  case 0:
108
+ onUploadButtonClickedAnalytics();
107
109
  dispatch({
108
110
  type: 'loading'
109
111
  });
110
112
  uploadMediaClientConfig = mediaProvider.uploadMediaClientConfig, uploadParams = mediaProvider.uploadParams;
111
113
  if (uploadMediaClientConfig) {
112
- _context.next = 4;
114
+ _context.next = 5;
113
115
  break;
114
116
  }
115
117
  return _context.abrupt("return");
116
- case 4:
118
+ case 5:
117
119
  mediaClient = (0, _mediaClientReact.getMediaClient)(uploadMediaClientConfig);
118
120
  collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
119
- onUploadAnalytics();
120
- _context.prev = 7;
121
- _context.next = 10;
121
+ onUploadCommencedAnalytics('url');
122
+ _context.prev = 8;
123
+ _context.next = 11;
122
124
  return mediaClient.file.uploadExternal(url, collection);
123
- case 10:
125
+ case 11:
124
126
  _yield$mediaClient$fi = _context.sent;
125
127
  uploadableFileUpfrontIds = _yield$mediaClient$fi.uploadableFileUpfrontIds;
126
128
  dimensions = _yield$mediaClient$fi.dimensions;
127
- onUploadSuccessAnalytics();
129
+ onUploadSuccessAnalytics('url');
128
130
  dispatch({
129
131
  type: 'success',
130
132
  payload: {
@@ -135,16 +137,16 @@ function MediaFromURL(_ref) {
135
137
  occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
136
138
  }
137
139
  });
138
- _context.next = 20;
140
+ _context.next = 21;
139
141
  break;
140
- case 17:
141
- _context.prev = 17;
142
- _context.t0 = _context["catch"](7);
142
+ case 18:
143
+ _context.prev = 18;
144
+ _context.t0 = _context["catch"](8);
143
145
  if (typeof _context.t0 === 'string' && _context.t0 === 'Could not download remote file') {
144
146
  // TODO: Make sure this gets good unit test coverage with the actual
145
147
  // media plugin. This hard coded error message could be changed at any
146
148
  // point and we need a unit test to break to stop people changing it.
147
- onUploadFailureAnalytics(_context.t0);
149
+ onUploadFailureAnalytics(_context.t0, 'url');
148
150
  dispatch({
149
151
  type: 'warning',
150
152
  warning: _context.t0,
@@ -152,28 +154,28 @@ function MediaFromURL(_ref) {
152
154
  });
153
155
  } else if (_context.t0 instanceof Error) {
154
156
  message = 'Image preview fetch failed';
155
- onUploadFailureAnalytics(message);
157
+ onUploadFailureAnalytics(message, 'url');
156
158
  dispatch({
157
159
  type: 'error',
158
160
  error: message
159
161
  });
160
162
  } else {
161
- onUploadFailureAnalytics('Unknown error');
163
+ onUploadFailureAnalytics('Unknown error', 'url');
162
164
  dispatch({
163
165
  type: 'error',
164
166
  error: 'Unknown error'
165
167
  });
166
168
  }
167
- case 20:
169
+ case 21:
168
170
  case "end":
169
171
  return _context.stop();
170
172
  }
171
- }, _callee, null, [[7, 17]]);
173
+ }, _callee, null, [[8, 18]]);
172
174
  }));
173
175
  return function (_x) {
174
176
  return _ref2.apply(this, arguments);
175
177
  };
176
- }(), [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, inputUrl]);
178
+ }(), [onUploadButtonClickedAnalytics, mediaProvider, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics, inputUrl]);
177
179
  var onURLChange = _react.default.useCallback(function (e) {
178
180
  var url = e.target.value;
179
181
  setUrl(url);
@@ -11,7 +11,8 @@ var _reactIntlNext = require("react-intl-next");
11
11
  var _messages = require("@atlaskit/editor-common/messages");
12
12
  var _primitives = require("@atlaskit/primitives");
13
13
  var _tabs = _interopRequireWildcard(require("@atlaskit/tabs"));
14
- var _FromURL = require("./FromURL");
14
+ var _LocalMedia = require("./LocalMedia");
15
+ var _MediaFromURL = require("./MediaFromURL");
15
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
16
17
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
18
  var MediaInsertContent = exports.MediaInsertContent = function MediaInsertContent(_ref) {
@@ -23,7 +24,12 @@ var MediaInsertContent = exports.MediaInsertContent = function MediaInsertConten
23
24
  id: "media-insert-tab-navigation"
24
25
  }, /*#__PURE__*/_react.default.createElement(_primitives.Box, {
25
26
  paddingBlockEnd: "space.150"
26
- }, /*#__PURE__*/_react.default.createElement(_tabs.TabList, null, /*#__PURE__*/_react.default.createElement(_tabs.Tab, null, intl.formatMessage(_messages.mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/_react.default.createElement(_tabs.TabPanel, null, /*#__PURE__*/_react.default.createElement(_FromURL.MediaFromURL, {
27
+ }, /*#__PURE__*/_react.default.createElement(_tabs.TabList, null, /*#__PURE__*/_react.default.createElement(_tabs.Tab, null, intl.formatMessage(_messages.mediaInsertMessages.fileTabTitle)), /*#__PURE__*/_react.default.createElement(_tabs.Tab, null, intl.formatMessage(_messages.mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/_react.default.createElement(_tabs.TabPanel, null, /*#__PURE__*/_react.default.createElement(_LocalMedia.LocalMedia, {
28
+ mediaProvider: mediaProvider,
29
+ onInsert: function onInsert() {},
30
+ onClose: closeMediaInsertPicker,
31
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent
32
+ })), /*#__PURE__*/_react.default.createElement(_tabs.TabPanel, null, /*#__PURE__*/_react.default.createElement(_MediaFromURL.MediaFromURL, {
27
33
  mediaProvider: mediaProvider,
28
34
  onExternalInsert: function onExternalInsert() {},
29
35
  onInsert: function onInsert() {},
@@ -8,38 +8,54 @@ exports.useAnalyticsEvents = useAnalyticsEvents;
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
  var _analytics = require("@atlaskit/editor-common/analytics");
10
10
  function useAnalyticsEvents(dispatchAnalyticsEvent) {
11
- var onUploadAnalytics = _react.default.useCallback(function () {
11
+ var onUploadButtonClickedAnalytics = _react.default.useCallback(function () {
12
12
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
13
13
  action: _analytics.ACTION.CLICKED,
14
14
  actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
15
- actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
15
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA,
16
16
  eventType: _analytics.EVENT_TYPE.UI
17
17
  });
18
18
  }, [dispatchAnalyticsEvent]);
19
- var onUploadSuccessAnalytics = _react.default.useCallback(function () {
19
+ var onUploadCommencedAnalytics = _react.default.useCallback(function (mediaUploadSource) {
20
+ dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
21
+ action: _analytics.ACTION.UPLOAD_COMMENCED,
22
+ actionSubject: _analytics.ACTION_SUBJECT.MEDIA,
23
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA,
24
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
25
+ attributes: {
26
+ mediaUploadSource: mediaUploadSource
27
+ }
28
+ });
29
+ }, [dispatchAnalyticsEvent]);
30
+ var onUploadSuccessAnalytics = _react.default.useCallback(function (mediaUploadSource) {
20
31
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
21
32
  action: _analytics.ACTION.UPLOAD_SUCCEEDED,
22
33
  actionSubject: _analytics.ACTION_SUBJECT.MEDIA,
23
- actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
24
- eventType: _analytics.EVENT_TYPE.OPERATIONAL
34
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA,
35
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
36
+ attributes: {
37
+ mediaUploadSource: mediaUploadSource
38
+ }
25
39
  });
26
40
  }, [dispatchAnalyticsEvent]);
27
- var onUploadFailureAnalytics = _react.default.useCallback(function (reason) {
41
+ var onUploadFailureAnalytics = _react.default.useCallback(function (reason, mediaUploadSource) {
28
42
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
29
43
  action: _analytics.ACTION.UPLOAD_FAILED,
30
44
  actionSubject: _analytics.ACTION_SUBJECT.MEDIA,
31
- actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
45
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA,
32
46
  eventType: _analytics.EVENT_TYPE.OPERATIONAL,
33
47
  attributes: {
34
- reason: reason
48
+ reason: reason,
49
+ mediaUploadSource: mediaUploadSource
35
50
  }
36
51
  });
37
52
  }, [dispatchAnalyticsEvent]);
38
53
  return _react.default.useMemo(function () {
39
54
  return {
40
- onUploadAnalytics: onUploadAnalytics,
55
+ onUploadButtonClickedAnalytics: onUploadButtonClickedAnalytics,
56
+ onUploadCommencedAnalytics: onUploadCommencedAnalytics,
41
57
  onUploadSuccessAnalytics: onUploadSuccessAnalytics,
42
58
  onUploadFailureAnalytics: onUploadFailureAnalytics
43
59
  };
44
- }, [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
60
+ }, [onUploadButtonClickedAnalytics, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
45
61
  }
@@ -0,0 +1,128 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import Button from '@atlaskit/button/new';
4
+ import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
5
+ import UploadIcon from '@atlaskit/icon/glyph/upload';
6
+ import { Browser } from '@atlaskit/media-picker';
7
+ import { Stack } from '@atlaskit/primitives';
8
+ import SectionMessage from '@atlaskit/section-message';
9
+ import { useAnalyticsEvents } from './useAnalyticsEvents';
10
+ const INITIAL_UPLOAD_STATE = Object.freeze({
11
+ isOpen: false,
12
+ error: null
13
+ });
14
+ const uploadReducer = (state, action) => {
15
+ switch (action.type) {
16
+ case 'open':
17
+ return {
18
+ ...INITIAL_UPLOAD_STATE,
19
+ isOpen: true
20
+ };
21
+ case 'close':
22
+ // This is the only case where we don't reset state. This is because
23
+ // onClose gets called for cancel _and_ upload, so we don't want to
24
+ // reset any loading or error states that may have occured
25
+ return {
26
+ ...state,
27
+ isOpen: false
28
+ };
29
+ case 'error':
30
+ return {
31
+ ...INITIAL_UPLOAD_STATE,
32
+ error: action.error
33
+ };
34
+ case 'reset':
35
+ return INITIAL_UPLOAD_STATE;
36
+ }
37
+ };
38
+ const isImagePreview = preview => {
39
+ return 'dimensions' in preview;
40
+ };
41
+ export const LocalMedia = ({
42
+ mediaProvider,
43
+ onInsert,
44
+ dispatchAnalyticsEvent
45
+ }) => {
46
+ const intl = useIntl();
47
+ const strings = {
48
+ upload: intl.formatMessage(mediaInsertMessages.upload),
49
+ networkError: intl.formatMessage(mediaInsertMessages.localFileNetworkErrorMessage),
50
+ genericError: intl.formatMessage(mediaInsertMessages.localFileErrorMessage)
51
+ };
52
+ const {
53
+ onUploadButtonClickedAnalytics,
54
+ onUploadCommencedAnalytics,
55
+ onUploadSuccessAnalytics,
56
+ onUploadFailureAnalytics
57
+ } = useAnalyticsEvents(dispatchAnalyticsEvent);
58
+ const [uploadState, dispatch] = React.useReducer(uploadReducer, INITIAL_UPLOAD_STATE);
59
+ const onUpload = ({
60
+ file,
61
+ preview
62
+ }) => {
63
+ var _mediaProvider$upload;
64
+ onUploadSuccessAnalytics('local');
65
+ const insertPayload = {
66
+ id: file.id,
67
+ collection: (_mediaProvider$upload = mediaProvider.uploadParams) === null || _mediaProvider$upload === void 0 ? void 0 : _mediaProvider$upload.collection,
68
+ occurrenceKey: file.occurrenceKey
69
+ };
70
+ if (isImagePreview(preview)) {
71
+ insertPayload.height = preview.dimensions.height;
72
+ insertPayload.width = preview.dimensions.width;
73
+ }
74
+ onInsert(insertPayload);
75
+
76
+ // Probably not needed but I guess it _could_ fail to close for some reason
77
+ dispatch({
78
+ type: 'reset'
79
+ });
80
+ };
81
+ const {
82
+ uploadParams,
83
+ uploadMediaClientConfig
84
+ } = mediaProvider;
85
+ return /*#__PURE__*/React.createElement(Stack, {
86
+ grow: "fill",
87
+ space: "space.200"
88
+ }, uploadState.error && /*#__PURE__*/React.createElement(SectionMessage, {
89
+ appearance: "error"
90
+ }, uploadState.error === 'upload_fail' ? strings.networkError : strings.genericError), /*#__PURE__*/React.createElement(Button, {
91
+ iconBefore: UploadIcon,
92
+ shouldFitContainer: true,
93
+ isDisabled: !uploadMediaClientConfig || !uploadParams,
94
+ onClick: () => {
95
+ onUploadButtonClickedAnalytics();
96
+ dispatch({
97
+ type: 'open'
98
+ });
99
+ },
100
+ autoFocus: true
101
+ }, strings.upload), uploadMediaClientConfig && uploadParams && /*#__PURE__*/React.createElement(Browser, {
102
+ isOpen: uploadState.isOpen,
103
+ config: {
104
+ uploadParams: uploadParams
105
+ },
106
+ mediaClientConfig: uploadMediaClientConfig,
107
+ onUploadsStart: () => {
108
+ onUploadCommencedAnalytics('local');
109
+ },
110
+ onPreviewUpdate: onUpload
111
+ // NOTE: this will fire for some errors like network failures, but not
112
+ // for others like empty files. Those have their own feedback toast
113
+ // owned by media.
114
+ ,
115
+ onError: payload => {
116
+ onUploadFailureAnalytics(payload.error.name, 'local');
117
+ dispatch({
118
+ type: 'error',
119
+ error: payload.error.name
120
+ });
121
+ },
122
+ onClose: () => {
123
+ dispatch({
124
+ type: 'close'
125
+ });
126
+ }
127
+ }));
128
+ };
@@ -74,18 +74,20 @@ export function MediaFromURL({
74
74
  insert: intl.formatMessage(mediaInsertMessages.insert),
75
75
  pasteLinkToUpload: intl.formatMessage(mediaInsertMessages.pasteLinkToUpload),
76
76
  cancel: intl.formatMessage(mediaInsertMessages.cancel),
77
- errorMessage: intl.formatMessage(mediaInsertMessages.errorMessage),
78
- warning: intl.formatMessage(mediaInsertMessages.warning)
77
+ errorMessage: intl.formatMessage(mediaInsertMessages.fromUrlErrorMessage),
78
+ warning: intl.formatMessage(mediaInsertMessages.fromUrlWarning)
79
79
  };
80
80
  const [inputUrl, setUrl] = React.useState('');
81
81
  const [previewState, dispatch] = React.useReducer(previewStateReducer, INITIAL_PREVIEW_STATE);
82
82
  const pasteFlag = React.useRef(false);
83
83
  const {
84
- onUploadAnalytics,
84
+ onUploadButtonClickedAnalytics,
85
+ onUploadCommencedAnalytics,
85
86
  onUploadSuccessAnalytics,
86
87
  onUploadFailureAnalytics
87
88
  } = useAnalyticsEvents(dispatchAnalyticsEvent);
88
89
  const uploadExternalMedia = React.useCallback(async url => {
90
+ onUploadButtonClickedAnalytics();
89
91
  dispatch({
90
92
  type: 'loading'
91
93
  });
@@ -98,13 +100,13 @@ export function MediaFromURL({
98
100
  }
99
101
  const mediaClient = getMediaClient(uploadMediaClientConfig);
100
102
  const collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
101
- onUploadAnalytics();
103
+ onUploadCommencedAnalytics('url');
102
104
  try {
103
105
  const {
104
106
  uploadableFileUpfrontIds,
105
107
  dimensions
106
108
  } = await mediaClient.file.uploadExternal(url, collection);
107
- onUploadSuccessAnalytics();
109
+ onUploadSuccessAnalytics('url');
108
110
  dispatch({
109
111
  type: 'success',
110
112
  payload: {
@@ -120,7 +122,7 @@ export function MediaFromURL({
120
122
  // TODO: Make sure this gets good unit test coverage with the actual
121
123
  // media plugin. This hard coded error message could be changed at any
122
124
  // point and we need a unit test to break to stop people changing it.
123
- onUploadFailureAnalytics(e);
125
+ onUploadFailureAnalytics(e, 'url');
124
126
  dispatch({
125
127
  type: 'warning',
126
128
  warning: e,
@@ -128,20 +130,20 @@ export function MediaFromURL({
128
130
  });
129
131
  } else if (e instanceof Error) {
130
132
  const message = 'Image preview fetch failed';
131
- onUploadFailureAnalytics(message);
133
+ onUploadFailureAnalytics(message, 'url');
132
134
  dispatch({
133
135
  type: 'error',
134
136
  error: message
135
137
  });
136
138
  } else {
137
- onUploadFailureAnalytics('Unknown error');
139
+ onUploadFailureAnalytics('Unknown error', 'url');
138
140
  dispatch({
139
141
  type: 'error',
140
142
  error: 'Unknown error'
141
143
  });
142
144
  }
143
145
  }
144
- }, [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, inputUrl]);
146
+ }, [onUploadButtonClickedAnalytics, mediaProvider, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics, inputUrl]);
145
147
  const onURLChange = React.useCallback(e => {
146
148
  const url = e.target.value;
147
149
  setUrl(url);
@@ -3,7 +3,8 @@ import { useIntl } from 'react-intl-next';
3
3
  import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
4
4
  import { Box } from '@atlaskit/primitives';
5
5
  import Tabs, { Tab, TabList, TabPanel } from '@atlaskit/tabs';
6
- import { MediaFromURL } from './FromURL';
6
+ import { LocalMedia } from './LocalMedia';
7
+ import { MediaFromURL } from './MediaFromURL';
7
8
  export const MediaInsertContent = ({
8
9
  mediaProvider,
9
10
  dispatchAnalyticsEvent,
@@ -14,7 +15,12 @@ export const MediaInsertContent = ({
14
15
  id: "media-insert-tab-navigation"
15
16
  }, /*#__PURE__*/React.createElement(Box, {
16
17
  paddingBlockEnd: "space.150"
17
- }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
18
+ }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.fileTabTitle)), /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(LocalMedia, {
19
+ mediaProvider: mediaProvider,
20
+ onInsert: () => {},
21
+ onClose: closeMediaInsertPicker,
22
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent
23
+ })), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
18
24
  mediaProvider: mediaProvider,
19
25
  onExternalInsert: () => {},
20
26
  onInsert: () => {},
@@ -1,36 +1,52 @@
1
1
  import React from 'react';
2
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  export function useAnalyticsEvents(dispatchAnalyticsEvent) {
4
- const onUploadAnalytics = React.useCallback(() => {
4
+ const onUploadButtonClickedAnalytics = React.useCallback(() => {
5
5
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
6
6
  action: ACTION.CLICKED,
7
7
  actionSubject: ACTION_SUBJECT.BUTTON,
8
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
8
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
9
9
  eventType: EVENT_TYPE.UI
10
10
  });
11
11
  }, [dispatchAnalyticsEvent]);
12
- const onUploadSuccessAnalytics = React.useCallback(() => {
12
+ const onUploadCommencedAnalytics = React.useCallback(mediaUploadSource => {
13
+ dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
14
+ action: ACTION.UPLOAD_COMMENCED,
15
+ actionSubject: ACTION_SUBJECT.MEDIA,
16
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
17
+ eventType: EVENT_TYPE.OPERATIONAL,
18
+ attributes: {
19
+ mediaUploadSource
20
+ }
21
+ });
22
+ }, [dispatchAnalyticsEvent]);
23
+ const onUploadSuccessAnalytics = React.useCallback(mediaUploadSource => {
13
24
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
14
25
  action: ACTION.UPLOAD_SUCCEEDED,
15
26
  actionSubject: ACTION_SUBJECT.MEDIA,
16
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
17
- eventType: EVENT_TYPE.OPERATIONAL
27
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
28
+ eventType: EVENT_TYPE.OPERATIONAL,
29
+ attributes: {
30
+ mediaUploadSource
31
+ }
18
32
  });
19
33
  }, [dispatchAnalyticsEvent]);
20
- const onUploadFailureAnalytics = React.useCallback(reason => {
34
+ const onUploadFailureAnalytics = React.useCallback((reason, mediaUploadSource) => {
21
35
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
22
36
  action: ACTION.UPLOAD_FAILED,
23
37
  actionSubject: ACTION_SUBJECT.MEDIA,
24
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
38
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
25
39
  eventType: EVENT_TYPE.OPERATIONAL,
26
40
  attributes: {
27
- reason
41
+ reason,
42
+ mediaUploadSource
28
43
  }
29
44
  });
30
45
  }, [dispatchAnalyticsEvent]);
31
46
  return React.useMemo(() => ({
32
- onUploadAnalytics,
47
+ onUploadButtonClickedAnalytics,
48
+ onUploadCommencedAnalytics,
33
49
  onUploadSuccessAnalytics,
34
50
  onUploadFailureAnalytics
35
- }), [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
51
+ }), [onUploadButtonClickedAnalytics, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
36
52
  }
@@ -0,0 +1,127 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
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; }
5
+ import React from 'react';
6
+ import { useIntl } from 'react-intl-next';
7
+ import Button from '@atlaskit/button/new';
8
+ import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
9
+ import UploadIcon from '@atlaskit/icon/glyph/upload';
10
+ import { Browser } from '@atlaskit/media-picker';
11
+ import { Stack } from '@atlaskit/primitives';
12
+ import SectionMessage from '@atlaskit/section-message';
13
+ import { useAnalyticsEvents } from './useAnalyticsEvents';
14
+ var INITIAL_UPLOAD_STATE = Object.freeze({
15
+ isOpen: false,
16
+ error: null
17
+ });
18
+ var uploadReducer = function uploadReducer(state, action) {
19
+ switch (action.type) {
20
+ case 'open':
21
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
22
+ isOpen: true
23
+ });
24
+ case 'close':
25
+ // This is the only case where we don't reset state. This is because
26
+ // onClose gets called for cancel _and_ upload, so we don't want to
27
+ // reset any loading or error states that may have occured
28
+ return _objectSpread(_objectSpread({}, state), {}, {
29
+ isOpen: false
30
+ });
31
+ case 'error':
32
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
33
+ error: action.error
34
+ });
35
+ case 'reset':
36
+ return INITIAL_UPLOAD_STATE;
37
+ }
38
+ };
39
+ var isImagePreview = function isImagePreview(preview) {
40
+ return 'dimensions' in preview;
41
+ };
42
+ export var LocalMedia = function LocalMedia(_ref) {
43
+ var mediaProvider = _ref.mediaProvider,
44
+ onInsert = _ref.onInsert,
45
+ dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
46
+ var intl = useIntl();
47
+ var strings = {
48
+ upload: intl.formatMessage(mediaInsertMessages.upload),
49
+ networkError: intl.formatMessage(mediaInsertMessages.localFileNetworkErrorMessage),
50
+ genericError: intl.formatMessage(mediaInsertMessages.localFileErrorMessage)
51
+ };
52
+ var _useAnalyticsEvents = useAnalyticsEvents(dispatchAnalyticsEvent),
53
+ onUploadButtonClickedAnalytics = _useAnalyticsEvents.onUploadButtonClickedAnalytics,
54
+ onUploadCommencedAnalytics = _useAnalyticsEvents.onUploadCommencedAnalytics,
55
+ onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
56
+ onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
57
+ var _React$useReducer = React.useReducer(uploadReducer, INITIAL_UPLOAD_STATE),
58
+ _React$useReducer2 = _slicedToArray(_React$useReducer, 2),
59
+ uploadState = _React$useReducer2[0],
60
+ dispatch = _React$useReducer2[1];
61
+ var onUpload = function onUpload(_ref2) {
62
+ var _mediaProvider$upload;
63
+ var file = _ref2.file,
64
+ preview = _ref2.preview;
65
+ onUploadSuccessAnalytics('local');
66
+ var insertPayload = {
67
+ id: file.id,
68
+ collection: (_mediaProvider$upload = mediaProvider.uploadParams) === null || _mediaProvider$upload === void 0 ? void 0 : _mediaProvider$upload.collection,
69
+ occurrenceKey: file.occurrenceKey
70
+ };
71
+ if (isImagePreview(preview)) {
72
+ insertPayload.height = preview.dimensions.height;
73
+ insertPayload.width = preview.dimensions.width;
74
+ }
75
+ onInsert(insertPayload);
76
+
77
+ // Probably not needed but I guess it _could_ fail to close for some reason
78
+ dispatch({
79
+ type: 'reset'
80
+ });
81
+ };
82
+ var uploadParams = mediaProvider.uploadParams,
83
+ uploadMediaClientConfig = mediaProvider.uploadMediaClientConfig;
84
+ return /*#__PURE__*/React.createElement(Stack, {
85
+ grow: "fill",
86
+ space: "space.200"
87
+ }, uploadState.error && /*#__PURE__*/React.createElement(SectionMessage, {
88
+ appearance: "error"
89
+ }, uploadState.error === 'upload_fail' ? strings.networkError : strings.genericError), /*#__PURE__*/React.createElement(Button, {
90
+ iconBefore: UploadIcon,
91
+ shouldFitContainer: true,
92
+ isDisabled: !uploadMediaClientConfig || !uploadParams,
93
+ onClick: function onClick() {
94
+ onUploadButtonClickedAnalytics();
95
+ dispatch({
96
+ type: 'open'
97
+ });
98
+ },
99
+ autoFocus: true
100
+ }, strings.upload), uploadMediaClientConfig && uploadParams && /*#__PURE__*/React.createElement(Browser, {
101
+ isOpen: uploadState.isOpen,
102
+ config: {
103
+ uploadParams: uploadParams
104
+ },
105
+ mediaClientConfig: uploadMediaClientConfig,
106
+ onUploadsStart: function onUploadsStart() {
107
+ onUploadCommencedAnalytics('local');
108
+ },
109
+ onPreviewUpdate: onUpload
110
+ // NOTE: this will fire for some errors like network failures, but not
111
+ // for others like empty files. Those have their own feedback toast
112
+ // owned by media.
113
+ ,
114
+ onError: function onError(payload) {
115
+ onUploadFailureAnalytics(payload.error.name, 'local');
116
+ dispatch({
117
+ type: 'error',
118
+ error: payload.error.name
119
+ });
120
+ },
121
+ onClose: function onClose() {
122
+ dispatch({
123
+ type: 'close'
124
+ });
125
+ }
126
+ }));
127
+ };
@@ -75,8 +75,8 @@ export function MediaFromURL(_ref) {
75
75
  insert: intl.formatMessage(mediaInsertMessages.insert),
76
76
  pasteLinkToUpload: intl.formatMessage(mediaInsertMessages.pasteLinkToUpload),
77
77
  cancel: intl.formatMessage(mediaInsertMessages.cancel),
78
- errorMessage: intl.formatMessage(mediaInsertMessages.errorMessage),
79
- warning: intl.formatMessage(mediaInsertMessages.warning)
78
+ errorMessage: intl.formatMessage(mediaInsertMessages.fromUrlErrorMessage),
79
+ warning: intl.formatMessage(mediaInsertMessages.fromUrlWarning)
80
80
  };
81
81
  var _React$useState = React.useState(''),
82
82
  _React$useState2 = _slicedToArray(_React$useState, 2),
@@ -88,7 +88,8 @@ export function MediaFromURL(_ref) {
88
88
  dispatch = _React$useReducer2[1];
89
89
  var pasteFlag = React.useRef(false);
90
90
  var _useAnalyticsEvents = useAnalyticsEvents(dispatchAnalyticsEvent),
91
- onUploadAnalytics = _useAnalyticsEvents.onUploadAnalytics,
91
+ onUploadButtonClickedAnalytics = _useAnalyticsEvents.onUploadButtonClickedAnalytics,
92
+ onUploadCommencedAnalytics = _useAnalyticsEvents.onUploadCommencedAnalytics,
92
93
  onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
93
94
  onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
94
95
  var uploadExternalMedia = React.useCallback( /*#__PURE__*/function () {
@@ -97,27 +98,28 @@ export function MediaFromURL(_ref) {
97
98
  return _regeneratorRuntime.wrap(function _callee$(_context) {
98
99
  while (1) switch (_context.prev = _context.next) {
99
100
  case 0:
101
+ onUploadButtonClickedAnalytics();
100
102
  dispatch({
101
103
  type: 'loading'
102
104
  });
103
105
  uploadMediaClientConfig = mediaProvider.uploadMediaClientConfig, uploadParams = mediaProvider.uploadParams;
104
106
  if (uploadMediaClientConfig) {
105
- _context.next = 4;
107
+ _context.next = 5;
106
108
  break;
107
109
  }
108
110
  return _context.abrupt("return");
109
- case 4:
111
+ case 5:
110
112
  mediaClient = getMediaClient(uploadMediaClientConfig);
111
113
  collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
112
- onUploadAnalytics();
113
- _context.prev = 7;
114
- _context.next = 10;
114
+ onUploadCommencedAnalytics('url');
115
+ _context.prev = 8;
116
+ _context.next = 11;
115
117
  return mediaClient.file.uploadExternal(url, collection);
116
- case 10:
118
+ case 11:
117
119
  _yield$mediaClient$fi = _context.sent;
118
120
  uploadableFileUpfrontIds = _yield$mediaClient$fi.uploadableFileUpfrontIds;
119
121
  dimensions = _yield$mediaClient$fi.dimensions;
120
- onUploadSuccessAnalytics();
122
+ onUploadSuccessAnalytics('url');
121
123
  dispatch({
122
124
  type: 'success',
123
125
  payload: {
@@ -128,16 +130,16 @@ export function MediaFromURL(_ref) {
128
130
  occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
129
131
  }
130
132
  });
131
- _context.next = 20;
133
+ _context.next = 21;
132
134
  break;
133
- case 17:
134
- _context.prev = 17;
135
- _context.t0 = _context["catch"](7);
135
+ case 18:
136
+ _context.prev = 18;
137
+ _context.t0 = _context["catch"](8);
136
138
  if (typeof _context.t0 === 'string' && _context.t0 === 'Could not download remote file') {
137
139
  // TODO: Make sure this gets good unit test coverage with the actual
138
140
  // media plugin. This hard coded error message could be changed at any
139
141
  // point and we need a unit test to break to stop people changing it.
140
- onUploadFailureAnalytics(_context.t0);
142
+ onUploadFailureAnalytics(_context.t0, 'url');
141
143
  dispatch({
142
144
  type: 'warning',
143
145
  warning: _context.t0,
@@ -145,28 +147,28 @@ export function MediaFromURL(_ref) {
145
147
  });
146
148
  } else if (_context.t0 instanceof Error) {
147
149
  message = 'Image preview fetch failed';
148
- onUploadFailureAnalytics(message);
150
+ onUploadFailureAnalytics(message, 'url');
149
151
  dispatch({
150
152
  type: 'error',
151
153
  error: message
152
154
  });
153
155
  } else {
154
- onUploadFailureAnalytics('Unknown error');
156
+ onUploadFailureAnalytics('Unknown error', 'url');
155
157
  dispatch({
156
158
  type: 'error',
157
159
  error: 'Unknown error'
158
160
  });
159
161
  }
160
- case 20:
162
+ case 21:
161
163
  case "end":
162
164
  return _context.stop();
163
165
  }
164
- }, _callee, null, [[7, 17]]);
166
+ }, _callee, null, [[8, 18]]);
165
167
  }));
166
168
  return function (_x) {
167
169
  return _ref2.apply(this, arguments);
168
170
  };
169
- }(), [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, inputUrl]);
171
+ }(), [onUploadButtonClickedAnalytics, mediaProvider, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics, inputUrl]);
170
172
  var onURLChange = React.useCallback(function (e) {
171
173
  var url = e.target.value;
172
174
  setUrl(url);
@@ -3,7 +3,8 @@ import { useIntl } from 'react-intl-next';
3
3
  import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
4
4
  import { Box } from '@atlaskit/primitives';
5
5
  import Tabs, { Tab, TabList, TabPanel } from '@atlaskit/tabs';
6
- import { MediaFromURL } from './FromURL';
6
+ import { LocalMedia } from './LocalMedia';
7
+ import { MediaFromURL } from './MediaFromURL';
7
8
  export var MediaInsertContent = function MediaInsertContent(_ref) {
8
9
  var mediaProvider = _ref.mediaProvider,
9
10
  dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
@@ -13,7 +14,12 @@ export var MediaInsertContent = function MediaInsertContent(_ref) {
13
14
  id: "media-insert-tab-navigation"
14
15
  }, /*#__PURE__*/React.createElement(Box, {
15
16
  paddingBlockEnd: "space.150"
16
- }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
17
+ }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.fileTabTitle)), /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(LocalMedia, {
18
+ mediaProvider: mediaProvider,
19
+ onInsert: function onInsert() {},
20
+ onClose: closeMediaInsertPicker,
21
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent
22
+ })), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
17
23
  mediaProvider: mediaProvider,
18
24
  onExternalInsert: function onExternalInsert() {},
19
25
  onInsert: function onInsert() {},
@@ -1,38 +1,54 @@
1
1
  import React from 'react';
2
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  export function useAnalyticsEvents(dispatchAnalyticsEvent) {
4
- var onUploadAnalytics = React.useCallback(function () {
4
+ var onUploadButtonClickedAnalytics = React.useCallback(function () {
5
5
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
6
6
  action: ACTION.CLICKED,
7
7
  actionSubject: ACTION_SUBJECT.BUTTON,
8
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
8
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
9
9
  eventType: EVENT_TYPE.UI
10
10
  });
11
11
  }, [dispatchAnalyticsEvent]);
12
- var onUploadSuccessAnalytics = React.useCallback(function () {
12
+ var onUploadCommencedAnalytics = React.useCallback(function (mediaUploadSource) {
13
+ dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
14
+ action: ACTION.UPLOAD_COMMENCED,
15
+ actionSubject: ACTION_SUBJECT.MEDIA,
16
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
17
+ eventType: EVENT_TYPE.OPERATIONAL,
18
+ attributes: {
19
+ mediaUploadSource: mediaUploadSource
20
+ }
21
+ });
22
+ }, [dispatchAnalyticsEvent]);
23
+ var onUploadSuccessAnalytics = React.useCallback(function (mediaUploadSource) {
13
24
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
14
25
  action: ACTION.UPLOAD_SUCCEEDED,
15
26
  actionSubject: ACTION_SUBJECT.MEDIA,
16
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
17
- eventType: EVENT_TYPE.OPERATIONAL
27
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
28
+ eventType: EVENT_TYPE.OPERATIONAL,
29
+ attributes: {
30
+ mediaUploadSource: mediaUploadSource
31
+ }
18
32
  });
19
33
  }, [dispatchAnalyticsEvent]);
20
- var onUploadFailureAnalytics = React.useCallback(function (reason) {
34
+ var onUploadFailureAnalytics = React.useCallback(function (reason, mediaUploadSource) {
21
35
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
22
36
  action: ACTION.UPLOAD_FAILED,
23
37
  actionSubject: ACTION_SUBJECT.MEDIA,
24
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
38
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
25
39
  eventType: EVENT_TYPE.OPERATIONAL,
26
40
  attributes: {
27
- reason: reason
41
+ reason: reason,
42
+ mediaUploadSource: mediaUploadSource
28
43
  }
29
44
  });
30
45
  }, [dispatchAnalyticsEvent]);
31
46
  return React.useMemo(function () {
32
47
  return {
33
- onUploadAnalytics: onUploadAnalytics,
48
+ onUploadButtonClickedAnalytics: onUploadButtonClickedAnalytics,
49
+ onUploadCommencedAnalytics: onUploadCommencedAnalytics,
34
50
  onUploadSuccessAnalytics: onUploadSuccessAnalytics,
35
51
  onUploadFailureAnalytics: onUploadFailureAnalytics
36
52
  };
37
- }, [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
53
+ }, [onUploadButtonClickedAnalytics, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
38
54
  }
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
3
+ import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
4
+ import { type OnInsertAttrs } from './types';
5
+ type Props = {
6
+ mediaProvider: MediaProvider;
7
+ onInsert: (attrs: OnInsertAttrs) => void;
8
+ onClose: () => void;
9
+ dispatchAnalyticsEvent?: DispatchAnalyticsEvent;
10
+ };
11
+ export declare const LocalMedia: ({ mediaProvider, onInsert, dispatchAnalyticsEvent }: Props) => JSX.Element;
12
+ export {};
@@ -2,7 +2,7 @@
2
2
  import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
3
3
  import { type OnInsertAttrs } from './types';
4
4
  type Props = {
5
- attrs: OnInsertAttrs;
5
+ attrs: Required<OnInsertAttrs>;
6
6
  mediaProvider: MediaProvider;
7
7
  };
8
8
  export declare const MediaCard: ({ attrs, mediaProvider }: Props) => JSX.Element;
@@ -1,7 +1,7 @@
1
1
  export type OnInsertAttrs = {
2
2
  id: string;
3
3
  collection: string | undefined;
4
- height: number;
5
- width: number;
4
+ height?: number;
5
+ width?: number;
6
6
  occurrenceKey: string | undefined;
7
7
  };
@@ -1,6 +1,9 @@
1
1
  import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
2
+ type Source = 'local' | 'url';
2
3
  export declare function useAnalyticsEvents(dispatchAnalyticsEvent?: DispatchAnalyticsEvent): {
3
- onUploadAnalytics: () => void;
4
- onUploadSuccessAnalytics: () => void;
5
- onUploadFailureAnalytics: (reason: string) => void;
4
+ onUploadButtonClickedAnalytics: () => void;
5
+ onUploadCommencedAnalytics: (mediaUploadSource: Source) => void;
6
+ onUploadSuccessAnalytics: (mediaUploadSource: Source) => void;
7
+ onUploadFailureAnalytics: (reason: string, mediaUploadSource: Source) => void;
6
8
  };
9
+ export {};
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
3
+ import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
4
+ import { type OnInsertAttrs } from './types';
5
+ type Props = {
6
+ mediaProvider: MediaProvider;
7
+ onInsert: (attrs: OnInsertAttrs) => void;
8
+ onClose: () => void;
9
+ dispatchAnalyticsEvent?: DispatchAnalyticsEvent;
10
+ };
11
+ export declare const LocalMedia: ({ mediaProvider, onInsert, dispatchAnalyticsEvent }: Props) => JSX.Element;
12
+ export {};
@@ -2,7 +2,7 @@
2
2
  import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
3
3
  import { type OnInsertAttrs } from './types';
4
4
  type Props = {
5
- attrs: OnInsertAttrs;
5
+ attrs: Required<OnInsertAttrs>;
6
6
  mediaProvider: MediaProvider;
7
7
  };
8
8
  export declare const MediaCard: ({ attrs, mediaProvider }: Props) => JSX.Element;
@@ -1,7 +1,7 @@
1
1
  export type OnInsertAttrs = {
2
2
  id: string;
3
3
  collection: string | undefined;
4
- height: number;
5
- width: number;
4
+ height?: number;
5
+ width?: number;
6
6
  occurrenceKey: string | undefined;
7
7
  };
@@ -1,6 +1,9 @@
1
1
  import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
2
+ type Source = 'local' | 'url';
2
3
  export declare function useAnalyticsEvents(dispatchAnalyticsEvent?: DispatchAnalyticsEvent): {
3
- onUploadAnalytics: () => void;
4
- onUploadSuccessAnalytics: () => void;
5
- onUploadFailureAnalytics: (reason: string) => void;
4
+ onUploadButtonClickedAnalytics: () => void;
5
+ onUploadCommencedAnalytics: (mediaUploadSource: Source) => void;
6
+ onUploadSuccessAnalytics: (mediaUploadSource: Source) => void;
7
+ onUploadFailureAnalytics: (reason: string, mediaUploadSource: Source) => void;
6
8
  };
9
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-media-insert",
3
- "version": "2.1.2",
3
+ "version": "2.2.0",
4
4
  "description": "Media Insert plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@atlaskit/button": "^20.1.0",
28
- "@atlaskit/editor-common": "^88.2.0",
28
+ "@atlaskit/editor-common": "^88.3.0",
29
29
  "@atlaskit/editor-plugin-analytics": "^1.8.0",
30
30
  "@atlaskit/editor-plugin-media": "^1.29.0",
31
31
  "@atlaskit/editor-prosemirror": "5.0.1",
@@ -34,6 +34,7 @@
34
34
  "@atlaskit/media-card": "^78.1.0",
35
35
  "@atlaskit/media-client": "^27.5.0",
36
36
  "@atlaskit/media-client-react": "^2.1.0",
37
+ "@atlaskit/media-picker": "^66.4.0",
37
38
  "@atlaskit/primitives": "^12.0.0",
38
39
  "@atlaskit/section-message": "^6.6.0",
39
40
  "@atlaskit/tabs": "^16.4.0",