@playkit-js/moderation 2.1.1 → 2.2.0-canary.2-223f8a4

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 (69) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +5 -5
  3. package/README.md +105 -8
  4. package/dist/3758875b5327755db91c.svg +3 -0
  5. package/dist/4e88e84bb6cd6f386467.svg +9 -0
  6. package/{src/components/moderation/assets/down.svg → dist/699b282225ecacccffd9.svg} +2 -2
  7. package/dist/f4a8c73d84c247e719f8.svg +3 -0
  8. package/dist/playkit-moderation.js +1 -23
  9. package/dist/playkit-moderation.js.map +1 -1
  10. package/package.json +49 -54
  11. package/src/components/a11y-wrapper/a11y-wrapper.tsx +26 -0
  12. package/src/components/a11y-wrapper/index.ts +1 -0
  13. package/src/components/icons/index.ts +9 -0
  14. package/src/components/moderation/moderation.scss +25 -7
  15. package/src/components/moderation/moderation.tsx +64 -104
  16. package/src/components/plugin-button/plugin-button.scss +14 -14
  17. package/src/components/plugin-button/plugin-button.tsx +26 -3
  18. package/src/components/popover/index.ts +1 -0
  19. package/src/components/popover/popover-menu.scss +4 -0
  20. package/src/components/popover/popover-menu.tsx +57 -0
  21. package/src/components/popover/popover.scss +30 -0
  22. package/src/components/popover/popover.tsx +224 -0
  23. package/src/contrib-services/common-types.ts +2 -0
  24. package/src/contrib-services/contrib-services.ts +80 -0
  25. package/src/contrib-services/contrib-utils.ts +16 -0
  26. package/src/contrib-services/events-manager.ts +59 -0
  27. package/src/contrib-services/floating-item-data.tsx +31 -0
  28. package/src/contrib-services/floating-item.tsx +116 -0
  29. package/src/contrib-services/floating-manager.tsx +224 -0
  30. package/src/contrib-services/index.ts +2 -0
  31. package/src/contrib-services/injected-component/index.ts +1 -0
  32. package/src/contrib-services/injected-component/injected-component.scss +5 -0
  33. package/src/contrib-services/injected-component/injected-component.tsx +58 -0
  34. package/src/contrib-services/kaltura-player-utils.ts +18 -0
  35. package/src/contrib-services/managed-component/_managed-component.scss +8 -0
  36. package/src/contrib-services/managed-component/index.ts +1 -0
  37. package/src/contrib-services/managed-component/managed-component.tsx +71 -0
  38. package/src/contrib-services/object-utils.ts +157 -0
  39. package/src/contrib-services/player-contrib-registry.ts +34 -0
  40. package/src/contrib-services/player-utils.ts +37 -0
  41. package/src/contrib-services/preset-item-data.tsx +43 -0
  42. package/src/contrib-services/preset-item.tsx +113 -0
  43. package/src/contrib-services/preset-manager.tsx +153 -0
  44. package/src/contrib-services/presets-utils.ts +27 -0
  45. package/src/contrib-services/toast/_toast.scss +93 -0
  46. package/src/contrib-services/toast/assets/close.svg +9 -0
  47. package/src/contrib-services/toast/index.ts +1 -0
  48. package/src/contrib-services/toast/toast.tsx +67 -0
  49. package/src/contrib-services/toast-manager.tsx +121 -0
  50. package/src/contrib-services/toasts-container/_toasts-container.scss +21 -0
  51. package/src/contrib-services/toasts-container/index.ts +1 -0
  52. package/src/contrib-services/toasts-container/toasts-container.tsx +23 -0
  53. package/src/contrib-services/ui-player-adapter/index.tsx +1 -0
  54. package/src/contrib-services/ui-player-adapter/ui-player-adapter.tsx +27 -0
  55. package/src/contrib-services/uuid.ts +6 -0
  56. package/src/global.d.ts +6 -6
  57. package/src/index.ts +13 -1
  58. package/src/moderation-plugin.scss +12 -12
  59. package/src/moderation-plugin.tsx +123 -160
  60. package/src/providers/index.ts +2 -0
  61. package/src/providers/report-loader.ts +69 -0
  62. package/src/providers/response-types/index.ts +2 -0
  63. package/src/providers/response-types/kaltura-moderation-flag-response.ts +13 -0
  64. package/src/providers/response-types/kaltura-moderation-flag.ts +51 -0
  65. package/src/variables.scss +4 -1
  66. package/src/assets/.gitkeep +0 -0
  67. package/src/assets/close.svg +0 -10
  68. package/src/assets/flag.svg +0 -6
  69. package/src/components/.gitkeep +0 -0
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@playkit-js/moderation",
3
- "version": "2.1.1",
3
+ "version": "2.2.0-canary.2-223f8a4",
4
+ "main": "dist/playkit-moderation.js",
4
5
  "private": false,
