@atlaskit/link-create 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/analytics.spec.yaml +85 -0
  3. package/dist/cjs/common/constants.js +10 -0
  4. package/dist/cjs/common/utils/analytics/analytics.codegen.js +27 -0
  5. package/dist/cjs/common/utils/analytics/context.js +103 -0
  6. package/dist/cjs/common/utils/analytics/index.js +18 -0
  7. package/dist/cjs/controllers/callback-context/main.js +17 -3
  8. package/dist/cjs/ui/create-form/main.js +18 -8
  9. package/dist/cjs/ui/error-boundary/error-boundary-ui/error-svg/index.js +1 -0
  10. package/dist/cjs/ui/error-boundary/index.js +22 -2
  11. package/dist/cjs/ui/main.js +51 -15
  12. package/dist/cjs/version.json +1 -1
  13. package/dist/es2019/common/constants.js +2 -0
  14. package/dist/es2019/common/utils/analytics/analytics.codegen.js +20 -0
  15. package/dist/es2019/common/utils/analytics/context.js +86 -0
  16. package/dist/es2019/common/utils/analytics/index.js +1 -0
  17. package/dist/es2019/controllers/callback-context/main.js +18 -2
  18. package/dist/es2019/ui/create-form/main.js +15 -4
  19. package/dist/es2019/ui/error-boundary/error-boundary-ui/error-svg/index.js +1 -0
  20. package/dist/es2019/ui/error-boundary/index.js +20 -2
  21. package/dist/es2019/ui/main.js +53 -16
  22. package/dist/es2019/version.json +1 -1
  23. package/dist/esm/common/constants.js +2 -0
  24. package/dist/esm/common/utils/analytics/analytics.codegen.js +20 -0
  25. package/dist/esm/common/utils/analytics/context.js +91 -0
  26. package/dist/esm/common/utils/analytics/index.js +1 -0
  27. package/dist/esm/controllers/callback-context/main.js +16 -3
  28. package/dist/esm/ui/create-form/main.js +18 -8
  29. package/dist/esm/ui/error-boundary/error-boundary-ui/error-svg/index.js +1 -0
  30. package/dist/esm/ui/error-boundary/index.js +19 -2
  31. package/dist/esm/ui/main.js +49 -15
  32. package/dist/esm/version.json +1 -1
  33. package/dist/types/common/constants.d.ts +2 -0
  34. package/dist/types/common/types.d.ts +80 -0
  35. package/dist/types/common/utils/analytics/analytics.codegen.d.ts +48 -0
  36. package/dist/types/common/utils/analytics/context.d.ts +29 -0
  37. package/dist/types/common/utils/analytics/index.d.ts +1 -0
  38. package/dist/types/controllers/callback-context/main.d.ts +5 -1
  39. package/dist/types/index.d.ts +2 -2
  40. package/dist/types/ui/error-boundary/index.d.ts +2 -6
  41. package/dist/types/ui/group-selection/types.d.ts +1 -14
  42. package/dist/types/ui/main.d.ts +5 -3
  43. package/dist/types/ui/types.d.ts +0 -61
  44. package/package.json +7 -2
  45. package/report.api.md +12 -7
  46. package/tmp/api-report-tmp.d.ts +10 -5
@@ -1,4 +1,7 @@
1
1
  import React, { useContext, useMemo } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
4
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
2
5
  const LinkCreateCallbackContext = /*#__PURE__*/React.createContext({});
3
6
  const LinkCreateCallbackProvider = ({
4
7
  children,
@@ -6,11 +9,24 @@ const LinkCreateCallbackProvider = ({
6
9
  onFailure,
7
10
  onCancel
8
11
  }) => {
12
+ const {
13
+ createAnalyticsEvent
14
+ } = useAnalyticsEvents();
9
15
  const value = useMemo(() => ({
10
- onCreate,
16
+ onCreate: result => {
17
+ const {
18
+ objectId,
19
+ objectType
20
+ } = result;
21
+ createAnalyticsEvent(createEventPayload('track.object.created.linkCreate', {
22
+ objectId,
23
+ objectType
24
+ })).fire(ANALYTICS_CHANNEL);
25
+ onCreate && onCreate(result);
26
+ },
11
27
  onFailure,
12
28
  onCancel
13
- }), [onCreate, onFailure, onCancel]);
29
+ }), [onFailure, onCancel, createAnalyticsEvent, onCreate]);
14
30
  return /*#__PURE__*/React.createElement(LinkCreateCallbackContext.Provider, {
15
31
  value: value
16
32
  }, children);
