@brightcove/components-embed-code-modal 1.0.6 → 1.0.8

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 (184) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc +23 -0
  3. package/.github/workflows/ci.yml +23 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.nvmrc +1 -0
  6. package/.prettierignore +7 -0
  7. package/.prettierrc +5 -0
  8. package/.release-it.json +40 -0
  9. package/.whitesource +3 -0
  10. package/CHANGELOG.md +387 -0
  11. package/CODEOWNERS +37 -0
  12. package/PULL_REQUEST_TEMPLATE.md +17 -0
  13. package/__tests__/EmbedCode.test.tsx +51 -0
  14. package/__tests__/InteractivityProject.test.tsx +50 -0
  15. package/__tests__/PlayerPreview.test.tsx +23 -0
  16. package/__tests__/TabsHeader.test.tsx +19 -0
  17. package/__tests__/TabsSection.test.tsx +46 -0
  18. package/__tests__/TitleWithTooltip.test.tsx +45 -0
  19. package/__tests__/VideoPlayer.test.tsx +38 -0
  20. package/__tests__/embedCodeGenerator.test.ts +111 -0
  21. package/__tests__/util.test.ts +89 -0
  22. package/babel.config.json +17 -0
  23. package/build/README.md +109 -0
  24. package/{index.js → build/index.js} +1 -1
  25. package/build/index.js.map +1 -0
  26. package/build/package.json +100 -0
  27. package/{src → build/src}/js/utils/embedCodeGenerator.d.ts.map +1 -1
  28. package/etc/wildcard.brightcove.com.key +27 -0
  29. package/etc/wildcard.brightcove.com.pem +96 -0
  30. package/jest/jest.setup.js +62 -0
  31. package/jest/jest.stub.js +4 -0
  32. package/jest.config.js +24 -0
  33. package/package.json +15 -5
  34. package/scripts/create-dist-pkg-prod.js +18 -0
  35. package/src/index.ts +17 -0
  36. package/src/js/EmbedCodeModal.tsx +105 -0
  37. package/src/js/components/CustomSettingsDropdown.tsx +184 -0
  38. package/src/js/components/EmbedCopySection.tsx +130 -0
  39. package/src/js/components/ModalContainer.tsx +367 -0
  40. package/src/js/components/NoPlayerModal.tsx +42 -0
  41. package/src/js/components/PlayerPreview.tsx +116 -0
  42. package/src/js/components/TabsHeader.tsx +31 -0
  43. package/src/js/components/TabsSection.tsx +74 -0
  44. package/src/js/components/TitleWithTooltip.tsx +39 -0
  45. package/src/js/components/VideoLinks.tsx +83 -0
  46. package/src/js/components/VideoPlayer.tsx +324 -0
  47. package/src/js/components/index.ts +9 -0
  48. package/src/js/components/prism/PrismLiveModal.tsx +162 -0
  49. package/src/js/components/prism/PrismPlayerControls.tsx +343 -0
  50. package/src/js/components/prism/PrismPlayerPreview.tsx +98 -0
  51. package/src/js/components/prism/index.ts +3 -0
  52. package/src/js/constants/baseUrls.ts +4 -0
  53. package/src/js/constants/embed.ts +12 -0
  54. package/src/js/constants/player.ts +32 -0
  55. package/src/js/constants/pluginsRegistry.ts +30 -0
  56. package/src/js/hooks/useGetPlayers.ts +12 -0
  57. package/src/js/i18n.ts +43 -0
  58. package/src/js/services/players-api.ts +26 -0
  59. package/src/js/services/url-shortener.ts +10 -0
  60. package/src/js/types/EmbedCodeModalProps.ts +72 -0
  61. package/src/js/types/EmbedCodeProps.ts +13 -0
  62. package/src/js/types/brightcoveEmbedCode.d.ts +18 -0
  63. package/src/js/types/players.ts +64 -0
  64. package/src/js/types/react-i18next.d.ts +8 -0
  65. package/src/js/types/studioModule.ts +7 -0
  66. package/src/js/utils/addPluginsDataToPlayers.ts +59 -0
  67. package/src/js/utils/call.ts +31 -0
  68. package/src/js/utils/dimensions.ts +53 -0
  69. package/src/js/utils/embedCodeGenerator.ts +120 -0
  70. package/src/js/utils/featureSwitches.ts +16 -0
  71. package/src/js/utils/util.ts +153 -0
  72. package/src/module.tsx +280 -0
  73. package/src/styles/CustomSettingsDropdown.sass +42 -0
  74. package/src/styles/EmbedCode.sass +30 -0
  75. package/src/styles/EmbedCodeModal.sass +76 -0
  76. package/src/styles/base.sass +1 -0
  77. package/src/styles/prism/PrismLiveModal.sass +155 -0
  78. package/src/styles/theme.sass +11 -0
  79. package/src/styles/typings.td.ts +9 -0
  80. package/src/translations/en.json +61 -0
  81. package/src/translations/es.json +61 -0
  82. package/src/translations/fr.json +61 -0
  83. package/src/translations/ja.json +61 -0
  84. package/src/translations/ko.json +61 -0
  85. package/src/translations/zh.json +61 -0
  86. package/src/types/studio.ts +197 -0
  87. package/tsconfig.json +34 -0
  88. package/webpack.config.js +117 -0
  89. package/index.js.map +0 -1
  90. package/src/js/components/prism/PrismCodeCard.d.ts +0 -9
  91. package/src/js/components/prism/PrismCodeCard.d.ts.map +0 -1
  92. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts +0 -0
  93. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts.map +0 -0
  94. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts +0 -0
  95. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts.map +0 -0
  96. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts +0 -0
  97. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts.map +0 -0
  98. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts +0 -0
  99. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts.map +0 -0
  100. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts +0 -0
  101. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts.map +0 -0
  102. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts +0 -0
  103. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts.map +0 -0
  104. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts +0 -0
  105. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts.map +0 -0
  106. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts +0 -0
  107. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts.map +0 -0
  108. /package/{__tests__ → build/__tests__}/util.test.d.ts +0 -0
  109. /package/{__tests__ → build/__tests__}/util.test.d.ts.map +0 -0
  110. /package/{src → build/src}/index.d.ts +0 -0
  111. /package/{src → build/src}/index.d.ts.map +0 -0
  112. /package/{src → build/src}/js/EmbedCodeModal.d.ts +0 -0
  113. /package/{src → build/src}/js/EmbedCodeModal.d.ts.map +0 -0
  114. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts +0 -0
  115. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts.map +0 -0
  116. /package/{src → build/src}/js/components/EmbedCopySection.d.ts +0 -0
  117. /package/{src → build/src}/js/components/EmbedCopySection.d.ts.map +0 -0
  118. /package/{src → build/src}/js/components/ModalContainer.d.ts +0 -0
  119. /package/{src → build/src}/js/components/ModalContainer.d.ts.map +0 -0
  120. /package/{src → build/src}/js/components/NoPlayerModal.d.ts +0 -0
  121. /package/{src → build/src}/js/components/NoPlayerModal.d.ts.map +0 -0
  122. /package/{src → build/src}/js/components/PlayerPreview.d.ts +0 -0
  123. /package/{src → build/src}/js/components/PlayerPreview.d.ts.map +0 -0
  124. /package/{src → build/src}/js/components/TabsHeader.d.ts +0 -0
  125. /package/{src → build/src}/js/components/TabsHeader.d.ts.map +0 -0
  126. /package/{src → build/src}/js/components/TabsSection.d.ts +0 -0
  127. /package/{src → build/src}/js/components/TabsSection.d.ts.map +0 -0
  128. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts +0 -0
  129. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts.map +0 -0
  130. /package/{src → build/src}/js/components/VideoLinks.d.ts +0 -0
  131. /package/{src → build/src}/js/components/VideoLinks.d.ts.map +0 -0
  132. /package/{src → build/src}/js/components/VideoPlayer.d.ts +0 -0
  133. /package/{src → build/src}/js/components/VideoPlayer.d.ts.map +0 -0
  134. /package/{src → build/src}/js/components/index.d.ts +0 -0
  135. /package/{src → build/src}/js/components/index.d.ts.map +0 -0
  136. /package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts +0 -0
  137. /package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts.map +0 -0
  138. /package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts +0 -0
  139. /package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts.map +0 -0
  140. /package/{src → build/src}/js/components/prism/PrismPlayerPreview.d.ts +0 -0
  141. /package/{src → build/src}/js/components/prism/PrismPlayerPreview.d.ts.map +0 -0
  142. /package/{src → build/src}/js/components/prism/index.d.ts +0 -0
  143. /package/{src → build/src}/js/components/prism/index.d.ts.map +0 -0
  144. /package/{src → build/src}/js/constants/baseUrls.d.ts +0 -0
  145. /package/{src → build/src}/js/constants/baseUrls.d.ts.map +0 -0
  146. /package/{src → build/src}/js/constants/embed.d.ts +0 -0
  147. /package/{src → build/src}/js/constants/embed.d.ts.map +0 -0
  148. /package/{src → build/src}/js/constants/player.d.ts +0 -0
  149. /package/{src → build/src}/js/constants/player.d.ts.map +0 -0
  150. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts +0 -0
  151. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts.map +0 -0
  152. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts +0 -0
  153. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts.map +0 -0
  154. /package/{src → build/src}/js/i18n.d.ts +0 -0
  155. /package/{src → build/src}/js/i18n.d.ts.map +0 -0
  156. /package/{src → build/src}/js/services/players-api.d.ts +0 -0
  157. /package/{src → build/src}/js/services/players-api.d.ts.map +0 -0
  158. /package/{src → build/src}/js/services/url-shortener.d.ts +0 -0
  159. /package/{src → build/src}/js/services/url-shortener.d.ts.map +0 -0
  160. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts +0 -0
  161. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts.map +0 -0
  162. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts +0 -0
  163. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts.map +0 -0
  164. /package/{src → build/src}/js/types/players.d.ts +0 -0
  165. /package/{src → build/src}/js/types/players.d.ts.map +0 -0
  166. /package/{src → build/src}/js/types/studioModule.d.ts +0 -0
  167. /package/{src → build/src}/js/types/studioModule.d.ts.map +0 -0
  168. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts +0 -0
  169. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts.map +0 -0
  170. /package/{src → build/src}/js/utils/call.d.ts +0 -0
  171. /package/{src → build/src}/js/utils/call.d.ts.map +0 -0
  172. /package/{src → build/src}/js/utils/dimensions.d.ts +0 -0
  173. /package/{src → build/src}/js/utils/dimensions.d.ts.map +0 -0
  174. /package/{src → build/src}/js/utils/embedCodeGenerator.d.ts +0 -0
  175. /package/{src → build/src}/js/utils/featureSwitches.d.ts +0 -0
  176. /package/{src → build/src}/js/utils/featureSwitches.d.ts.map +0 -0
  177. /package/{src → build/src}/js/utils/util.d.ts +0 -0
  178. /package/{src → build/src}/js/utils/util.d.ts.map +0 -0
  179. /package/{src → build/src}/module.d.ts +0 -0
  180. /package/{src → build/src}/module.d.ts.map +0 -0
  181. /package/{src → build/src}/styles/typings.td.d.ts +0 -0
  182. /package/{src → build/src}/styles/typings.td.d.ts.map +0 -0
  183. /package/{src → build/src}/types/studio.d.ts +0 -0
  184. /package/{src → build/src}/types/studio.d.ts.map +0 -0
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Flex } from '@brightcove/studio-components';
4
+ import { getPlayerManagerModuleUrl } from 'js/utils/util';
5
+ import { NoInteractivityPlayerModalTypes } from 'js/types/EmbedCodeModalProps';
6
+
7
+ interface NoPlayerProps {
8
+ modalType: NoInteractivityPlayerModalTypes;
9
+ }
10
+
11
+ export const NoPlayerModal = ({ modalType }: NoPlayerProps) => {
12
+ const { t } = useTranslation();
13
+
14
+ const createPlayersModuleLink = (text: string) => {
15
+ return <a href={getPlayerManagerModuleUrl()}>{text}</a>;
16
+ };
17
+
18
+ return (
19
+ <Flex flexDirection='column'>
20
+ <p>
21
+ {modalType === NoInteractivityPlayerModalTypes.NO_PLAYER ? (
22
+ t('noPlayerModalContent1')
23
+ ) : (
24
+ <>
25
+ {t('activateModalContent1')}
26
+ {createPlayersModuleLink(t('activateModalContent2'))}.
27
+ </>
28
+ )}
29
+ <br />
30
+ {modalType === NoInteractivityPlayerModalTypes.NO_PLAYER
31
+ ? t('noPlayerModalContent2')
32
+ : null}
33
+ </p>
34
+
35
+ <>
36
+ {modalType === NoInteractivityPlayerModalTypes.NO_PLAYER ? (
37
+ <p>{createPlayersModuleLink(t('toPlayersModuleLink'))}</p>
38
+ ) : null}
39
+ </>
40
+ </Flex>
41
+ );
42
+ };
@@ -0,0 +1,116 @@
1
+ import React, { useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import cx from 'classnames';
4
+ import { Hideable } from '@brightcove/studio-components';
5
+ import ReactPlayerLoader from '@brightcove/react-player-loader';
6
+
7
+ import {
8
+ getPreviewPlayerUrl,
9
+ getUrlBase,
10
+ getVideoPreviewLink,
11
+ } from 'js/utils/util';
12
+ import {
13
+ bcHostedPlugins,
14
+ CAMPAIGN_PLUGIN_NAME,
15
+ VIEWER_ID_KEY_NAME,
16
+ BC_MAP_TRACKING_NAME,
17
+ } from 'js/constants/pluginsRegistry';
18
+ import { PlayerPayload } from '../types/EmbedCodeModalProps';
19
+
20
+ import { TabsSection, VideoLinks } from 'js/components';
21
+
22
+ import css from 'styles/EmbedCodeModal.sass';
23
+
24
+ interface Plugin {
25
+ name: string;
26
+ options?: Record<string, unknown>;
27
+ }
28
+
29
+ export const PlayerPreview = ({
30
+ id,
31
+ configuration,
32
+ accountId = '',
33
+ embedCodeProperties,
34
+ isOutstreamPlayer,
35
+ }: PlayerPayload) => {
36
+ const { t } = useTranslation();
37
+ const previewPlayerUrl = getPreviewPlayerUrl(accountId, id);
38
+ const playerUrl = getVideoPreviewLink({ accountId, playerId: id });
39
+
40
+ const {
41
+ hasCustomPlugins,
42
+ isCampaignPlayer,
43
+ isViewerIdSource,
44
+ isBcMapTracking,
45
+ } = useMemo((): {
46
+ isCampaignPlayer: boolean;
47
+ hasCustomPlugins: boolean;
48
+ isViewerIdSource: boolean;
49
+ isBcMapTracking: boolean;
50
+ } => {
51
+ let hasBCHostedPlugin = false;
52
+ let isCampaignPlayer = false;
53
+ let isViewerIdSource = false;
54
+ let isBcMapTracking = false;
55
+ let plugins: Plugin[] = [];
56
+
57
+ // TODO: refactor with addPluginsDataToPlayers function to reuse code
58
+ if (configuration) {
59
+ plugins = (configuration.plugins as Plugin[]) ?? plugins;
60
+ for (const plugin of plugins) {
61
+ const { name } = plugin;
62
+ hasBCHostedPlugin = bcHostedPlugins.includes(name);
63
+ isCampaignPlayer =
64
+ isCampaignPlayer || plugin.name === CAMPAIGN_PLUGIN_NAME;
65
+ isBcMapTracking =
66
+ isBcMapTracking || plugin.name === BC_MAP_TRACKING_NAME;
67
+ }
68
+ isViewerIdSource =
69
+ (configuration[VIEWER_ID_KEY_NAME] as boolean) || false;
70
+ }
71
+
72
+ return {
73
+ hasCustomPlugins: !hasBCHostedPlugin && plugins.length > 0,
74
+ isCampaignPlayer,
75
+ isViewerIdSource,
76
+ isBcMapTracking,
77
+ };
78
+ }, [configuration]);
79
+
80
+ return (
81
+ <>
82
+ <div className={css.leftContent}>
83
+ <ReactPlayerLoader
84
+ accountId={accountId}
85
+ baseUrl={getUrlBase()}
86
+ attrs={{ className: css.playerLoader }}
87
+ embedType='iframe'
88
+ refNode='player-container'
89
+ playerUrl={previewPlayerUrl}
90
+ />
91
+ <Hideable show={hasCustomPlugins}>
92
+ <span className={css.customPluginNotice}>
93
+ {t('customPluginNotice')}
94
+ </span>
95
+ </Hideable>
96
+ {isOutstreamPlayer ? null : (
97
+ <VideoLinks previewUrl={previewPlayerUrl} playerUrl={playerUrl} />
98
+ )}
99
+ </div>
100
+ <div
101
+ className={cx(css.rightContent, {
102
+ [css.rightContentFullWidth]: !!isOutstreamPlayer,
103
+ })}
104
+ >
105
+ <TabsSection
106
+ isCampaign={isCampaignPlayer}
107
+ isViewerIdSource={isViewerIdSource}
108
+ isBcMapTracking={isBcMapTracking}
109
+ playerId={id}
110
+ accountId={accountId}
111
+ embedCodeProperties={embedCodeProperties}
112
+ />
113
+ </div>
114
+ </>
115
+ );
116
+ };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { Flex, Tabs, TabList, Tab } from '@brightcove/studio-components';
3
+ import { TabsSelectedId } from 'js/types/players';
4
+
5
+ interface TabsHeaderProps {
6
+ currentTab: TabsSelectedId;
7
+ handleTabChange: () => void;
8
+ iframeLabel: string;
9
+ jsLabel: string;
10
+ }
11
+ export const TabsHeader = ({
12
+ currentTab,
13
+ handleTabChange,
14
+ iframeLabel,
15
+ jsLabel,
16
+ }: TabsHeaderProps) => {
17
+ return (
18
+ <Flex justifyContent='space-between' alignItems='baseline'>
19
+ <Tabs selectedId={currentTab} onSelect={handleTabChange}>
20
+ <TabList>
21
+ <Tab tabId='iframe' testName={'iframe-tab'}>
22
+ {iframeLabel}
23
+ </Tab>
24
+ <Tab tabId='javascript' testName={'js-tab'}>
25
+ {jsLabel}
26
+ </Tab>
27
+ </TabList>
28
+ </Tabs>
29
+ </Flex>
30
+ );
31
+ };
@@ -0,0 +1,74 @@
1
+ import React, { useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { TabPanel } from '@brightcove/studio-components';
4
+ import { TabsSelectedId } from 'js/types/players';
5
+ import css from 'styles/EmbedCodeModal.sass';
6
+ import { TabsHeader, EmbedCode } from 'js/components';
7
+ import { EmbedCodeProperties } from 'js/types/EmbedCodeModalProps';
8
+
9
+ export const TabsSection = ({
10
+ isCampaign,
11
+ isViewerIdSource,
12
+ isBcMapTracking,
13
+ ...rest
14
+ }: {
15
+ playerId: string;
16
+ isCampaign: boolean;
17
+ isViewerIdSource: boolean;
18
+ isBcMapTracking: boolean;
19
+ videoId?: string;
20
+ accountId: string;
21
+ interactivityProjectId?: string;
22
+ livePlaybackToken?: string;
23
+ adConfigId?: string;
24
+ embedCodeProperties?: EmbedCodeProperties;
25
+ }) => {
26
+ const { t } = useTranslation();
27
+ const [currentTab, setCurrentTab] = useState<TabsSelectedId>('iframe');
28
+
29
+ const isIframe = currentTab === 'iframe';
30
+
31
+ const handleTabChange = (id?: string | number) => setCurrentTab(id);
32
+
33
+ return (
34
+ <>
35
+ <TabsHeader
36
+ currentTab={currentTab}
37
+ handleTabChange={handleTabChange}
38
+ jsLabel={t('tabs.labels.javascript')}
39
+ iframeLabel={t('tabs.labels.iframe')}
40
+ />
41
+ <TabPanel
42
+ testName='embed-tab-content'
43
+ className={css.tabPanelContent}
44
+ render={() => {
45
+ if (isIframe) {
46
+ if (isCampaign) {
47
+ return (
48
+ <span className={css.redHelperText}>
49
+ {t('tabs.helperTextWarning')}
50
+ </span>
51
+ );
52
+ } else if (isViewerIdSource) {
53
+ return (
54
+ <span className={css.redHelperText}>
55
+ {t('tabs.viewerIdTextWarning')}
56
+ </span>
57
+ );
58
+ } else if (isBcMapTracking) {
59
+ return (
60
+ <span className={css.redHelperText}>
61
+ {t('tabs.bcMapTrackingTextWarning')}
62
+ </span>
63
+ );
64
+ } else {
65
+ return <EmbedCode iframe={isIframe} {...rest} />;
66
+ }
67
+ } else {
68
+ return <EmbedCode iframe={isIframe} {...rest} />;
69
+ }
70
+ }}
71
+ />
72
+ </>
73
+ );
74
+ };
@@ -0,0 +1,39 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { Flex, ToolTip } from '@brightcove/studio-components';
3
+ import css from 'styles/EmbedCodeModal.sass';
4
+ import { truncateVideoTitle } from '../utils/util';
5
+
6
+ interface TitleWithTooltipProps {
7
+ name: string;
8
+ id: string;
9
+ }
10
+ export const TitleWithTooltip = ({ name, id }: TitleWithTooltipProps) => {
11
+ const [isOverflowing, setIsOverflowing] = useState(false);
12
+
13
+ const titleMemo = useMemo(
14
+ () => (name ? truncateVideoTitle(name) : ''),
15
+ [name],
16
+ );
17
+
18
+ useEffect(() => {
19
+ if (name) {
20
+ setIsOverflowing(titleMemo !== name);
21
+ }
22
+ }, [titleMemo, name]);
23
+
24
+ return (
25
+ <Flex flexDirection='column' className={css.mediaData}>
26
+ <ToolTip
27
+ placement='top'
28
+ portal
29
+ block
30
+ content={name}
31
+ active={isOverflowing}
32
+ testName='embed-video-tooltip'
33
+ >
34
+ <div className={css.mediaTitle}>{titleMemo}</div>
35
+ </ToolTip>
36
+ <div className={css.mediaId}>{id}</div>
37
+ </Flex>
38
+ );
39
+ };
@@ -0,0 +1,83 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, Loader } from '@brightcove/studio-components';
4
+ import css from 'styles/EmbedCodeModal.sass';
5
+ import { shortenUrl } from '../services/url-shortener';
6
+ import { getBrightcove } from 'js/utils/util';
7
+
8
+ interface VideoLinksProps {
9
+ previewUrl: string;
10
+ playerUrl: string;
11
+ }
12
+
13
+ export const VideoLinks = ({ previewUrl, playerUrl }: VideoLinksProps) => {
14
+ const { t } = useTranslation();
15
+ const [isGetUrlLoading, setIsGetUrlLoading] = useState<boolean>(false);
16
+
17
+ const copyPreviewURL = useCallback(
18
+ async (link: string) => {
19
+ setIsGetUrlLoading(true);
20
+ getUrlAndAddItToClipboard(link)
21
+ .then(() => {
22
+ getBrightcove().Toaster.success({
23
+ title: t('toasterTitle'),
24
+ message: t('toasterGetURLSuccess'),
25
+ });
26
+ })
27
+ .catch(() => {
28
+ getBrightcove().Toaster.error({
29
+ message: t('toasterGetURLError'),
30
+ });
31
+ })
32
+ .finally(() => setIsGetUrlLoading(false));
33
+ },
34
+ [t],
35
+ );
36
+ return (
37
+ <div>
38
+ <div className={css.getURLBtnContainer}>
39
+ <Button
40
+ look='tertiary'
41
+ text={t('getURL')}
42
+ testName='get-url-btn'
43
+ icon={isGetUrlLoading ? '' : 'link'}
44
+ iconRight
45
+ onClick={() => copyPreviewURL(playerUrl)}
46
+ />
47
+ {isGetUrlLoading && (
48
+ <Loader className={css.getURLBtnSpinner} size='inline' color='navy' />
49
+ )}
50
+ </div>
51
+ <Button
52
+ look='tertiary'
53
+ text={t('previewButton')}
54
+ testName='preview-player-btn'
55
+ icon='external_link'
56
+ iconRight
57
+ onClick={() => {
58
+ window.open(previewUrl, '_blank');
59
+ }}
60
+ />
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export const getUrlAndAddItToClipboard = async (url: string) => {
66
+ const escapedLongUrl = encodeURI(url);
67
+ // safari
68
+ try {
69
+ return navigator.clipboard.write([
70
+ new ClipboardItem({
71
+ // eslint-disable-next-line no-async-promise-executor
72
+ 'text/plain': new Promise(async (resolve) => {
73
+ const shortUrl = await shortenUrl({ longUrl: escapedLongUrl });
74
+ resolve(new Blob([shortUrl], { type: 'text/plain' }));
75
+ }),
76
+ }),
77
+ ]);
78
+ } catch {
79
+ // chrome and firefox
80
+ const shortUrl = await shortenUrl({ longUrl: escapedLongUrl });
81
+ return navigator.clipboard.writeText(shortUrl);
82
+ }
83
+ };