5
6
  "bugs": {
6
7
  "url": "https://github.com/kaltura/playkit-js-moderation/issues"
@@ -13,27 +14,32 @@
13
14
  "publishConfig": {
14
15
  "access": "public"
15
16
  },
16
- "dependencies": {
17
- "@playkit-js-contrib/cli": "1.1.0",
18
- "@playkit-js-contrib/common": "^4.1.10",
19
- "@playkit-js-contrib/plugin": "^4.1.13",
20
- "@playkit-js-contrib/ui": "^4.1.13",
21
- "classnames": "2.2.6",
22
- "kaltura-typescript-client": "file:libs/kaltura-typescript-client-7.0.0-v20190324-101134.tgz",
23
- "null": "^2.0.0"
24
- },
25
17
  "devDependencies": {
26
- "@commitlint/cli": "8.3.5",
27
- "@commitlint/config-conventional": "8.3.4",
28
- "@types/classnames": "2.2.9",
29
- "@types/node": "13.7.6",
30
- "@typescript-eslint/eslint-plugin": "2.21.0",
31
- "@typescript-eslint/parser": "2.21.0",
32
- "husky": "3.1.0",
33
- "preact": "^10.4.1",
34
- "tslint": "5.20.1",
35
- "standard-version": "^6.0.1",
36
- "typescript": "3.8.2"
18
+ "@typescript-eslint/eslint-plugin": "^5.23.0",
19
+ "@typescript-eslint/parser": "^5.23.0",
20
+ "conventional-github-releaser": "3.1.3",
21
+ "cross-env": "^7.0.3",
22
+ "css-loader": "^6.7.1",
23
+ "documentation": "^13.2.5",
24
+ "husky": "^8.0.1",
25
+ "jest": "^28.1.0",
26
+ "kaltura-player-js": "https://github.com/kaltura/kaltura-player-js.git#master",
27
+ "lint-staged": "^12.4.1",
28
+ "node-sass": "^7.0.1",
29
+ "prettier": "^2.6.2",
30
+ "sass-loader": "^12.6.0",
31
+ "standard-version": "^9.3.2",
32
+ "style-loader": "1.3.0",
33
+ "ts-loader": "^9.3.0",
34
+ "tslint": "^6.1.3",
35
+ "typescript": "^4.6.4",
36
+ "uglifyjs-webpack-plugin": "^2.2.0",
37
+ "webpack": "^5.72.1",
38
+ "webpack-cli": "^4.9.2",
39
+ "webpack-dev-server": "^4.9.0"
40
+ },
41
+ "peerDependencies": {
42
+ "kaltura-player-js": "https://github.com/kaltura/kaltura-player-js.git#master"
37
43
  },
38
44
  "license": "AGPL-3.0",
39
45
  "files": [
@@ -44,38 +50,27 @@
44
50
  "src"
45
51
  ],
46
52
  "scripts": {
47
- "clean": "rm -rf dist",
48
- "reset": "npm run clean && rm -rf node_modules",
49
- "build": "kcontrib build",
50
- "build:dev": "kcontrib build --dev",
51
- "bump-canary": "standard-version --prerelease canary --skip.commit=true --skip.tag=true",
52
- "serve": "kcontrib serve",
53
- "serve:update-modes": "kcontrib serve --update-modes",
54
- "serve:update-player": "kcontrib serve --update-player",
55
- "analyze": "npm run build && npx source-map-explorer dist/playkit-moderation.js",
56
- "lint": "tsc --noEmit && eslint ./src --ext .ts,.tsx",
57
- "lint:fix": "tsc --noEmit && eslint ./src --ext .ts,.tsx --fix",
58
- "husky:pre-commit": "lint-staged",
59
- "husky:commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
60
- "deploy:prepare": "kcontrib deploy --prepare",
61
- "deploy:publish-to-npm": "kcontrib deploy --publish",
62
- "deploy:next:prepare": "kcontrib deploy --prepare --prerelease next",
63
- "contrib:latest": "kcontrib infra --type=latest",
64
- "infra:latest": "kcontrib infra --type=latest",
65
- "infra:next": "kcontrib infra --type=next",
66
- "infra:local": "kcontrib infra --type=local",
67
- "infra:add": "kcontrib infra --add"
53
+ "clean": "rm -rf ./dist",
54
+ "prebuild": "npm run clean",
55
+ "build": "webpack --mode production",
56
+ "dev": "webpack-dev-server --mode development",
57
+ "watch": "webpack --progress --color --watch --mode development",
58
+ "test": "jest",
59
+ "release": "standard-version",
60
+ "pushTaggedRelease": "git push --follow-tags --no-verify origin master",
61
+ "eslint": "eslint . --color",
62
+ "commit:dist": "git add --force --all dist && (git commit -m 'chore: update dist' || exit 0)",
63
+ "docs:generate": "documentation build flow-typed/** src/** -f md -o docs/configuration.md",
64
+ "docs:serve": "documentation serve flow-typed/** src/** --watch",
65
+ "precommit": "lint-staged",
66
+ "prettier:fix": "prettier --write ."
68
67
  },
69
- "browserslist": {
70
- "production": [
71
- ">0.2%",
72
- "not dead",
73
- "not op_mini all"
74
- ],
75
- "development": [
76
- "last 1 chrome version",
77
- "last 1 firefox version",
78
- "last 1 safari version"
79
- ]
80
- }
68
+ "keywords": [
69
+ "moderation",
70
+ "kaltura",
71
+ "player",
72
+ "playkit-js",
73
+ "playkit-js-moderation",
74
+ "html5 player"
75
+ ]
81
76
  }
