@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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +5 -5
- package/README.md +105 -8
- package/dist/3758875b5327755db91c.svg +3 -0
- package/dist/4e88e84bb6cd6f386467.svg +9 -0
- package/{src/components/moderation/assets/down.svg → dist/699b282225ecacccffd9.svg} +2 -2
- package/dist/f4a8c73d84c247e719f8.svg +3 -0
- package/dist/playkit-moderation.js +1 -23
- package/dist/playkit-moderation.js.map +1 -1
- package/package.json +49 -54
- package/src/components/a11y-wrapper/a11y-wrapper.tsx +26 -0
- package/src/components/a11y-wrapper/index.ts +1 -0
- package/src/components/icons/index.ts +9 -0
- package/src/components/moderation/moderation.scss +25 -7
- package/src/components/moderation/moderation.tsx +64 -104
- package/src/components/plugin-button/plugin-button.scss +14 -14
- package/src/components/plugin-button/plugin-button.tsx +26 -3
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover/popover-menu.scss +4 -0
- package/src/components/popover/popover-menu.tsx +57 -0
- package/src/components/popover/popover.scss +30 -0
- package/src/components/popover/popover.tsx +224 -0
- package/src/contrib-services/common-types.ts +2 -0
- package/src/contrib-services/contrib-services.ts +80 -0
- package/src/contrib-services/contrib-utils.ts +16 -0
- package/src/contrib-services/events-manager.ts +59 -0
- package/src/contrib-services/floating-item-data.tsx +31 -0
- package/src/contrib-services/floating-item.tsx +116 -0
- package/src/contrib-services/floating-manager.tsx +224 -0
- package/src/contrib-services/index.ts +2 -0
- package/src/contrib-services/injected-component/index.ts +1 -0
- package/src/contrib-services/injected-component/injected-component.scss +5 -0
- package/src/contrib-services/injected-component/injected-component.tsx +58 -0
- package/src/contrib-services/kaltura-player-utils.ts +18 -0
- package/src/contrib-services/managed-component/_managed-component.scss +8 -0
- package/src/contrib-services/managed-component/index.ts +1 -0
- package/src/contrib-services/managed-component/managed-component.tsx +71 -0
- package/src/contrib-services/object-utils.ts +157 -0
- package/src/contrib-services/player-contrib-registry.ts +34 -0
- package/src/contrib-services/player-utils.ts +37 -0
- package/src/contrib-services/preset-item-data.tsx +43 -0
- package/src/contrib-services/preset-item.tsx +113 -0
- package/src/contrib-services/preset-manager.tsx +153 -0
- package/src/contrib-services/presets-utils.ts +27 -0
- package/src/contrib-services/toast/_toast.scss +93 -0
- package/src/contrib-services/toast/assets/close.svg +9 -0
- package/src/contrib-services/toast/index.ts +1 -0
- package/src/contrib-services/toast/toast.tsx +67 -0
- package/src/contrib-services/toast-manager.tsx +121 -0
- package/src/contrib-services/toasts-container/_toasts-container.scss +21 -0
- package/src/contrib-services/toasts-container/index.ts +1 -0
- package/src/contrib-services/toasts-container/toasts-container.tsx +23 -0
- package/src/contrib-services/ui-player-adapter/index.tsx +1 -0
- package/src/contrib-services/ui-player-adapter/ui-player-adapter.tsx +27 -0
- package/src/contrib-services/uuid.ts +6 -0
- package/src/global.d.ts +6 -6
- package/src/index.ts +13 -1
- package/src/moderation-plugin.scss +12 -12
- package/src/moderation-plugin.tsx +123 -160
- package/src/providers/index.ts +2 -0
- package/src/providers/report-loader.ts +69 -0
- package/src/providers/response-types/index.ts +2 -0
- package/src/providers/response-types/kaltura-moderation-flag-response.ts +13 -0
- package/src/providers/response-types/kaltura-moderation-flag.ts +51 -0
- package/src/variables.scss +4 -1
- package/src/assets/.gitkeep +0 -0
- package/src/assets/close.svg +0 -10
- package/src/assets/flag.svg +0 -6
- 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.
|
|
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
|
-
"@
|
|
27
|
-
"@
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"husky": "
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
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
|
-
"
|
|
49
|
-
"build": "
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
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
|
-
"
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
117
|
+
&::-ms-input-placeholder {
|
|
118
|
+
/* Microsoft Edge */
|
|
114
119
|
color: $gray-color;
|
|
115
120
|
}
|
|
116
|
-
&::placeholder {
|
|
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 {
|
|
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
|
-
|
|
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:
|
|
22
|
-
onSubmit: (contentType:
|
|
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 |
|
|
53
|
+
_closeButtonNode: null | HTMLButtonElement = null;
|
|
51
54
|
|
|
52
|
-
state: ModerationState = {
|
|
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
|
|
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
|
|
153
|
-
|
|
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
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'kaltura-moderation__close-button'
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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
|
|
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=
|
|
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
|
-
<
|
|
224
|
-
className={[
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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,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
|
+
}
|