@@ -1,10 +1,13 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
- import React from 'react';
3
+ import React, { useCallback } from 'react';
4
4
  import { jsx } from '@emotion/react';
5
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
5
6
  import LoadingButton from '@atlaskit/button/loading-button';
6
7
  import Button from '@atlaskit/button/standard-button';
7
8
  import Form, { FormFooter, FormSection } from '@atlaskit/form';
9
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
10
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
8
11
  import { FormContextProvider, useFormContext } from '../../controllers/form-context';
9
12
  import { formStyles } from './styled';
10
13
  import { validateFormData } from './utils';
@@ -15,10 +18,14 @@ const CreateFormWithoutContext = ({
15
18
  onCancel,
16
19
  onSubmit
17
20
  }) => {
21
+ const {
22
+ createAnalyticsEvent
23
+ } = useAnalyticsEvents();
18
24
  const {
19
25
  getValidators
20
26
  } = useFormContext();
21
- const handleSubmit = async data => {
27
+ const handleSubmit = useCallback(async data => {
28
+ createAnalyticsEvent(createEventPayload('ui.button.clicked.create', {})).fire(ANALYTICS_CHANNEL);
22
29
  const validators = getValidators();
23
30
  const errors = validateFormData({
24
31
  data,
@@ -28,7 +35,11 @@ const CreateFormWithoutContext = ({
28
35
  return errors;
29
36
  }
30
37
  onSubmit(data);
31
- };
38
+ }, [createAnalyticsEvent, getValidators, onSubmit]);
39
+ const handleCancel = useCallback(() => {
40
+ createAnalyticsEvent(createEventPayload('ui.button.clicked.cancel', {})).fire(ANALYTICS_CHANNEL);
41
+ onCancel && onCancel();
42
+ }, [createAnalyticsEvent, onCancel]);
32
43
  return jsx(Form, {
33
44
  onSubmit: handleSubmit
34
45
  }, ({
@@ -42,7 +53,7 @@ const CreateFormWithoutContext = ({
42
53
  css: formStyles
43
54
  }), jsx(FormSection, null, children), jsx(FormFooter, null, jsx(Button, {
44
55
  appearance: "subtle",
45
- onClick: onCancel,
56
+ onClick: handleCancel,
46
57
  testId: 'cancel-button'
47
58
  }, "Cancel"), jsx(LoadingButton, {
48
59
  appearance: "primary",
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
1
2
  /** @jsx jsx */
2
3
  import { jsx } from '@emotion/react';
3
4
  import { errorStyles } from './styled';
@@ -1,11 +1,29 @@
1
- import React from 'react';
1
+ import React, { useCallback } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
4
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
2
5
  import { BaseErrorBoundary } from './error-boundary-base';
3
6
  import { ErrorBoundaryUI } from './error-boundary-ui';
4
7
  export const ErrorBoundary = ({
5
8
  children
6
9
  }) => {
7
- // TODO: onError => Analytics
10
+ const {
11
+ createAnalyticsEvent
12
+ } = useAnalyticsEvents();
13
+ const handleError = useCallback((error, info) => {
14
+ var _window, _window$navigator, _info$componentStack;
15
+ // Fire Analytics event
16
+ createAnalyticsEvent(createEventPayload('operational.linkCreate.unhandledErrorCaught', {
17
+ browserInfo: ((_window = window) === null || _window === void 0 ? void 0 : (_window$navigator = _window.navigator) === null || _window$navigator === void 0 ? void 0 : _window$navigator.userAgent) || 'unknown',
18
+ error: error.toString(),
19
+ componentStack: (_info$componentStack = info === null || info === void 0 ? void 0 : info.componentStack) !== null && _info$componentStack !== void 0 ? _info$componentStack : ''
20
+ })).fire(ANALYTICS_CHANNEL);
21
+
22
+ // Fire UFO failed experience
23
+ // failUfoExperience(ufoExperience.mounted);
24
+ }, [createAnalyticsEvent]);
8
25
  return /*#__PURE__*/React.createElement(BaseErrorBoundary, {
26
+ onError: handleError,
9
27
  ErrorComponent: ErrorBoundaryUI
10
28
  }, children);
11
29
  };
@@ -1,34 +1,71 @@
1
1
  /** @jsx jsx */
2
- import { memo } from 'react';
2
+ import { memo, useCallback } from 'react';
3
3
  import { jsx } from '@emotion/react';
4
+ import { AnalyticsContext, useAnalyticsEvents } from '@atlaskit/analytics-next';
4
5
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
6
+ import { ANALYTICS_CHANNEL, COMPONENT_NAME } from '../common/constants';
7
+ import { withLinkCreateAnalyticsContext } from '../common/utils/analytics';
8
+ import createEventPayload from '../common/utils/analytics/analytics.codegen';
5
9
  import { LinkCreateCallbackProvider } from '../controllers/callback-context';
10
+ import { name as packageName, version as packageVersion } from '../version.json';
6
11
  import { ErrorBoundary } from './error-boundary';
7
- function ComposedLinkCreate({
12
+ const LinkCreate = ({
8
13
  plugins,
9
- testId,
10
- groupKey,
11
14
  entityKey,
12
15
  onCreate,
13
16
  onFailure,
14
- onCancel,
15
- active
16
- }) {
17
+ onCancel
18
+ }) => {
17
19
  const chosenOne = plugins.find(plugin => plugin.key === entityKey);
18
20
  if (!chosenOne) {
19
21
  throw new Error('Make sure you specified a valid entityKey');
20
22
  }
23
+ const handleCreate = useCallback(result => {
24
+ onCreate && onCreate(result.url);
25
+ }, [onCreate]);
21
26
  return jsx(LinkCreateCallbackProvider, {
22
- onCreate: onCreate,
27
+ onCreate: handleCreate,
23
28
  onFailure: onFailure,
24
29
  onCancel: onCancel
25
30
  }, chosenOne.form);
26
- }
27
- const LinkCreate = /*#__PURE__*/memo(props => {
28
- return jsx(ModalTransition, null, !!props.active && jsx(Modal, {
29
- onClose: props.onCancel,
30
- testId: props.testId,
31
- shouldScrollInViewport: true
32
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, "Create New")), jsx(ModalBody, null, jsx(ErrorBoundary, null, jsx(ComposedLinkCreate, props)))));
31
+ };
32
+ const LinkCreateWithModal = props => {
33
+ const {
34
+ testId,
35
+ onCancel,
36
+ active
37
+ } = props;
38
+ const {
39
+ createAnalyticsEvent
40
+ } = useAnalyticsEvents();
41
+ const handleOpenComplete = useCallback(() => {
42
+ createAnalyticsEvent(createEventPayload('screen.linkCreateScreen.viewed', {})).fire(ANALYTICS_CHANNEL);
43
+ }, [createAnalyticsEvent]);
44
+ const handleCloseComplete = useCallback(() => {
45
+ createAnalyticsEvent(createEventPayload('screen.linkCreateScreen.closed', {})).fire(ANALYTICS_CHANNEL);
46
+ }, [createAnalyticsEvent]);
47
+ return jsx(ModalTransition, null, !!active && jsx(Modal, {
48
+ onClose: onCancel,
49
+ testId: testId,
50
+ shouldScrollInViewport: true,
51
+ onOpenComplete: handleOpenComplete,
52
+ onCloseComplete: handleCloseComplete
53
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, "Create New")), jsx(ModalBody, null, jsx(ErrorBoundary, null, jsx(LinkCreate, props)))));
54
+ };
55
+ const LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE__*/memo(({
56
+ ...props
57
+ }) => {
58
+ return jsx(LinkCreateWithModal, props);
59
+ }));
60
+ export const PACKAGE_DATA = {
61
+ packageName,
62
+ packageVersion,
63
+ componentName: COMPONENT_NAME,
64
+ source: COMPONENT_NAME
65
+ };
66
+ const ComposedLinkCreate = /*#__PURE__*/memo(props => {
67
+ return jsx(AnalyticsContext, {
68
+ data: PACKAGE_DATA
69
+ }, jsx(LinkCreateWithAnalyticsContext, props));
33
70
  });
34
- export default LinkCreate;
71
+ export default ComposedLinkCreate;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-create",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,2 @@
1
+ export var ANALYTICS_CHANNEL = 'media';
2
+ export var COMPONENT_NAME = 'linkCreate';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
+ *
4
+ * Generates Typescript types for analytics events from analytics.spec.yaml
5
+ *
6
+ * @codegen <<SignedSource::6d7803f5c035dc3cde1be03caa91eb04>>
7
+ * @codegenCommand yarn workspace @atlaskit/link-create run codegen-analytics
8
+ */
9
+
10
+ function createEventPayload(eventKey, attributes) {
11
+ var event = eventKey.split('.');
12
+ return {
13
+ eventType: event[0],
14
+ actionSubject: event[1],
15
+ action: event[2],
16
+ actionSubjectId: event[3],
17
+ attributes: attributes
18
+ };
19
+ }
20
+ export default createEventPayload;
@@ -0,0 +1,91 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
4
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
5
+ import React, { useCallback, useContext, useMemo, useRef, useState } from 'react';
6
+ import { AnalyticsListener } from '@atlaskit/analytics-next';
7
+ import { ANALYTICS_CHANNEL } from '../../constants';
8
+ var UNKNOWN = 'unknown';
9
+ var DEFAULT_CONTEXT_ATTRIBUTES = {
10
+ triggeredFrom: UNKNOWN,
11
+ objectName: UNKNOWN,
12
+ appearance: 'modal'
13
+ };
14
+ var LinkCreateAnalyticsContext = /*#__PURE__*/React.createContext({
15
+ trackAttribute: function trackAttribute() {},
16
+ trackAttributes: function trackAttributes() {},
17
+ getAttributes: function getAttributes() {
18
+ return DEFAULT_CONTEXT_ATTRIBUTES;
19
+ }
20
+ });
21
+ var LinkCreateAnalytics = function LinkCreateAnalytics(_ref) {
22
+ var initialContext = _ref.initialContext,
23
+ children = _ref.children;
24
+ var dataRef = useRef(_objectSpread(_objectSpread({}, DEFAULT_CONTEXT_ATTRIBUTES), initialContext));
25
+ var methods = useMemo(function () {
26
+ return {
27
+ trackAttribute: function trackAttribute(key, value) {
28
+ dataRef.current[key] = value;
29
+ },
30
+ trackAttributes: function trackAttributes(attributes) {
31
+ dataRef.current = _objectSpread(_objectSpread({}, dataRef.current), attributes);
32
+ },
33
+ getAttributes: function getAttributes() {
34
+ return dataRef.current;
35
+ }
36
+ };
37
+ }, []);
38
+ return /*#__PURE__*/React.createElement(LinkCreateAnalyticsContext.Provider, {
39
+ value: methods
40
+ }, children);
41
+ };
42
+ var contextAttributesFromInitialProps = function contextAttributesFromInitialProps(props) {
43
+ return {
44
+ objectName: props.entityKey,
45
+ triggeredFrom: props.triggeredFrom
46
+ };
47
+ };
48
+
49
+ /**
50
+ * Hook that exposes the context-level attribute getters and setters.
51
+ */
52
+ export var useLinkCreateAnalytics = function useLinkCreateAnalytics() {
53
+ return useContext(LinkCreateAnalyticsContext);
54
+ };
55
+
56
+ /**
57
+ * Wrap component in "attributes" context store and initialise the initial context attributes from props.
58
+ */
59
+ function withLinkCreateAnalytics(WrappedComponent) {
60
+ return function (props) {
61
+ var _useState = useState(function () {
62
+ return contextAttributesFromInitialProps(props);
63
+ }),
64
+ _useState2 = _slicedToArray(_useState, 1),
65
+ initialContext = _useState2[0];
66
+ return /*#__PURE__*/React.createElement(LinkCreateAnalytics, {
67
+ initialContext: initialContext
68
+ }, /*#__PURE__*/React.createElement(WrappedComponent, props));
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Wraps a component with the analytics context + listener to update events with contextual-level attributes.
74
+ * Should be implemented once at the root of the link create.
75
+ */
76
+ export function withLinkCreateAnalyticsContext(WrappedComponent) {
77
+ return withLinkCreateAnalytics(function (props) {
78
+ var _useLinkCreateAnalyti = useLinkCreateAnalytics(),
79
+ getAttributes = _useLinkCreateAnalyti.getAttributes;
80
+ var onEvent = useCallback(function (event) {
81
+ var _event$payload$attrib;
82
+ event.update({
83
+ attributes: _objectSpread(_objectSpread({}, getAttributes()), (_event$payload$attrib = event.payload.attributes) !== null && _event$payload$attrib !== void 0 ? _event$payload$attrib : {})
84
+ });
85
+ }, [getAttributes]);
86
+ return /*#__PURE__*/React.createElement(AnalyticsListener, {
87
+ channel: ANALYTICS_CHANNEL,
88
+ onEvent: onEvent
89
+ }, /*#__PURE__*/React.createElement(WrappedComponent, props));
90
+ });
91
+ }
@@ -0,0 +1 @@
1
+ export { useLinkCreateAnalytics, withLinkCreateAnalyticsContext } from './context';
@@ -1,17 +1,30 @@
1
1
  import React, { useContext, useMemo } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
4
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
2
5
  var LinkCreateCallbackContext = /*#__PURE__*/React.createContext({});
3
6
  var LinkCreateCallbackProvider = function LinkCreateCallbackProvider(_ref) {
4
7
  var children = _ref.children,
5
- onCreate = _ref.onCreate,
8
+ _onCreate = _ref.onCreate,
6
9
  onFailure = _ref.onFailure,
7
10
  onCancel = _ref.onCancel;
11
+ var _useAnalyticsEvents = useAnalyticsEvents(),
12
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
8
13
  var value = useMemo(function () {
9
14
  return {
10
- onCreate: onCreate,
15
+ onCreate: function onCreate(result) {
16
+ var objectId = result.objectId,
17
+ objectType = result.objectType;
18
+ createAnalyticsEvent(createEventPayload('track.object.created.linkCreate', {
19
+ objectId: objectId,
20
+ objectType: objectType
21
+ })).fire(ANALYTICS_CHANNEL);
22
+ _onCreate && _onCreate(result);
23
+ },
11
24
  onFailure: onFailure,
12
25
  onCancel: onCancel
13
26
  };
14
- }, [onCreate, onFailure, onCancel]);
27
+ }, [onFailure, onCancel, createAnalyticsEvent, _onCreate]);
15
28
  return /*#__PURE__*/React.createElement(LinkCreateCallbackContext.Provider, {
16
29
  value: value
17
30
  }, children);
@@ -3,11 +3,14 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
4
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function value(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) { if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; } return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) { keys.push(key); } return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) { "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); } }, stop: function stop() { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function complete(record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, catch: function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; }
5
5
  /** @jsx jsx */
6
- import React from 'react';
6
+ import React, { useCallback } from 'react';
7
7
  import { jsx } from '@emotion/react';
8
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
8
9
  import LoadingButton from '@atlaskit/button/loading-button';
9
10
  import Button from '@atlaskit/button/standard-button';
10
11
  import Form, { FormFooter, FormSection } from '@atlaskit/form';
12
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
13
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
11
14
  import { FormContextProvider, useFormContext } from '../../controllers/form-context';
12
15
  import { formStyles } from './styled';
13
16
  import { validateFormData } from './utils';
@@ -21,38 +24,45 @@ var CreateFormWithoutContext = function CreateFormWithoutContext(_ref) {
21
24
  testId = _ref.testId,
22
25
  onCancel = _ref.onCancel,
23
26
  onSubmit = _ref.onSubmit;
27
+ var _useAnalyticsEvents = useAnalyticsEvents(),
28
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
24
29
  var _useFormContext = useFormContext(),
25
30
  getValidators = _useFormContext.getValidators;
26
- var handleSubmit = /*#__PURE__*/function () {
31
+ var handleSubmit = useCallback( /*#__PURE__*/function () {
27
32
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(data) {
28
33
  var validators, errors;
29
34
  return _regeneratorRuntime().wrap(function _callee$(_context) {
30
35
  while (1) {
31
36
  switch (_context.prev = _context.next) {
32
37
  case 0:
38
+ createAnalyticsEvent(createEventPayload('ui.button.clicked.create', {})).fire(ANALYTICS_CHANNEL);
33
39
  validators = getValidators();
34
40
  errors = validateFormData({
35
41
  data: data,
36
42
  validators: validators
37
43
  });
38
44
  if (!(Object.keys(errors).length !== 0)) {
39
- _context.next = 4;
45
+ _context.next = 5;
40
46
  break;
41
47
  }
42
48
  return _context.abrupt("return", errors);
43
- case 4:
44
- onSubmit(data);
45
49
  case 5:
50
+ onSubmit(data);
51
+ case 6:
46
52
  case "end":
47
53
  return _context.stop();
48
54
  }
49
55
  }
50
56
  }, _callee);
51
57
  }));
52
- return function handleSubmit(_x) {
58
+ return function (_x) {
53
59
  return _ref2.apply(this, arguments);
54
60
  };
55
- }();
61
+ }(), [createAnalyticsEvent, getValidators, onSubmit]);
62
+ var handleCancel = useCallback(function () {
63
+ createAnalyticsEvent(createEventPayload('ui.button.clicked.cancel', {})).fire(ANALYTICS_CHANNEL);
64
+ onCancel && onCancel();
65
+ }, [createAnalyticsEvent, onCancel]);
56
66
  return jsx(Form, {
57
67
  onSubmit: handleSubmit
58
68
  }, function (_ref3) {
@@ -66,7 +76,7 @@ var CreateFormWithoutContext = function CreateFormWithoutContext(_ref) {
66
76
  css: formStyles
67
77
  }), jsx(FormSection, null, children), jsx(FormFooter, null, jsx(Button, {
68
78
  appearance: "subtle",
69
- onClick: onCancel,
79
+ onClick: handleCancel,
70
80
  testId: 'cancel-button'
71
81
  }, "Cancel"), jsx(LoadingButton, {
72
82
  appearance: "primary",
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
1
2
  /** @jsx jsx */
2
3
  import { jsx } from '@emotion/react';
3
4
  import { errorStyles } from './styled';
@@ -1,10 +1,27 @@
1
- import React from 'react';
1
+ import React, { useCallback } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
+ import { ANALYTICS_CHANNEL } from '../../common/constants';
4
+ import createEventPayload from '../../common/utils/analytics/analytics.codegen';
2
5
  import { BaseErrorBoundary } from './error-boundary-base';
3
6
  import { ErrorBoundaryUI } from './error-boundary-ui';
4
7
  export var ErrorBoundary = function ErrorBoundary(_ref) {
5
8
  var children = _ref.children;
6
- // TODO: onError => Analytics
9
+ var _useAnalyticsEvents = useAnalyticsEvents(),
10
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
11
+ var handleError = useCallback(function (error, info) {
12
+ var _window, _window$navigator, _info$componentStack;
13
+ // Fire Analytics event
14
+ createAnalyticsEvent(createEventPayload('operational.linkCreate.unhandledErrorCaught', {
15
+ browserInfo: ((_window = window) === null || _window === void 0 ? void 0 : (_window$navigator = _window.navigator) === null || _window$navigator === void 0 ? void 0 : _window$navigator.userAgent) || 'unknown',
16
+ error: error.toString(),
17
+ componentStack: (_info$componentStack = info === null || info === void 0 ? void 0 : info.componentStack) !== null && _info$componentStack !== void 0 ? _info$componentStack : ''
18
+ })).fire(ANALYTICS_CHANNEL);
19
+
20
+ // Fire UFO failed experience
21
+ // failUfoExperience(ufoExperience.mounted);
22
+ }, [createAnalyticsEvent]);
7
23
  return /*#__PURE__*/React.createElement(BaseErrorBoundary, {
24
+ onError: handleError,
8
25
  ErrorComponent: ErrorBoundaryUI
9
26
  }, children);
10
27
  };
@@ -1,35 +1,69 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  /** @jsx jsx */
2
- import { memo } from 'react';
3
+ import { memo, useCallback } from 'react';
3
4
  import { jsx } from '@emotion/react';
5
+ import { AnalyticsContext, useAnalyticsEvents } from '@atlaskit/analytics-next';
4
6
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
7
+ import { ANALYTICS_CHANNEL, COMPONENT_NAME } from '../common/constants';
8
+ import { withLinkCreateAnalyticsContext } from '../common/utils/analytics';
9
+ import createEventPayload from '../common/utils/analytics/analytics.codegen';
5
10
  import { LinkCreateCallbackProvider } from '../controllers/callback-context';
11
+ import { name as packageName, version as packageVersion } from '../version.json';
6
12
  import { ErrorBoundary } from './error-boundary';
7
- function ComposedLinkCreate(_ref) {
13
+ var LinkCreate = function LinkCreate(_ref) {
8
14
  var plugins = _ref.plugins,
9
- testId = _ref.testId,
10
- groupKey = _ref.groupKey,
11
15
  entityKey = _ref.entityKey,
12
16
  onCreate = _ref.onCreate,
13
17
  onFailure = _ref.onFailure,
14
- onCancel = _ref.onCancel,
15
- active = _ref.active;
18
+ onCancel = _ref.onCancel;
16
19
  var chosenOne = plugins.find(function (plugin) {
17
20
  return plugin.key === entityKey;
18
21
  });
19
22
  if (!chosenOne) {
20
23
  throw new Error('Make sure you specified a valid entityKey');
21
24
  }
25
+ var handleCreate = useCallback(function (result) {
26
+ onCreate && onCreate(result.url);
27
+ }, [onCreate]);
22
28
  return jsx(LinkCreateCallbackProvider, {
23
- onCreate: onCreate,
29
+ onCreate: handleCreate,
24
30
  onFailure: onFailure,
25
31
  onCancel: onCancel
26
32
  }, chosenOne.form);
27
- }
28
- var LinkCreate = /*#__PURE__*/memo(function (props) {
29
- return jsx(ModalTransition, null, !!props.active && jsx(Modal, {
30
- onClose: props.onCancel,
31
- testId: props.testId,
32
- shouldScrollInViewport: true
33
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, "Create New")), jsx(ModalBody, null, jsx(ErrorBoundary, null, jsx(ComposedLinkCreate, props)))));
33
+ };
34
+ var LinkCreateWithModal = function LinkCreateWithModal(props) {
35
+ var testId = props.testId,
36
+ onCancel = props.onCancel,
37
+ active = props.active;
38
+ var _useAnalyticsEvents = useAnalyticsEvents(),
39
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
40
+ var handleOpenComplete = useCallback(function () {
41
+ createAnalyticsEvent(createEventPayload('screen.linkCreateScreen.viewed', {})).fire(ANALYTICS_CHANNEL);
42
+ }, [createAnalyticsEvent]);
43
+ var handleCloseComplete = useCallback(function () {
44
+ createAnalyticsEvent(createEventPayload('screen.linkCreateScreen.closed', {})).fire(ANALYTICS_CHANNEL);
45
+ }, [createAnalyticsEvent]);
46
+ return jsx(ModalTransition, null, !!active && jsx(Modal, {
47
+ onClose: onCancel,
48
+ testId: testId,
49
+ shouldScrollInViewport: true,
50
+ onOpenComplete: handleOpenComplete,
51
+ onCloseComplete: handleCloseComplete
52
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, "Create New")), jsx(ModalBody, null, jsx(ErrorBoundary, null, jsx(LinkCreate, props)))));
53
+ };
54
+ var LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE__*/memo(function (_ref2) {
55
+ var props = _extends({}, _ref2);
56
+ return jsx(LinkCreateWithModal, props);
57
+ }));
58
+ export var PACKAGE_DATA = {
59
+ packageName: packageName,
60
+ packageVersion: packageVersion,
61
+ componentName: COMPONENT_NAME,
62
+ source: COMPONENT_NAME
63
+ };
64
+ var ComposedLinkCreate = /*#__PURE__*/memo(function (props) {
65
+ return jsx(AnalyticsContext, {
66
+ data: PACKAGE_DATA
67
+ }, jsx(LinkCreateWithAnalyticsContext, props));
34
68
  });
35
- export default LinkCreate;
69
+ export default ComposedLinkCreate;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-create",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,2 @@
1
+ export declare const ANALYTICS_CHANNEL = "media";
2
+ export declare const COMPONENT_NAME = "linkCreate";