@@ -0,0 +1,26 @@
1
+ import {cloneElement, VNode} from 'preact';
2
+
3
+ const {ENTER, SPACE} = KalturaPlayer.ui.utils.KeyMap;
4
+
5
+ export type OnClickEvent = KeyboardEvent | MouseEvent;
6
+ export type OnClick = (e: OnClickEvent, byKeyboard?: boolean) => void;
7
+
8
+ interface A11yWrapperProps {
9
+ children: VNode;
10
+ onClick: OnClick;
11
+ }
12
+
13
+ export const A11yWrapper = ({children, onClick}: A11yWrapperProps) => {
14
+ return cloneElement(children, {
15
+ onKeyDown: (e: KeyboardEvent) => {
16
+ if ([SPACE, ENTER].includes(e.keyCode)) {
17
+ e.preventDefault();
18
+ onClick(e, true);
19
+ }
20
+ },
21
+ onClick: (e: MouseEvent) => {
22
+ e.stopPropagation();
23
+ onClick(e);
24
+ }
25
+ });
26
+ };
@@ -0,0 +1 @@
1
+ export * from './a11y-wrapper';
@@ -0,0 +1,9 @@
1
+ export namespace icons {
2
+ export const PLUGIN_ICON =
3
+ 'M8.378 7.084l5.175 19.314c.134.497-.126 1.005-.594 1.19l-.112.037c-.533.143-1.08-.165-1.225-.71L6.447 7.603c-.134-.497.126-1.005.594-1.19l.112-.037c.533-.143 1.08.165 1.225.71zM21.882 7c1.878 0 2.79 1.622 1.84 3.239l-1.386 2.36 2.94 3.246C26.6 17.31 25.842 19 23.868 19h-10.21c-.452 0-.848-.304-.966-.741l-2.68-10c-.17-.635.31-1.259.967-1.259h10.902zm.211 1.994l-.21.006h-9.6l2.144 8h9.196l-3.263-3.604c-.293-.324-.342-.8-.12-1.178l1.757-2.992c.114-.194.168-.23.096-.232z';
4
+ export const CLOSE_ICON =
5
+ 'M17.9113162,16 L24.6072325,9.30408374 C25.1313645,8.77995172 25.1287183,7.92687249 24.6009229,7.3990771 C24.0694478,6.86760201 23.220227,6.86845682 22.6959163,7.39276754 L16,14.0886838 L9.30408374,7.39276754 C8.77995172,6.86863552 7.92687249,6.8712817 7.3990771,7.3990771 C6.86760201,7.93055219 6.86845682,8.77977302 7.39276754,9.30408374 L14.0886838,16 L7.39276754,22.6959163 C6.86863552,23.2200483 6.8712817,24.0731275 7.3990771,24.6009229 C7.93055219,25.132398 8.77977302,25.1315432 9.30408374,24.6072325 L16,17.9113162 L22.6959163,24.6072325 C23.2200483,25.1313645 24.0731275,25.1287183 24.6009229,24.6009229 C25.132398,24.0694478 25.1315432,23.220227 24.6072325,22.6959163 L17.9113162,16 Z';
6
+ export const BigSize = 32;
7
+ export const MediumSize = 24;
8
+ export const SmallSize = 16;
9
+ }
@@ -13,19 +13,22 @@
13
13
  background-color: $root-background;
