@atlaskit/editor-plugin-media-insert 1.1.2 → 1.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 +12 -0
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/ui/FromURL.js +234 -0
- package/dist/cjs/ui/MediaCard.js +55 -0
- package/dist/cjs/ui/types.js +1 -0
- package/dist/cjs/ui/useAnalyticsEvents.js +45 -0
- package/dist/es2019/index.js +2 -1
- package/dist/es2019/ui/FromURL.js +202 -0
- package/dist/es2019/ui/MediaCard.js +43 -0
- package/dist/es2019/ui/types.js +0 -0
- package/dist/es2019/ui/useAnalyticsEvents.js +36 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/ui/FromURL.js +227 -0
- package/dist/esm/ui/MediaCard.js +48 -0
- package/dist/esm/ui/types.js +0 -0
- package/dist/esm/ui/useAnalyticsEvents.js +38 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/ui/FromURL.d.ts +12 -0
- package/dist/types/ui/MediaCard.d.ts +9 -0
- package/dist/types/ui/types.d.ts +7 -0
- package/dist/types/ui/useAnalyticsEvents.d.ts +6 -0
- package/dist/types-ts4.5/index.d.ts +1 -0
- package/dist/types-ts4.5/ui/FromURL.d.ts +12 -0
- package/dist/types-ts4.5/ui/MediaCard.d.ts +9 -0
- package/dist/types-ts4.5/ui/types.d.ts +7 -0
- package/dist/types-ts4.5/ui/useAnalyticsEvents.d.ts +6 -0
- package/package.json +14 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-media-insert
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#128527](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/128527)
|
|
8
|
+
[`e9e003a733b63`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e9e003a733b63) -
|
|
9
|
+
Add media upload from URL and associated i18n, analytics and test packages
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 1.1.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "MediaFromURL", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _FromURL.MediaFromURL;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "mediaInsertPlugin", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function get() {
|
|
9
15
|
return _plugin.mediaInsertPlugin;
|
|
10
16
|
}
|
|
11
17
|
});
|
|
12
|
-
var _plugin = require("./plugin");
|
|
18
|
+
var _plugin = require("./plugin");
|
|
19
|
+
var _FromURL = require("./ui/FromURL");
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.MediaFromURL = MediaFromURL;
|
|
8
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
12
|
+
var _react = _interopRequireDefault(require("react"));
|
|
13
|
+
var _reactIntlNext = require("react-intl-next");
|
|
14
|
+
var _buttonGroup = _interopRequireDefault(require("@atlaskit/button/button-group"));
|
|
15
|
+
var _new = _interopRequireDefault(require("@atlaskit/button/new"));
|
|
16
|
+
var _messages = require("@atlaskit/editor-common/messages");
|
|
17
|
+
var _filePreview = _interopRequireDefault(require("@atlaskit/icon/glyph/editor/file-preview"));
|
|
18
|
+
var _mediaClientReact = require("@atlaskit/media-client-react");
|
|
19
|
+
var _primitives = require("@atlaskit/primitives");
|
|
20
|
+
var _sectionMessage = _interopRequireDefault(require("@atlaskit/section-message"));
|
|
21
|
+
var _textfield = _interopRequireDefault(require("@atlaskit/textfield"));
|
|
22
|
+
var _MediaCard = require("./MediaCard");
|
|
23
|
+
var _useAnalyticsEvents2 = require("./useAnalyticsEvents");
|
|
24
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
25
|
+
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; }
|
|
26
|
+
var PreviewBoxStyles = (0, _primitives.xcss)({
|
|
27
|
+
borderWidth: 'border.width',
|
|
28
|
+
borderStyle: 'dashed',
|
|
29
|
+
borderColor: 'color.border',
|
|
30
|
+
borderRadius: 'border.radius',
|
|
31
|
+
height: '200px'
|
|
32
|
+
});
|
|
33
|
+
var PreviewImageStyles = (0, _primitives.xcss)({
|
|
34
|
+
height: '200px'
|
|
35
|
+
});
|
|
36
|
+
var ButtonGroupStyles = (0, _primitives.xcss)({
|
|
37
|
+
alignSelf: 'end'
|
|
38
|
+
});
|
|
39
|
+
var INITIAL_PREVIEW_STATE = Object.freeze({
|
|
40
|
+
isLoading: false,
|
|
41
|
+
error: null,
|
|
42
|
+
warning: null,
|
|
43
|
+
previewInfo: null
|
|
44
|
+
});
|
|
45
|
+
var previewStateReducer = function previewStateReducer(state, action) {
|
|
46
|
+
switch (action.type) {
|
|
47
|
+
case 'loading':
|
|
48
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
49
|
+
isLoading: true
|
|
50
|
+
});
|
|
51
|
+
case 'error':
|
|
52
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
53
|
+
error: action.error
|
|
54
|
+
});
|
|
55
|
+
case 'warning':
|
|
56
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
57
|
+
warning: action.warning
|
|
58
|
+
});
|
|
59
|
+
case 'success':
|
|
60
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
61
|
+
previewInfo: action.payload
|
|
62
|
+
});
|
|
63
|
+
case 'reset':
|
|
64
|
+
return INITIAL_PREVIEW_STATE;
|
|
65
|
+
default:
|
|
66
|
+
return state;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
// TODO: Delete these before rollout
|
|
70
|
+
var placeholders = ['https://picsum.photos/200/300',
|
|
71
|
+
// has cors
|
|
72
|
+
'https://placedog.net/500/280',
|
|
73
|
+
// has cors
|
|
74
|
+
'https://preview.redd.it/gabriel-medina-at-the-olympics-after-riding-a-nearly-v0-dbyczz2fkifd1.jpeg?auto=webp&s=045550d672718427b67fb929bc6efc57116a7596' // no cors
|
|
75
|
+
];
|
|
76
|
+
function MediaFromURL(_ref) {
|
|
77
|
+
var mediaProvider = _ref.mediaProvider,
|
|
78
|
+
onInsert = _ref.onInsert,
|
|
79
|
+
onExternalInsert = _ref.onExternalInsert,
|
|
80
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
|
|
81
|
+
var intl = (0, _reactIntlNext.useIntl)();
|
|
82
|
+
var strings = {
|
|
83
|
+
loadPreview: intl.formatMessage(_messages.mediaInsertMessages.loadPreview),
|
|
84
|
+
insert: intl.formatMessage(_messages.mediaInsertMessages.insert),
|
|
85
|
+
pasteLinkToUpload: intl.formatMessage(_messages.mediaInsertMessages.pasteLinkToUpload),
|
|
86
|
+
cancel: intl.formatMessage(_messages.mediaInsertMessages.cancel),
|
|
87
|
+
errorMessage: intl.formatMessage(_messages.mediaInsertMessages.errorMessage),
|
|
88
|
+
warning: intl.formatMessage(_messages.mediaInsertMessages.warning)
|
|
89
|
+
};
|
|
90
|
+
var _React$useState = _react.default.useState(placeholders[1]),
|
|
91
|
+
_React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
|
|
92
|
+
url = _React$useState2[0],
|
|
93
|
+
setUrl = _React$useState2[1];
|
|
94
|
+
var _React$useReducer = _react.default.useReducer(previewStateReducer, INITIAL_PREVIEW_STATE),
|
|
95
|
+
_React$useReducer2 = (0, _slicedToArray2.default)(_React$useReducer, 2),
|
|
96
|
+
previewState = _React$useReducer2[0],
|
|
97
|
+
dispatch = _React$useReducer2[1];
|
|
98
|
+
var _useAnalyticsEvents = (0, _useAnalyticsEvents2.useAnalyticsEvents)(dispatchAnalyticsEvent),
|
|
99
|
+
onUploadAnalytics = _useAnalyticsEvents.onUploadAnalytics,
|
|
100
|
+
onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
|
|
101
|
+
onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
|
|
102
|
+
var onURLChange = _react.default.useCallback(function (e) {
|
|
103
|
+
setUrl(e.target.value);
|
|
104
|
+
dispatch({
|
|
105
|
+
type: 'reset'
|
|
106
|
+
});
|
|
107
|
+
}, []);
|
|
108
|
+
var uploadExternalMedia = _react.default.useCallback( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
109
|
+
var _yield$mediaProvider, uploadMediaClientConfig, uploadParams, mediaClient, collection, _yield$mediaClient$fi, uploadableFileUpfrontIds, dimensions, message;
|
|
110
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
111
|
+
while (1) switch (_context.prev = _context.next) {
|
|
112
|
+
case 0:
|
|
113
|
+
dispatch({
|
|
114
|
+
type: 'loading'
|
|
115
|
+
});
|
|
116
|
+
_context.next = 3;
|
|
117
|
+
return mediaProvider;
|
|
118
|
+
case 3:
|
|
119
|
+
_yield$mediaProvider = _context.sent;
|
|
120
|
+
uploadMediaClientConfig = _yield$mediaProvider.uploadMediaClientConfig;
|
|
121
|
+
uploadParams = _yield$mediaProvider.uploadParams;
|
|
122
|
+
if (uploadMediaClientConfig) {
|
|
123
|
+
_context.next = 8;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
return _context.abrupt("return");
|
|
127
|
+
case 8:
|
|
128
|
+
mediaClient = (0, _mediaClientReact.getMediaClient)(uploadMediaClientConfig);
|
|
129
|
+
collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
|
|
130
|
+
onUploadAnalytics();
|
|
131
|
+
_context.prev = 11;
|
|
132
|
+
_context.next = 14;
|
|
133
|
+
return mediaClient.file.uploadExternal(url, collection);
|
|
134
|
+
case 14:
|
|
135
|
+
_yield$mediaClient$fi = _context.sent;
|
|
136
|
+
uploadableFileUpfrontIds = _yield$mediaClient$fi.uploadableFileUpfrontIds;
|
|
137
|
+
dimensions = _yield$mediaClient$fi.dimensions;
|
|
138
|
+
onUploadSuccessAnalytics();
|
|
139
|
+
dispatch({
|
|
140
|
+
type: 'success',
|
|
141
|
+
payload: {
|
|
142
|
+
id: uploadableFileUpfrontIds.id,
|
|
143
|
+
collection: collection,
|
|
144
|
+
height: dimensions.height,
|
|
145
|
+
width: dimensions.width,
|
|
146
|
+
occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
_context.next = 24;
|
|
150
|
+
break;
|
|
151
|
+
case 21:
|
|
152
|
+
_context.prev = 21;
|
|
153
|
+
_context.t0 = _context["catch"](11);
|
|
154
|
+
if (typeof _context.t0 === 'string' && _context.t0 === 'Could not download remote file') {
|
|
155
|
+
// TODO: Make sure this gets good unit test coverage with the actual
|
|
156
|
+
// media plugin. This hard coded error message could be changed at any
|
|
157
|
+
// point and we need a unit test to break to stop people changing it.
|
|
158
|
+
onUploadFailureAnalytics(_context.t0);
|
|
159
|
+
dispatch({
|
|
160
|
+
type: 'warning',
|
|
161
|
+
warning: _context.t0,
|
|
162
|
+
url: url
|
|
163
|
+
});
|
|
164
|
+
} else if (_context.t0 instanceof Error) {
|
|
165
|
+
message = 'Image preview fetch failed';
|
|
166
|
+
onUploadFailureAnalytics(message);
|
|
167
|
+
dispatch({
|
|
168
|
+
type: 'error',
|
|
169
|
+
error: message
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
onUploadFailureAnalytics('Unknown error');
|
|
173
|
+
dispatch({
|
|
174
|
+
type: 'error',
|
|
175
|
+
error: 'Unknown error'
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
case 24:
|
|
179
|
+
case "end":
|
|
180
|
+
return _context.stop();
|
|
181
|
+
}
|
|
182
|
+
}, _callee, null, [[11, 21]]);
|
|
183
|
+
})), [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, url]);
|
|
184
|
+
var onInsertClick = _react.default.useCallback(function () {
|
|
185
|
+
if (previewState.previewInfo) {
|
|
186
|
+
return onInsert(previewState.previewInfo);
|
|
187
|
+
}
|
|
188
|
+
if (previewState.warning) {
|
|
189
|
+
return onExternalInsert(url);
|
|
190
|
+
}
|
|
191
|
+
}, [onExternalInsert, onInsert, previewState.previewInfo, previewState.warning, url]);
|
|
192
|
+
return /*#__PURE__*/_react.default.createElement("form", {
|
|
193
|
+
onSubmit: function onSubmit(e) {
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
uploadExternalMedia();
|
|
196
|
+
}
|
|
197
|
+
}, /*#__PURE__*/_react.default.createElement(_primitives.Stack, {
|
|
198
|
+
space: "space.150"
|
|
199
|
+
}, /*#__PURE__*/_react.default.createElement(_textfield.default, {
|
|
200
|
+
autoFocus: true,
|
|
201
|
+
value: url,
|
|
202
|
+
placeholder: strings.pasteLinkToUpload,
|
|
203
|
+
onChange: onURLChange
|
|
204
|
+
}), previewState.previewInfo && /*#__PURE__*/_react.default.createElement(_primitives.Inline, {
|
|
205
|
+
alignInline: "center",
|
|
206
|
+
alignBlock: "center",
|
|
207
|
+
xcss: PreviewImageStyles,
|
|
208
|
+
space: "space.200"
|
|
209
|
+
}, /*#__PURE__*/_react.default.createElement(_MediaCard.MediaCard, {
|
|
210
|
+
attrs: previewState.previewInfo,
|
|
211
|
+
mediaProvider: mediaProvider
|
|
212
|
+
})), previewState.error && /*#__PURE__*/_react.default.createElement(_sectionMessage.default, {
|
|
213
|
+
appearance: "error"
|
|
214
|
+
}, strings.errorMessage), previewState.warning && /*#__PURE__*/_react.default.createElement(_sectionMessage.default, {
|
|
215
|
+
appearance: "warning"
|
|
216
|
+
}, strings.warning), !previewState.previewInfo && !previewState.error && !previewState.warning && /*#__PURE__*/_react.default.createElement(_primitives.Flex, {
|
|
217
|
+
xcss: PreviewBoxStyles,
|
|
218
|
+
alignItems: "center",
|
|
219
|
+
justifyContent: "center"
|
|
220
|
+
}, /*#__PURE__*/_react.default.createElement(_new.default, {
|
|
221
|
+
type: "submit",
|
|
222
|
+
isLoading: previewState.isLoading,
|
|
223
|
+
isDisabled: !url,
|
|
224
|
+
iconBefore: _filePreview.default
|
|
225
|
+
}, strings.loadPreview)), /*#__PURE__*/_react.default.createElement(_primitives.Box, {
|
|
226
|
+
xcss: ButtonGroupStyles
|
|
227
|
+
}, /*#__PURE__*/_react.default.createElement(_buttonGroup.default, null, /*#__PURE__*/_react.default.createElement(_new.default, {
|
|
228
|
+
appearance: "subtle"
|
|
229
|
+
}, strings.cancel), /*#__PURE__*/_react.default.createElement(_new.default, {
|
|
230
|
+
appearance: "primary",
|
|
231
|
+
isDisabled: !previewState.previewInfo && !previewState.warning,
|
|
232
|
+
onClick: onInsertClick
|
|
233
|
+
}, strings.insert)))));
|
|
234
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.MediaCard = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _react = _interopRequireDefault(require("react"));
|
|
10
|
+
var _reactIntlNext = require("react-intl-next");
|
|
11
|
+
var _messages = require("@atlaskit/editor-common/messages");
|
|
12
|
+
var _mediaCard = require("@atlaskit/media-card");
|
|
13
|
+
var maxDimensions = {
|
|
14
|
+
width: '100%',
|
|
15
|
+
height: '100%'
|
|
16
|
+
};
|
|
17
|
+
var MediaCard = exports.MediaCard = function MediaCard(_ref) {
|
|
18
|
+
var attrs = _ref.attrs,
|
|
19
|
+
mediaProviderPromise = _ref.mediaProvider;
|
|
20
|
+
var intl = (0, _reactIntlNext.useIntl)();
|
|
21
|
+
var mediaAlt = intl.formatMessage(_messages.mediaInsertMessages.mediaAlt);
|
|
22
|
+
var _React$useState = _react.default.useState(),
|
|
23
|
+
_React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
|
|
24
|
+
mediaProvider = _React$useState2[0],
|
|
25
|
+
setMediaProvider = _React$useState2[1];
|
|
26
|
+
_react.default.useEffect(function () {
|
|
27
|
+
mediaProviderPromise.then(setMediaProvider);
|
|
28
|
+
}, [mediaProviderPromise]);
|
|
29
|
+
var dimensions = _react.default.useMemo(function () {
|
|
30
|
+
return {
|
|
31
|
+
width: attrs.width,
|
|
32
|
+
height: attrs.height
|
|
33
|
+
};
|
|
34
|
+
}, [attrs.width, attrs.height]);
|
|
35
|
+
var identifier = _react.default.useMemo(function () {
|
|
36
|
+
return {
|
|
37
|
+
id: attrs.id,
|
|
38
|
+
mediaItemType: 'file',
|
|
39
|
+
collectionName: attrs.collection
|
|
40
|
+
};
|
|
41
|
+
}, [attrs.collection, attrs.id]);
|
|
42
|
+
if (!mediaProvider) {
|
|
43
|
+
return /*#__PURE__*/_react.default.createElement(_mediaCard.CardLoading, {
|
|
44
|
+
dimensions: dimensions
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return /*#__PURE__*/_react.default.createElement(_mediaCard.Card, {
|
|
48
|
+
mediaClientConfig: mediaProvider.viewMediaClientConfig,
|
|
49
|
+
resizeMode: "stretchy-fit",
|
|
50
|
+
dimensions: maxDimensions,
|
|
51
|
+
originalDimensions: dimensions,
|
|
52
|
+
identifier: identifier,
|
|
53
|
+
alt: mediaAlt
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useAnalyticsEvents = useAnalyticsEvents;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
10
|
+
function useAnalyticsEvents(dispatchAnalyticsEvent) {
|
|
11
|
+
var onUploadAnalytics = _react.default.useCallback(function () {
|
|
12
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
13
|
+
action: _analytics.ACTION.CLICKED,
|
|
14
|
+
actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
|
|
15
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
16
|
+
eventType: _analytics.EVENT_TYPE.UI
|
|
17
|
+
});
|
|
18
|
+
}, [dispatchAnalyticsEvent]);
|
|
19
|
+
var onUploadSuccessAnalytics = _react.default.useCallback(function () {
|
|
20
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
21
|
+
action: _analytics.ACTION.UPLOAD_SUCCEEDED,
|
|
22
|
+
actionSubject: _analytics.ACTION_SUBJECT.MEDIA,
|
|
23
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
24
|
+
eventType: _analytics.EVENT_TYPE.OPERATIONAL
|
|
25
|
+
});
|
|
26
|
+
}, [dispatchAnalyticsEvent]);
|
|
27
|
+
var onUploadFailureAnalytics = _react.default.useCallback(function (reason) {
|
|
28
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
29
|
+
action: _analytics.ACTION.UPLOAD_FAILED,
|
|
30
|
+
actionSubject: _analytics.ACTION_SUBJECT.MEDIA,
|
|
31
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
32
|
+
eventType: _analytics.EVENT_TYPE.OPERATIONAL,
|
|
33
|
+
attributes: {
|
|
34
|
+
reason: reason
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}, [dispatchAnalyticsEvent]);
|
|
38
|
+
return _react.default.useMemo(function () {
|
|
39
|
+
return {
|
|
40
|
+
onUploadAnalytics: onUploadAnalytics,
|
|
41
|
+
onUploadSuccessAnalytics: onUploadSuccessAnalytics,
|
|
42
|
+
onUploadFailureAnalytics: onUploadFailureAnalytics
|
|
43
|
+
};
|
|
44
|
+
}, [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
|
|
45
|
+
}
|
package/dist/es2019/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { mediaInsertPlugin } from './plugin';
|
|
1
|
+
export { mediaInsertPlugin } from './plugin';
|
|
2
|
+
export { MediaFromURL } from './ui/FromURL';
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl-next';
|
|
3
|
+
import ButtonGroup from '@atlaskit/button/button-group';
|
|
4
|
+
import Button from '@atlaskit/button/new';
|
|
5
|
+
import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
|
|
6
|
+
import EditorFilePreviewIcon from '@atlaskit/icon/glyph/editor/file-preview';
|
|
7
|
+
import { getMediaClient } from '@atlaskit/media-client-react';
|
|
8
|
+
import { Box, Flex, Inline, Stack, xcss } from '@atlaskit/primitives';
|
|
9
|
+
import SectionMessage from '@atlaskit/section-message';
|
|
10
|
+
import TextField from '@atlaskit/textfield';
|
|
11
|
+
import { MediaCard } from './MediaCard';
|
|
12
|
+
import { useAnalyticsEvents } from './useAnalyticsEvents';
|
|
13
|
+
const PreviewBoxStyles = xcss({
|
|
14
|
+
borderWidth: 'border.width',
|
|
15
|
+
borderStyle: 'dashed',
|
|
16
|
+
borderColor: 'color.border',
|
|
17
|
+
borderRadius: 'border.radius',
|
|
18
|
+
height: '200px'
|
|
19
|
+
});
|
|
20
|
+
const PreviewImageStyles = xcss({
|
|
21
|
+
height: '200px'
|
|
22
|
+
});
|
|
23
|
+
const ButtonGroupStyles = xcss({
|
|
24
|
+
alignSelf: 'end'
|
|
25
|
+
});
|
|
26
|
+
const INITIAL_PREVIEW_STATE = Object.freeze({
|
|
27
|
+
isLoading: false,
|
|
28
|
+
error: null,
|
|
29
|
+
warning: null,
|
|
30
|
+
previewInfo: null
|
|
31
|
+
});
|
|
32
|
+
const previewStateReducer = (state, action) => {
|
|
33
|
+
switch (action.type) {
|
|
34
|
+
case 'loading':
|
|
35
|
+
return {
|
|
36
|
+
...INITIAL_PREVIEW_STATE,
|
|
37
|
+
isLoading: true
|
|
38
|
+
};
|
|
39
|
+
case 'error':
|
|
40
|
+
return {
|
|
41
|
+
...INITIAL_PREVIEW_STATE,
|
|
42
|
+
error: action.error
|
|
43
|
+
};
|
|
44
|
+
case 'warning':
|
|
45
|
+
return {
|
|
46
|
+
...INITIAL_PREVIEW_STATE,
|
|
47
|
+
warning: action.warning
|
|
48
|
+
};
|
|
49
|
+
case 'success':
|
|
50
|
+
return {
|
|
51
|
+
...INITIAL_PREVIEW_STATE,
|
|
52
|
+
previewInfo: action.payload
|
|
53
|
+
};
|
|
54
|
+
case 'reset':
|
|
55
|
+
return INITIAL_PREVIEW_STATE;
|
|
56
|
+
default:
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
// TODO: Delete these before rollout
|
|
61
|
+
const placeholders = ['https://picsum.photos/200/300',
|
|
62
|
+
// has cors
|
|
63
|
+
'https://placedog.net/500/280',
|
|
64
|
+
// has cors
|
|
65
|
+
'https://preview.redd.it/gabriel-medina-at-the-olympics-after-riding-a-nearly-v0-dbyczz2fkifd1.jpeg?auto=webp&s=045550d672718427b67fb929bc6efc57116a7596' // no cors
|
|
66
|
+
];
|
|
67
|
+
export function MediaFromURL({
|
|
68
|
+
mediaProvider,
|
|
69
|
+
onInsert,
|
|
70
|
+
onExternalInsert,
|
|
71
|
+
dispatchAnalyticsEvent
|
|
72
|
+
}) {
|
|
73
|
+
const intl = useIntl();
|
|
74
|
+
const strings = {
|
|
75
|
+
loadPreview: intl.formatMessage(mediaInsertMessages.loadPreview),
|
|
76
|
+
insert: intl.formatMessage(mediaInsertMessages.insert),
|
|
77
|
+
pasteLinkToUpload: intl.formatMessage(mediaInsertMessages.pasteLinkToUpload),
|
|
78
|
+
cancel: intl.formatMessage(mediaInsertMessages.cancel),
|
|
79
|
+
errorMessage: intl.formatMessage(mediaInsertMessages.errorMessage),
|
|
80
|
+
warning: intl.formatMessage(mediaInsertMessages.warning)
|
|
81
|
+
};
|
|
82
|
+
const [url, setUrl] = React.useState(placeholders[1]);
|
|
83
|
+
const [previewState, dispatch] = React.useReducer(previewStateReducer, INITIAL_PREVIEW_STATE);
|
|
84
|
+
const {
|
|
85
|
+
onUploadAnalytics,
|
|
86
|
+
onUploadSuccessAnalytics,
|
|
87
|
+
onUploadFailureAnalytics
|
|
88
|
+
} = useAnalyticsEvents(dispatchAnalyticsEvent);
|
|
89
|
+
const onURLChange = React.useCallback(e => {
|
|
90
|
+
setUrl(e.target.value);
|
|
91
|
+
dispatch({
|
|
92
|
+
type: 'reset'
|
|
93
|
+
});
|
|
94
|
+
}, []);
|
|
95
|
+
const uploadExternalMedia = React.useCallback(async () => {
|
|
96
|
+
dispatch({
|
|
97
|
+
type: 'loading'
|
|
98
|
+
});
|
|
99
|
+
const {
|
|
100
|
+
uploadMediaClientConfig,
|
|
101
|
+
uploadParams
|
|
102
|
+
} = await mediaProvider;
|
|
103
|
+
if (!uploadMediaClientConfig) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const mediaClient = getMediaClient(uploadMediaClientConfig);
|
|
107
|
+
const collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
|
|
108
|
+
onUploadAnalytics();
|
|
109
|
+
try {
|
|
110
|
+
const {
|
|
111
|
+
uploadableFileUpfrontIds,
|
|
112
|
+
dimensions
|
|
113
|
+
} = await mediaClient.file.uploadExternal(url, collection);
|
|
114
|
+
onUploadSuccessAnalytics();
|
|
115
|
+
dispatch({
|
|
116
|
+
type: 'success',
|
|
117
|
+
payload: {
|
|
118
|
+
id: uploadableFileUpfrontIds.id,
|
|
119
|
+
collection,
|
|
120
|
+
height: dimensions.height,
|
|
121
|
+
width: dimensions.width,
|
|
122
|
+
occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
} catch (e) {
|
|
126
|
+
if (typeof e === 'string' && e === 'Could not download remote file') {
|
|
127
|
+
// TODO: Make sure this gets good unit test coverage with the actual
|
|
128
|
+
// media plugin. This hard coded error message could be changed at any
|
|
129
|
+
// point and we need a unit test to break to stop people changing it.
|
|
130
|
+
onUploadFailureAnalytics(e);
|
|
131
|
+
dispatch({
|
|
132
|
+
type: 'warning',
|
|
133
|
+
warning: e,
|
|
134
|
+
url
|
|
135
|
+
});
|
|
136
|
+
} else if (e instanceof Error) {
|
|
137
|
+
const message = 'Image preview fetch failed';
|
|
138
|
+
onUploadFailureAnalytics(message);
|
|
139
|
+
dispatch({
|
|
140
|
+
type: 'error',
|
|
141
|
+
error: message
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
onUploadFailureAnalytics('Unknown error');
|
|
145
|
+
dispatch({
|
|
146
|
+
type: 'error',
|
|
147
|
+
error: 'Unknown error'
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}, [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, url]);
|
|
152
|
+
const onInsertClick = React.useCallback(() => {
|
|
153
|
+
if (previewState.previewInfo) {
|
|
154
|
+
return onInsert(previewState.previewInfo);
|
|
155
|
+
}
|
|
156
|
+
if (previewState.warning) {
|
|
157
|
+
return onExternalInsert(url);
|
|
158
|
+
}
|
|
159
|
+
}, [onExternalInsert, onInsert, previewState.previewInfo, previewState.warning, url]);
|
|
160
|
+
return /*#__PURE__*/React.createElement("form", {
|
|
161
|
+
onSubmit: e => {
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
uploadExternalMedia();
|
|
164
|
+
}
|
|
165
|
+
}, /*#__PURE__*/React.createElement(Stack, {
|
|
166
|
+
space: "space.150"
|
|
167
|
+
}, /*#__PURE__*/React.createElement(TextField, {
|
|
168
|
+
autoFocus: true,
|
|
169
|
+
value: url,
|
|
170
|
+
placeholder: strings.pasteLinkToUpload,
|
|
171
|
+
onChange: onURLChange
|
|
172
|
+
}), previewState.previewInfo && /*#__PURE__*/React.createElement(Inline, {
|
|
173
|
+
alignInline: "center",
|
|
174
|
+
alignBlock: "center",
|
|
175
|
+
xcss: PreviewImageStyles,
|
|
176
|
+
space: "space.200"
|
|
177
|
+
}, /*#__PURE__*/React.createElement(MediaCard, {
|
|
178
|
+
attrs: previewState.previewInfo,
|
|
179
|
+
mediaProvider: mediaProvider
|
|
180
|
+
})), previewState.error && /*#__PURE__*/React.createElement(SectionMessage, {
|
|
181
|
+
appearance: "error"
|
|
182
|
+
}, strings.errorMessage), previewState.warning && /*#__PURE__*/React.createElement(SectionMessage, {
|
|
183
|
+
appearance: "warning"
|
|
184
|
+
}, strings.warning), !previewState.previewInfo && !previewState.error && !previewState.warning && /*#__PURE__*/React.createElement(Flex, {
|
|
185
|
+
xcss: PreviewBoxStyles,
|
|
186
|
+
alignItems: "center",
|
|
187
|
+
justifyContent: "center"
|
|
188
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
189
|
+
type: "submit",
|
|
190
|
+
isLoading: previewState.isLoading,
|
|
191
|
+
isDisabled: !url,
|
|
192
|
+
iconBefore: EditorFilePreviewIcon
|
|
193
|
+
}, strings.loadPreview)), /*#__PURE__*/React.createElement(Box, {
|
|
194
|
+
xcss: ButtonGroupStyles
|
|
195
|
+
}, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(Button, {
|
|
196
|
+
appearance: "subtle"
|
|
197
|
+
}, strings.cancel), /*#__PURE__*/React.createElement(Button, {
|
|
198
|
+
appearance: "primary",
|
|
199
|
+
isDisabled: !previewState.previewInfo && !previewState.warning,
|
|
200
|
+
onClick: onInsertClick
|
|
201
|
+
}, strings.insert)))));
|
|
202
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl-next';
|
|
3
|
+
import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
|
|
4
|
+
import { Card, CardLoading } from '@atlaskit/media-card';
|
|
5
|
+
const maxDimensions = {
|
|
6
|
+
width: '100%',
|
|
7
|
+
height: '100%'
|
|
8
|
+
};
|
|
9
|
+
export const MediaCard = ({
|
|
10
|
+
attrs,
|
|
11
|
+
mediaProvider: mediaProviderPromise
|
|
12
|
+
}) => {
|
|
13
|
+
const intl = useIntl();
|
|
14
|
+
const mediaAlt = intl.formatMessage(mediaInsertMessages.mediaAlt);
|
|
15
|
+
const [mediaProvider, setMediaProvider] = React.useState();
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
mediaProviderPromise.then(setMediaProvider);
|
|
18
|
+
}, [mediaProviderPromise]);
|
|
19
|
+
const dimensions = React.useMemo(() => {
|
|
20
|
+
return {
|
|
21
|
+
width: attrs.width,
|
|
22
|
+
height: attrs.height
|
|
23
|
+
};
|
|
24
|
+
}, [attrs.width, attrs.height]);
|
|
25
|
+
const identifier = React.useMemo(() => ({
|
|
26
|
+
id: attrs.id,
|
|
27
|
+
mediaItemType: 'file',
|
|
28
|
+
collectionName: attrs.collection
|
|
29
|
+
}), [attrs.collection, attrs.id]);
|
|
30
|
+
if (!mediaProvider) {
|
|
31
|
+
return /*#__PURE__*/React.createElement(CardLoading, {
|
|
32
|
+
dimensions: dimensions
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return /*#__PURE__*/React.createElement(Card, {
|
|
36
|
+
mediaClientConfig: mediaProvider.viewMediaClientConfig,
|
|
37
|
+
resizeMode: "stretchy-fit",
|
|
38
|
+
dimensions: maxDimensions,
|
|
39
|
+
originalDimensions: dimensions,
|
|
40
|
+
identifier: identifier,
|
|
41
|
+
alt: mediaAlt
|
|
42
|
+
});
|
|
43
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
export function useAnalyticsEvents(dispatchAnalyticsEvent) {
|
|
4
|
+
const onUploadAnalytics = React.useCallback(() => {
|
|
5
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
|
|
6
|
+
action: ACTION.CLICKED,
|
|
7
|
+
actionSubject: ACTION_SUBJECT.BUTTON,
|
|
8
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
9
|
+
eventType: EVENT_TYPE.UI
|
|
10
|
+
});
|
|
11
|
+
}, [dispatchAnalyticsEvent]);
|
|
12
|
+
const onUploadSuccessAnalytics = React.useCallback(() => {
|
|
13
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
|
|
14
|
+
action: ACTION.UPLOAD_SUCCEEDED,
|
|
15
|
+
actionSubject: ACTION_SUBJECT.MEDIA,
|
|
16
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
17
|
+
eventType: EVENT_TYPE.OPERATIONAL
|
|
18
|
+
});
|
|
19
|
+
}, [dispatchAnalyticsEvent]);
|
|
20
|
+
const onUploadFailureAnalytics = React.useCallback(reason => {
|
|
21
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
|
|
22
|
+
action: ACTION.UPLOAD_FAILED,
|
|
23
|
+
actionSubject: ACTION_SUBJECT.MEDIA,
|
|
24
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
25
|
+
eventType: EVENT_TYPE.OPERATIONAL,
|
|
26
|
+
attributes: {
|
|
27
|
+
reason
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}, [dispatchAnalyticsEvent]);
|
|
31
|
+
return React.useMemo(() => ({
|
|
32
|
+
onUploadAnalytics,
|
|
33
|
+
onUploadSuccessAnalytics,
|
|
34
|
+
onUploadFailureAnalytics
|
|
35
|
+
}), [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
|
|
36
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { mediaInsertPlugin } from './plugin';
|
|
1
|
+
export { mediaInsertPlugin } from './plugin';
|
|
2
|
+
export { MediaFromURL } from './ui/FromURL';
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
|
+
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; }
|
|
6
|
+
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; }
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { useIntl } from 'react-intl-next';
|
|
9
|
+
import ButtonGroup from '@atlaskit/button/button-group';
|
|
10
|
+
import Button from '@atlaskit/button/new';
|
|
11
|
+
import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
|
|
12
|
+
import EditorFilePreviewIcon from '@atlaskit/icon/glyph/editor/file-preview';
|
|
13
|
+
import { getMediaClient } from '@atlaskit/media-client-react';
|
|
14
|
+
import { Box, Flex, Inline, Stack, xcss } from '@atlaskit/primitives';
|
|
15
|
+
import SectionMessage from '@atlaskit/section-message';
|
|
16
|
+
import TextField from '@atlaskit/textfield';
|
|
17
|
+
import { MediaCard } from './MediaCard';
|
|
18
|
+
import { useAnalyticsEvents } from './useAnalyticsEvents';
|
|
19
|
+
var PreviewBoxStyles = xcss({
|
|
20
|
+
borderWidth: 'border.width',
|
|
21
|
+
borderStyle: 'dashed',
|
|
22
|
+
borderColor: 'color.border',
|
|
23
|
+
borderRadius: 'border.radius',
|
|
24
|
+
height: '200px'
|
|
25
|
+
});
|
|
26
|
+
var PreviewImageStyles = xcss({
|
|
27
|
+
height: '200px'
|
|
28
|
+
});
|
|
29
|
+
var ButtonGroupStyles = xcss({
|
|
30
|
+
alignSelf: 'end'
|
|
31
|
+
});
|
|
32
|
+
var INITIAL_PREVIEW_STATE = Object.freeze({
|
|
33
|
+
isLoading: false,
|
|
34
|
+
error: null,
|
|
35
|
+
warning: null,
|
|
36
|
+
previewInfo: null
|
|
37
|
+
});
|
|
38
|
+
var previewStateReducer = function previewStateReducer(state, action) {
|
|
39
|
+
switch (action.type) {
|
|
40
|
+
case 'loading':
|
|
41
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
42
|
+
isLoading: true
|
|
43
|
+
});
|
|
44
|
+
case 'error':
|
|
45
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
46
|
+
error: action.error
|
|
47
|
+
});
|
|
48
|
+
case 'warning':
|
|
49
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
50
|
+
warning: action.warning
|
|
51
|
+
});
|
|
52
|
+
case 'success':
|
|
53
|
+
return _objectSpread(_objectSpread({}, INITIAL_PREVIEW_STATE), {}, {
|
|
54
|
+
previewInfo: action.payload
|
|
55
|
+
});
|
|
56
|
+
case 'reset':
|
|
57
|
+
return INITIAL_PREVIEW_STATE;
|
|
58
|
+
default:
|
|
59
|
+
return state;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
// TODO: Delete these before rollout
|
|
63
|
+
var placeholders = ['https://picsum.photos/200/300',
|
|
64
|
+
// has cors
|
|
65
|
+
'https://placedog.net/500/280',
|
|
66
|
+
// has cors
|
|
67
|
+
'https://preview.redd.it/gabriel-medina-at-the-olympics-after-riding-a-nearly-v0-dbyczz2fkifd1.jpeg?auto=webp&s=045550d672718427b67fb929bc6efc57116a7596' // no cors
|
|
68
|
+
];
|
|
69
|
+
export function MediaFromURL(_ref) {
|
|
70
|
+
var mediaProvider = _ref.mediaProvider,
|
|
71
|
+
onInsert = _ref.onInsert,
|
|
72
|
+
onExternalInsert = _ref.onExternalInsert,
|
|
73
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
|
|
74
|
+
var intl = useIntl();
|
|
75
|
+
var strings = {
|
|
76
|
+
loadPreview: intl.formatMessage(mediaInsertMessages.loadPreview),
|
|
77
|
+
insert: intl.formatMessage(mediaInsertMessages.insert),
|
|
78
|
+
pasteLinkToUpload: intl.formatMessage(mediaInsertMessages.pasteLinkToUpload),
|
|
79
|
+
cancel: intl.formatMessage(mediaInsertMessages.cancel),
|
|
80
|
+
errorMessage: intl.formatMessage(mediaInsertMessages.errorMessage),
|
|
81
|
+
warning: intl.formatMessage(mediaInsertMessages.warning)
|
|
82
|
+
};
|
|
83
|
+
var _React$useState = React.useState(placeholders[1]),
|
|
84
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
85
|
+
url = _React$useState2[0],
|
|
86
|
+
setUrl = _React$useState2[1];
|
|
87
|
+
var _React$useReducer = React.useReducer(previewStateReducer, INITIAL_PREVIEW_STATE),
|
|
88
|
+
_React$useReducer2 = _slicedToArray(_React$useReducer, 2),
|
|
89
|
+
previewState = _React$useReducer2[0],
|
|
90
|
+
dispatch = _React$useReducer2[1];
|
|
91
|
+
var _useAnalyticsEvents = useAnalyticsEvents(dispatchAnalyticsEvent),
|
|
92
|
+
onUploadAnalytics = _useAnalyticsEvents.onUploadAnalytics,
|
|
93
|
+
onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
|
|
94
|
+
onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
|
|
95
|
+
var onURLChange = React.useCallback(function (e) {
|
|
96
|
+
setUrl(e.target.value);
|
|
97
|
+
dispatch({
|
|
98
|
+
type: 'reset'
|
|
99
|
+
});
|
|
100
|
+
}, []);
|
|
101
|
+
var uploadExternalMedia = React.useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
102
|
+
var _yield$mediaProvider, uploadMediaClientConfig, uploadParams, mediaClient, collection, _yield$mediaClient$fi, uploadableFileUpfrontIds, dimensions, message;
|
|
103
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
104
|
+
while (1) switch (_context.prev = _context.next) {
|
|
105
|
+
case 0:
|
|
106
|
+
dispatch({
|
|
107
|
+
type: 'loading'
|
|
108
|
+
});
|
|
109
|
+
_context.next = 3;
|
|
110
|
+
return mediaProvider;
|
|
111
|
+
case 3:
|
|
112
|
+
_yield$mediaProvider = _context.sent;
|
|
113
|
+
uploadMediaClientConfig = _yield$mediaProvider.uploadMediaClientConfig;
|
|
114
|
+
uploadParams = _yield$mediaProvider.uploadParams;
|
|
115
|
+
if (uploadMediaClientConfig) {
|
|
116
|
+
_context.next = 8;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
return _context.abrupt("return");
|
|
120
|
+
case 8:
|
|
121
|
+
mediaClient = getMediaClient(uploadMediaClientConfig);
|
|
122
|
+
collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
|
|
123
|
+
onUploadAnalytics();
|
|
124
|
+
_context.prev = 11;
|
|
125
|
+
_context.next = 14;
|
|
126
|
+
return mediaClient.file.uploadExternal(url, collection);
|
|
127
|
+
case 14:
|
|
128
|
+
_yield$mediaClient$fi = _context.sent;
|
|
129
|
+
uploadableFileUpfrontIds = _yield$mediaClient$fi.uploadableFileUpfrontIds;
|
|
130
|
+
dimensions = _yield$mediaClient$fi.dimensions;
|
|
131
|
+
onUploadSuccessAnalytics();
|
|
132
|
+
dispatch({
|
|
133
|
+
type: 'success',
|
|
134
|
+
payload: {
|
|
135
|
+
id: uploadableFileUpfrontIds.id,
|
|
136
|
+
collection: collection,
|
|
137
|
+
height: dimensions.height,
|
|
138
|
+
width: dimensions.width,
|
|
139
|
+
occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
_context.next = 24;
|
|
143
|
+
break;
|
|
144
|
+
case 21:
|
|
145
|
+
_context.prev = 21;
|
|
146
|
+
_context.t0 = _context["catch"](11);
|
|
147
|
+
if (typeof _context.t0 === 'string' && _context.t0 === 'Could not download remote file') {
|
|
148
|
+
// TODO: Make sure this gets good unit test coverage with the actual
|
|
149
|
+
// media plugin. This hard coded error message could be changed at any
|
|
150
|
+
// point and we need a unit test to break to stop people changing it.
|
|
151
|
+
onUploadFailureAnalytics(_context.t0);
|
|
152
|
+
dispatch({
|
|
153
|
+
type: 'warning',
|
|
154
|
+
warning: _context.t0,
|
|
155
|
+
url: url
|
|
156
|
+
});
|
|
157
|
+
} else if (_context.t0 instanceof Error) {
|
|
158
|
+
message = 'Image preview fetch failed';
|
|
159
|
+
onUploadFailureAnalytics(message);
|
|
160
|
+
dispatch({
|
|
161
|
+
type: 'error',
|
|
162
|
+
error: message
|
|
163
|
+
});
|
|
164
|
+
} else {
|
|
165
|
+
onUploadFailureAnalytics('Unknown error');
|
|
166
|
+
dispatch({
|
|
167
|
+
type: 'error',
|
|
168
|
+
error: 'Unknown error'
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
case 24:
|
|
172
|
+
case "end":
|
|
173
|
+
return _context.stop();
|
|
174
|
+
}
|
|
175
|
+
}, _callee, null, [[11, 21]]);
|
|
176
|
+
})), [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, url]);
|
|
177
|
+
var onInsertClick = React.useCallback(function () {
|
|
178
|
+
if (previewState.previewInfo) {
|
|
179
|
+
return onInsert(previewState.previewInfo);
|
|
180
|
+
}
|
|
181
|
+
if (previewState.warning) {
|
|
182
|
+
return onExternalInsert(url);
|
|
183
|
+
}
|
|
184
|
+
}, [onExternalInsert, onInsert, previewState.previewInfo, previewState.warning, url]);
|
|
185
|
+
return /*#__PURE__*/React.createElement("form", {
|
|
186
|
+
onSubmit: function onSubmit(e) {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
uploadExternalMedia();
|
|
189
|
+
}
|
|
190
|
+
}, /*#__PURE__*/React.createElement(Stack, {
|
|
191
|
+
space: "space.150"
|
|
192
|
+
}, /*#__PURE__*/React.createElement(TextField, {
|
|
193
|
+
autoFocus: true,
|
|
194
|
+
value: url,
|
|
195
|
+
placeholder: strings.pasteLinkToUpload,
|
|
196
|
+
onChange: onURLChange
|
|
197
|
+
}), previewState.previewInfo && /*#__PURE__*/React.createElement(Inline, {
|
|
198
|
+
alignInline: "center",
|
|
199
|
+
alignBlock: "center",
|
|
200
|
+
xcss: PreviewImageStyles,
|
|
201
|
+
space: "space.200"
|
|
202
|
+
}, /*#__PURE__*/React.createElement(MediaCard, {
|
|
203
|
+
attrs: previewState.previewInfo,
|
|
204
|
+
mediaProvider: mediaProvider
|
|
205
|
+
})), previewState.error && /*#__PURE__*/React.createElement(SectionMessage, {
|
|
206
|
+
appearance: "error"
|
|
207
|
+
}, strings.errorMessage), previewState.warning && /*#__PURE__*/React.createElement(SectionMessage, {
|
|
208
|
+
appearance: "warning"
|
|
209
|
+
}, strings.warning), !previewState.previewInfo && !previewState.error && !previewState.warning && /*#__PURE__*/React.createElement(Flex, {
|
|
210
|
+
xcss: PreviewBoxStyles,
|
|
211
|
+
alignItems: "center",
|
|
212
|
+
justifyContent: "center"
|
|
213
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
214
|
+
type: "submit",
|
|
215
|
+
isLoading: previewState.isLoading,
|
|
216
|
+
isDisabled: !url,
|
|
217
|
+
iconBefore: EditorFilePreviewIcon
|
|
218
|
+
}, strings.loadPreview)), /*#__PURE__*/React.createElement(Box, {
|
|
219
|
+
xcss: ButtonGroupStyles
|
|
220
|
+
}, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(Button, {
|
|
221
|
+
appearance: "subtle"
|
|
222
|
+
}, strings.cancel), /*#__PURE__*/React.createElement(Button, {
|
|
223
|
+
appearance: "primary",
|
|
224
|
+
isDisabled: !previewState.previewInfo && !previewState.warning,
|
|
225
|
+
onClick: onInsertClick
|
|
226
|
+
}, strings.insert)))));
|
|
227
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useIntl } from 'react-intl-next';
|
|
4
|
+
import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
|
|
5
|
+
import { Card, CardLoading } from '@atlaskit/media-card';
|
|
6
|
+
var maxDimensions = {
|
|
7
|
+
width: '100%',
|
|
8
|
+
height: '100%'
|
|
9
|
+
};
|
|
10
|
+
export var MediaCard = function MediaCard(_ref) {
|
|
11
|
+
var attrs = _ref.attrs,
|
|
12
|
+
mediaProviderPromise = _ref.mediaProvider;
|
|
13
|
+
var intl = useIntl();
|
|
14
|
+
var mediaAlt = intl.formatMessage(mediaInsertMessages.mediaAlt);
|
|
15
|
+
var _React$useState = React.useState(),
|
|
16
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
17
|
+
mediaProvider = _React$useState2[0],
|
|
18
|
+
setMediaProvider = _React$useState2[1];
|
|
19
|
+
React.useEffect(function () {
|
|
20
|
+
mediaProviderPromise.then(setMediaProvider);
|
|
21
|
+
}, [mediaProviderPromise]);
|
|
22
|
+
var dimensions = React.useMemo(function () {
|
|
23
|
+
return {
|
|
24
|
+
width: attrs.width,
|
|
25
|
+
height: attrs.height
|
|
26
|
+
};
|
|
27
|
+
}, [attrs.width, attrs.height]);
|
|
28
|
+
var identifier = React.useMemo(function () {
|
|
29
|
+
return {
|
|
30
|
+
id: attrs.id,
|
|
31
|
+
mediaItemType: 'file',
|
|
32
|
+
collectionName: attrs.collection
|
|
33
|
+
};
|
|
34
|
+
}, [attrs.collection, attrs.id]);
|
|
35
|
+
if (!mediaProvider) {
|
|
36
|
+
return /*#__PURE__*/React.createElement(CardLoading, {
|
|
37
|
+
dimensions: dimensions
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return /*#__PURE__*/React.createElement(Card, {
|
|
41
|
+
mediaClientConfig: mediaProvider.viewMediaClientConfig,
|
|
42
|
+
resizeMode: "stretchy-fit",
|
|
43
|
+
dimensions: maxDimensions,
|
|
44
|
+
originalDimensions: dimensions,
|
|
45
|
+
identifier: identifier,
|
|
46
|
+
alt: mediaAlt
|
|
47
|
+
});
|
|
48
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
export function useAnalyticsEvents(dispatchAnalyticsEvent) {
|
|
4
|
+
var onUploadAnalytics = React.useCallback(function () {
|
|
5
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
6
|
+
action: ACTION.CLICKED,
|
|
7
|
+
actionSubject: ACTION_SUBJECT.BUTTON,
|
|
8
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
9
|
+
eventType: EVENT_TYPE.UI
|
|
10
|
+
});
|
|
11
|
+
}, [dispatchAnalyticsEvent]);
|
|
12
|
+
var onUploadSuccessAnalytics = React.useCallback(function () {
|
|
13
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
14
|
+
action: ACTION.UPLOAD_SUCCEEDED,
|
|
15
|
+
actionSubject: ACTION_SUBJECT.MEDIA,
|
|
16
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
17
|
+
eventType: EVENT_TYPE.OPERATIONAL
|
|
18
|
+
});
|
|
19
|
+
}, [dispatchAnalyticsEvent]);
|
|
20
|
+
var onUploadFailureAnalytics = React.useCallback(function (reason) {
|
|
21
|
+
dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 || dispatchAnalyticsEvent({
|
|
22
|
+
action: ACTION.UPLOAD_FAILED,
|
|
23
|
+
actionSubject: ACTION_SUBJECT.MEDIA,
|
|
24
|
+
actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
|
|
25
|
+
eventType: EVENT_TYPE.OPERATIONAL,
|
|
26
|
+
attributes: {
|
|
27
|
+
reason: reason
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}, [dispatchAnalyticsEvent]);
|
|
31
|
+
return React.useMemo(function () {
|
|
32
|
+
return {
|
|
33
|
+
onUploadAnalytics: onUploadAnalytics,
|
|
34
|
+
onUploadSuccessAnalytics: onUploadSuccessAnalytics,
|
|
35
|
+
onUploadFailureAnalytics: onUploadFailureAnalytics
|
|
36
|
+
};
|
|
37
|
+
}, [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
|
|
38
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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: Promise<MediaProvider>;
|
|
7
|
+
onInsert: (attrs: OnInsertAttrs) => void;
|
|
8
|
+
onExternalInsert: (url: string) => void;
|
|
9
|
+
dispatchAnalyticsEvent?: DispatchAnalyticsEvent;
|
|
10
|
+
};
|
|
11
|
+
export declare function MediaFromURL({ mediaProvider, onInsert, onExternalInsert, dispatchAnalyticsEvent, }: Props): JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
|
|
3
|
+
import { type OnInsertAttrs } from './types';
|
|
4
|
+
type Props = {
|
|
5
|
+
attrs: OnInsertAttrs;
|
|
6
|
+
mediaProvider: Promise<MediaProvider>;
|
|
7
|
+
};
|
|
8
|
+
export declare const MediaCard: ({ attrs, mediaProvider: mediaProviderPromise }: Props) => JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
export declare function useAnalyticsEvents(dispatchAnalyticsEvent?: DispatchAnalyticsEvent): {
|
|
3
|
+
onUploadAnalytics: () => void;
|
|
4
|
+
onUploadSuccessAnalytics: () => void;
|
|
5
|
+
onUploadFailureAnalytics: (reason: string) => void;
|
|
6
|
+
};
|
|
@@ -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: Promise<MediaProvider>;
|
|
7
|
+
onInsert: (attrs: OnInsertAttrs) => void;
|
|
8
|
+
onExternalInsert: (url: string) => void;
|
|
9
|
+
dispatchAnalyticsEvent?: DispatchAnalyticsEvent;
|
|
10
|
+
};
|
|
11
|
+
export declare function MediaFromURL({ mediaProvider, onInsert, onExternalInsert, dispatchAnalyticsEvent, }: Props): JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { MediaProvider } from '@atlaskit/editor-common/provider-factory';
|
|
3
|
+
import { type OnInsertAttrs } from './types';
|
|
4
|
+
type Props = {
|
|
5
|
+
attrs: OnInsertAttrs;
|
|
6
|
+
mediaProvider: Promise<MediaProvider>;
|
|
7
|
+
};
|
|
8
|
+
export declare const MediaCard: ({ attrs, mediaProvider: mediaProviderPromise }: Props) => JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
export declare function useAnalyticsEvents(dispatchAnalyticsEvent?: DispatchAnalyticsEvent): {
|
|
3
|
+
onUploadAnalytics: () => void;
|
|
4
|
+
onUploadSuccessAnalytics: () => void;
|
|
5
|
+
onUploadFailureAnalytics: (reason: string) => void;
|
|
6
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-media-insert",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Media Insert plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -24,12 +24,21 @@
|
|
|
24
24
|
".": "./src/index.ts"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@atlaskit/
|
|
28
|
-
"@
|
|
27
|
+
"@atlaskit/button": "^19.1.0",
|
|
28
|
+
"@atlaskit/editor-common": "^87.6.0",
|
|
29
|
+
"@atlaskit/icon": "^22.11.0",
|
|
30
|
+
"@atlaskit/media-card": "^78.0.0",
|
|
31
|
+
"@atlaskit/media-client": "^27.3.0",
|
|
32
|
+
"@atlaskit/media-client-react": "^2.0.0",
|
|
33
|
+
"@atlaskit/primitives": "^11.1.0",
|
|
34
|
+
"@atlaskit/section-message": "^6.5.0",
|
|
35
|
+
"@atlaskit/textfield": "^6.4.0",
|
|
36
|
+
"@babel/runtime": "^7.0.0",
|
|
37
|
+
"react": "^16.8.0",
|
|
38
|
+
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
29
39
|
},
|
|
30
40
|
"peerDependencies": {
|
|
31
|
-
"@atlaskit/tokens": "^1.
|
|
32
|
-
"react": "^16.8.0"
|
|
41
|
+
"@atlaskit/tokens": "^1.57.0"
|
|
33
42
|
},
|
|
34
43
|
"devDependencies": {
|
|
35
44
|
"typescript": "~5.4.2"
|
|
@@ -69,7 +78,6 @@
|
|
|
69
78
|
]
|
|
70
79
|
}
|
|
71
80
|
},
|
|
72
|
-
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.0",
|
|
73
81
|
"stricter": {
|
|
74
82
|
"no-unused-dependencies": {
|
|
75
83
|
"checkDevDependencies": true
|