14
14
  -webkit-backdrop-filter: blur(16px);
15
15
  backdrop-filter: blur(16px);
16
+ z-index: 1;
16
17
  .close-button {
17
18
  position: absolute;
18
19
  top: 32px;
19
20
  right: 32px;
21
+ display: flex;
20
22
  width: 32px;
21
23
  height: 32px;
22
- min-width: 32px;
24
+ padding: 0;
25
+ background: transparent;
26
+ border: none;
23
27
  cursor: pointer;
24
- background-image: url('../../assets/close.svg');
25
28
  &:focus {
26
29
  outline: 1px solid $focus-color;
27
30
  }
28
- }
31
+ }
29
32
  .main-wrapper {
30
33
  height: 100%;
31
34
  width: 400px;
@@ -58,7 +61,7 @@
58
61
  background-color: $semigray-color;
59
62
  }
60
63
  &:focus {
61
- outline: 1px solid $focus-color;
64
+ outline: 1px solid $focus-color;
62
65
  }
63
66
  }
64
67
  .select-wrapper {
@@ -105,15 +108,18 @@
105
108
  &.active {
106
109
  background-color: $black-color;
107
110
  }
108
- &:-ms-input-placeholderr { /* Internet Explorer 10-11 */
111
+ &:-ms-input-placeholderr {
112
+ /* Internet Explorer 10-11 */
109
113
  color: $gray-color !important;
110
114
  font-size: 15px;
111
115
  opacity: 1;
112
116
  }
113
- &::-ms-input-placeholder { /* Microsoft Edge */
117
+ &::-ms-input-placeholder {
118
+ /* Microsoft Edge */
114
119
  color: $gray-color;
115
120
  }
116
- &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
121
+ &::placeholder {
122
+ /* Chrome, Firefox, Opera, Safari 10.1+ */
117
123
  color: $gray-color;
118
124
  opacity: 1; /* Firefox */
119
125
  }
@@ -166,6 +172,12 @@
166
172
  }
167
173
  }
168
174
  }
175
+
176
+ // TODO: remove once player fix the font
177
+ * {
178
+ font-family: sans-serif;
179
+ font-style: normal;
180
+ }
169
181
  }
170
182
 
171
183
  :global {
@@ -193,3 +205,9 @@
193
205
  }
194
206
  }
195
207
  }
208
+
209
+ // TODO: remove once core team fix alignment of plugin icons
210
+ :global(.playkit-player .playkit-top-bar .playkit-right-controls) {
211
+ display: flex;
212
+ flex-direction: row;
213
+ }
@@ -1,16 +1,12 @@
1
1
  import {h, Component, Fragment} from 'preact';
2
- import {getContribLogger, ObjectUtils} from '@playkit-js-contrib/common';
3
- import {
4
- KeyboardKeys,
5
- Popover,
6
- PopoverHorizontalPositions,
7
- PopoverVerticalPositions,
8
- } from '@playkit-js-contrib/ui';
9
- import {KalturaModerationFlagType} from 'kaltura-typescript-client/api/types';
2
+ import {KeyboardKeys, Popover, PopoverHorizontalPositions, PopoverVerticalPositions} from '../popover';
10
3
  import {PopoverMenu, PopoverMenuItem} from '../popover-menu';
4
+ import {OnClick, A11yWrapper} from '../a11y-wrapper';
5
+ import {icons} from '../icons';
11
6
  import * as styles from './moderation.scss';
12
- const {get} = ObjectUtils;
13
- const {Tooltip} = KalturaPlayer.ui.components;
7
+
8
+ const {Tooltip, Icon} = KalturaPlayer.ui.components;
9
+ const {withText, Text} = KalturaPlayer.ui.preacti18n;
14
10
 
15
11
  export interface ModerateOption {
16
12
  id: number;
@@ -18,13 +14,18 @@ export interface ModerateOption {
18
14
  }
19
15
 
20
16
  interface ModerationProps {
21
- onClick: () => void;
22
- onSubmit: (contentType: KalturaModerationFlagType, content: string, callBack: () => void) => void;
17
+ onClick: OnClick;
18
+ onSubmit: (contentType: number, content: string, callBack: () => void) => void;
23
19
  reportLength: number;
24
20
  moderateOptions: ModerateOption[];
25
21
  subtitle: string;
26
22
  tooltipMessage: string;
27
23
  closeButtonSelected: boolean;
24
+ sendReportLabel?: string;
25
+ closeLabel?: string;
26
+ reportPlaceholder?: string;
27
+ defaultContentType?: string;
28
+ reportTitle?: string;
28
29
  }
29
30
 
30
31
  interface ModerationState {
@@ -33,28 +34,27 @@ interface ModerationState {
33
34
  isTextareaActive: boolean;
34
35
  }
35
36
 
36
- const logger = getContribLogger({
37
- class: 'Info',
38
- module: 'info-plugin',
39
- });
40
-
41
- const DEFAULT_CONTENT_TYPE = 'Choose a reason for reporting this content';
42
-
43
37
  const initialState: ModerationState = {
44
38
  reportContent: '',
45
39
  reportContentType: -1,
46
- isTextareaActive: false,
40
+ isTextareaActive: false
41
+ };
42
+
43
+ const translates = {
44
+ sendReportLabel: <Text id="moderation.send_report">Report</Text>,
45
+ closeLabel: <Text id="moderation.close">Close</Text>,
46
+ reportPlaceholder: <Text id="moderation.report_placeholder">Describe what you saw...</Text>,
47
+ defaultContentType: <Text id="moderation.default_content_type">Choose a reason for reporting this content</Text>,
48
+ reportTitle: <Text id="moderation.report_title">What’s wrong with this content?</Text>
47
49
  };
48
50
 
51
+ @withText(translates)
49
52
  export class Moderation extends Component<ModerationProps, ModerationState> {
50
- _closeButtonNode: null | HTMLDivElement = null;
53
+ _closeButtonNode: null | HTMLButtonElement = null;
51
54
 
52
- state: ModerationState = { ...initialState };
55
+ state: ModerationState = {...initialState};
53
56
 
54
57
  componentDidMount(): void {
55
- logger.trace('Moderation plugin mount', {
56
- method: 'componentDidMount',
57
- });
58
58
  if (this._closeButtonNode && this.props.closeButtonSelected) {
59
59
  this._closeButtonNode.focus();
60
60
  }
@@ -62,38 +62,32 @@ export class Moderation extends Component<ModerationProps, ModerationState> {
62
62
 
63
63
  private _onContentTypeChange = (id: number) => {
64
64
  this.setState({
65
- reportContentType: id,
65
+ reportContentType: id
66
66
  });
67
67
  };
68
68
 
69
69
  private _onContentChange = (event: any) => {
70
70
  this.setState({
71
- reportContent: event.target.value,
71
+ reportContent: event.target.value
72
72
  });
73
73
  };
74
74
 
75
75
  private _handleFocus = () => {
76
76
  this.setState({
77
- isTextareaActive: true,
77
+ isTextareaActive: true
78
78
  });
79
79
  };
80
80
 
81
81
  private _handleBlur = () => {
82
82
  this.setState((state: ModerationState) => ({
83
- isTextareaActive: state.reportContent.length > 0,
83
+ isTextareaActive: state.reportContent.length > 0
84
84
  }));
85
85
  };
86
86
 
87
87
  private _handleSubmit = (event: any) => {
88
88
  event.preventDefault();
89
89
  const {reportContent, reportContentType} = this.state;
90
- logger.trace('Moderation plugin submit click', {
91
- method: 'handleSubmit',
92
- });
93
90
  if (reportContentType === -1) {
94
- logger.trace('Moderation User did not select reason', {
95
- method: 'handleSubmit',
96
- });
97
91
  return;
98
92
  }
99
93
  this.props.onSubmit(reportContentType, reportContent, () => {
@@ -107,7 +101,7 @@ export class Moderation extends Component<ModerationProps, ModerationState> {
107
101
  e.stopPropagation();
108
102
  }
109
103
  switch (e.keyCode) {
110
- case 13: // Enter pressed
104
+ case KeyboardKeys.Enter: // Enter pressed
111
105
  callBack();
112
106
  break;
113
107
  }
@@ -127,64 +121,43 @@ export class Moderation extends Component<ModerationProps, ModerationState> {
127
121
  private _getPopoverMenuOptions = () => {
128
122
  return this.props.moderateOptions.map(({label, id}: ModerateOption) => ({
129
123
  label: label || '',
130
- onMenuChosen: () => this._onContentTypeChange(id || -1),
124
+ onMenuChosen: () => this._onContentTypeChange(id || -1)
131
125
  }));
132
126
  };
133
127
 
134
128
  private _popoverContent = () => {
135
- return (
136
- <PopoverMenu
137
- itemRenderer={this._popoverMenuItemRenderer}
138
- options={this._getPopoverMenuOptions()}
139
- />
140
- );
141
- };
142
-
143
- private _getContentType = () => {
144
- return (
145
- this.props.moderateOptions.find(
146
- (moderateOption: ModerateOption) =>
147
- moderateOption.id === this.state.reportContentType
148
- ) || {}
149
- );
129
+ return <PopoverMenu itemRenderer={this._popoverMenuItemRenderer} options={this._getPopoverMenuOptions()} />;
150
130
  };
151
131
 
152
- private _handleClose = (event: MouseEvent | KeyboardEvent) => {
153
- if (
154
- event.type === 'keypress' &&
155
- get(event, 'keyCode', null) !== KeyboardKeys.Enter
156
- ) {
157
- return;
158
- }
159
- this.props.onClick();
132
+ private _getContentType = (): any => {
133
+ return this.props.moderateOptions.find((moderateOption: ModerateOption) => moderateOption.id === this.state.reportContentType) || {};
160
134
  };
161
135
 
162
136
  render(props: ModerationProps) {
163
- const {reportLength, subtitle, tooltipMessage} = props;
137
+ const {reportLength, subtitle, tooltipMessage, onClick, closeLabel} = props;
164
138
  const {reportContent, reportContentType, isTextareaActive} = this.state;
165
139
  return (
166
140
  <div className={[styles.root, 'kaltura-moderation__root'].join(' ')}>
167
- <div
168
- className={[
169
- styles.closeButton,
170
- 'kaltura-moderation__close-button',
171
- ].join(' ')}
172
- role="button"
173
- tabIndex={1}
174
- onClick={this._handleClose}
175
- onKeyPress={this._handleClose}
176
- ref={(node: HTMLDivElement | null) => {
177
- this._closeButtonNode = node;
178
- }}
179
- />
141
+ <A11yWrapper onClick={onClick}>
142
+ <button
143
+ aria-label={closeLabel}
144
+ className={[styles.closeButton, 'kaltura-moderation__close-button'].join(' ')}
145
+ tabIndex={1}
146
+ ref={node => {
147
+ this._closeButtonNode = node;
148
+ }}>
149
+ <Icon
150
+ id="moderation-plugin-close-button"
151
+ height={icons.BigSize}
152
+ width={icons.BigSize}
153
+ viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`}
154
+ path={icons.CLOSE_ICON}
155
+ />
156
+ </button>
157
+ </A11yWrapper>
180
158
  <div className={styles.mainWrapper}>
181
- <div
182
- className={[styles.title, 'kaltura-moderation__title'].join(' ')}>
183
- What’s wrong with this content?
184
- </div>
185
- {subtitle ? (
186
- <div className={[styles.subtitle].join(' ')}>{subtitle}</div>
187
- ) : null}
159
+ <div className={[styles.title, 'kaltura-moderation__title'].join(' ')}>{this.props.reportTitle}</div>
160
+ {subtitle ? <div className={[styles.subtitle].join(' ')}>{subtitle}</div> : null}
188
161
  <Popover
189
162
  className={styles.reportPopover}
190
163
  verticalPosition={PopoverVerticalPositions.Bottom}
@@ -192,43 +165,30 @@ export class Moderation extends Component<ModerationProps, ModerationState> {
192
165
  content={this._popoverContent()}>
193
166
  <Fragment>
194
167
  <button className={styles.selectWrapper} tabIndex={1}>
195
- <div className={styles.select}>
196
- {reportContentType > -1
197
- ? get(this._getContentType(), 'label', '')
198
- : DEFAULT_CONTENT_TYPE}
199
- </div>
168
+ <div className={styles.select}>{reportContentType > -1 ? this._getContentType()?.label || '' : this.props.defaultContentType}</div>
200
169
  <div className={styles.downArrow} />
201
170
  </button>
202
171
  </Fragment>
203
172
  </Popover>
204
- <form onSubmit={this._handleSubmit}>
173
+ <form>
205
174
  <textarea
206
- className={[
207
- styles.textarea,
208
- isTextareaActive ? styles.active : '',
209
- ].join(' ')}
175
+ className={[styles.textarea, isTextareaActive ? styles.active : ''].join(' ')}
210
176
  onInput={this._onContentChange}
211
177
  onFocus={this._handleFocus}
212
178
  onBlur={this._handleBlur}
213
179
  tabIndex={1}
214
- placeholder="Describe what you saw..."
180
+ placeholder={this.props.reportPlaceholder}
215
181
  value={reportContent}
216
182
  maxLength={reportLength}
217
183
  />
218
184
  <div className={styles.submitWrapper}>
219
- <div className={styles.characterCounter}>
220
- {`${reportContent.length}/${reportLength}`}
221
- </div>
185
+ <div className={styles.characterCounter}>{`${reportContent.length}/${reportLength}`}</div>
222
186
  <Tooltip label={tooltipMessage} classNames={styles.tooltip}>
223
- <button
224
- className={[
225
- styles.submitButton,
226
- reportContentType === -1 ? styles.disabled : '',
227
- ].join(' ')}
228
- tabIndex={1}
229
- type="submit">
230
- Report
231
- </button>
187
+ <A11yWrapper onClick={this._handleSubmit}>
188
+ <button className={[styles.submitButton, reportContentType === -1 ? styles.disabled : ''].join(' ')} tabIndex={1}>
189
+ {this.props.sendReportLabel}
190
+ </button>
191
+ </A11yWrapper>
232
192
  </Tooltip>
233
193
  </div>
234
194
  </form>
@@ -1,14 +1,14 @@
1
- .moderation-icon {
2
- background-image: url("../../assets/flag.svg");
3
- width: 32px;
4
- height: 32px;
5
- opacity: 0.8;
6
- cursor: pointer;
7
- background-color: inherit;
8
- border: none;
9
- padding: 0;
10
- &:hover,
11
- &:focus {
12
- opacity: 1;
13
- }
14
- }
1
+ .pluginButton {
2
+ display: flex;
3
+ width: 36px;
4
+ height: 36px;
5
+ padding: 0;
6
+ background: transparent;
7
+ border: none;
8
+ border-radius: 4px;
9
+ cursor: pointer;
10
+ }
11
+
12
+ :global(.playkit-player .playkit-top-bar .playkit-right-controls) {
13
+ display: flex;
14
+ }
@@ -1,6 +1,29 @@
1
1
  import {h} from 'preact';
2
2
  import * as styles from './plugin-button.scss';
3
+ import {icons} from '../icons';
4
+ import {A11yWrapper, OnClick} from '../a11y-wrapper';
3
5
 
4
- export const PluginButton = () => (
5
- <button className={styles.moderationIcon} tabIndex={1} />
6
- );
6
+ const {Tooltip, Icon} = KalturaPlayer.ui.components;
7
+
8
+ interface PluginButtonProps {
9
+ onClick: OnClick;
10
+ label?: string;
11
+ }
12
+
13
+ export const PluginButton = ({onClick, label}: PluginButtonProps) => {
14
+ return (
15
+ <Tooltip label={label} type="bottom">
16
+ <A11yWrapper onClick={onClick}>
17
+ <button aria-label={label} className={styles.pluginButton}>
18
+ <Icon
19
+ id="moderation-plugin-button"
20
+ height={icons.BigSize}
21
+ width={icons.BigSize}
22
+ viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`}
23
+ path={icons.PLUGIN_ICON}
24
+ />
25
+ </button>
26
+ </A11yWrapper>
27
+ </Tooltip>
28
+ );
29
+ };
@@ -0,0 +1 @@
1
+ export * from './popover';
@@ -0,0 +1,4 @@
1
+ .popover-menu {
2
+ padding-top: 6px;
3
+ padding-bottom: 6px;
4
+ }
@@ -0,0 +1,57 @@
1
+ import {h, Component, ComponentChild} from 'preact';
2
+ import * as styles from './popover-menu.scss';
3
+
4
+ export interface PopoverMenuItem {
5
+ label?: string;
6
+ onMenuChosen?: Function;
7
+ customRenderer?: (el: PopoverMenuItem) => ComponentChild;
8
+ }
9
+
10
+ interface PopoverMenuProps {
11
+ options: Array<PopoverMenuItem>;
12
+ itemRenderer?: (el: PopoverMenuItem) => ComponentChild;
13
+ }
14
+
15
+ /**
16
+ * Popover menu renders list of options.
17
+ * options example:
18
+ * [
19
+ * {label: 'option_1', onMenuChosen: () => console.log('selected first')},
20
+ * {label: 'option_2', onMenuChosen: () => console.log('selected second')}
21
+ * ]
22
+ * In case when 'itemRenderer' properdy hasn't provided - PopoverMenu renders
23
+ * div with class "popover-menu-item" that contain label for the current option.
24
+ * Default render of options can be changed by providing 'itemRenderer' - it should be
25
+ * function that takes current option and returns valid 'preact' node.
26
+ * If some option need to be rendered with a different method - specific render
27
+ * method can be provided with 'customRenderer' property for the current option.
28
+ * option example with specific render method:
29
+ * { label: 'specific render', onMenuChosen: () => {}, customRenderer: el => (<span>{el.label}</span>)}
30
+ */
31
+
32
+ export class PopoverMenu extends Component<PopoverMenuProps> {
33
+ render(props: any) {
34
+ return (
35
+ <div className={styles.popoverMenu}>
36
+ {props.options.map((el: PopoverMenuItem) => {
37
+ if (el.customRenderer) {
38
+ return el.customRenderer(el);
39
+ }
40
+ if (props.itemRenderer) {
41
+ return props.itemRenderer(el);
42
+ }
43
+ return (
44
+ <div
45
+ className="popover-menu-item"
46
+ onClick={() => {
47
+ // @ts-ignore
48
+ el.onMenuChosen(el)
49
+ }}>
50
+ {el.label}
51
+ </div>
52
+ );
53
+ })}
54
+ </div>
55
+ );
56
+ }
57
+ }