@playkit-js/moderation 3.0.0 → 3.1.0-canary.10-08b2d40
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 +15 -0
- package/README.md +60 -7
- package/dist/playkit-moderation.js +1 -1
- package/dist/playkit-moderation.js.map +1 -1
- package/package.json +9 -2
- package/src/components/moderation/moderation.scss +31 -83
- package/src/components/moderation/moderation.tsx +87 -97
- package/src/components/plugin-button/plugin-button.tsx +2 -2
- package/src/components/popover/popover.scss +27 -0
- package/src/components/popover/popover.tsx +75 -157
- package/src/moderation-plugin.tsx +23 -13
- package/src/components/plugin-button/plugin-button.scss +0 -14
- package/src/components/popover/popover-menu.scss +0 -4
- package/src/components/popover/popover-menu.tsx +0 -57
- package/src/components/popover-menu/index.ts +0 -1
- package/src/components/popover-menu/popover-menu.scss +0 -4
- package/src/components/popover-menu/popover-menu.tsx +0 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playkit-js/moderation",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-canary.10-08b2d40",
|
|
4
4
|
"main": "dist/playkit-moderation.js",
|
|
5
5
|
"private": false,
|
|
6
6
|
"bugs": {
|
|
@@ -74,6 +74,13 @@
|
|
|
74
74
|
"html5 player"
|
|
75
75
|
],
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@playkit-js/common": "^1.0.
|
|
77
|
+
"@playkit-js/common": "^1.0.14",
|
|
78
|
+
"@playkit-js/ui-managers": "^1.3.0"
|
|
79
|
+
},
|
|
80
|
+
"kaltura": {
|
|
81
|
+
"name": "playkit-js-moderation",
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"playkit-ui-managers": "1.3.0"
|
|
84
|
+
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
@import '../../variables.scss';
|
|
2
2
|
|
|
3
3
|
.root {
|
|
4
|
-
position:
|
|
5
|
-
top: 0;
|
|
6
|
-
left: 0;
|
|
7
|
-
width: 100%;
|
|
4
|
+
position: relative;
|
|
8
5
|
height: 100%;
|
|
6
|
+
width: 100%;
|
|
9
7
|
display: flex;
|
|
10
|
-
|
|
8
|
+
flex-direction: column;
|
|
11
9
|
align-items: center;
|
|
12
|
-
|
|
10
|
+
justify-content: center;
|
|
13
11
|
color: $white-color;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
width: 32px;
|
|
24
|
-
height: 32px;
|
|
25
|
-
padding: 0;
|
|
26
|
-
background: transparent;
|
|
27
|
-
border: none;
|
|
28
|
-
cursor: pointer;
|
|
29
|
-
&:focus {
|
|
30
|
-
outline: 1px solid $focus-color;
|
|
12
|
+
|
|
13
|
+
&.extrasmall,
|
|
14
|
+
&.small {
|
|
15
|
+
.main-wrapper .title {
|
|
16
|
+
margin-bottom: 12px;
|
|
17
|
+
font-size: 20px;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
text-overflow: ellipsis;
|
|
20
|
+
white-space: nowrap;
|
|
31
21
|
}
|
|
32
22
|
}
|
|
23
|
+
|
|
24
|
+
div {
|
|
25
|
+
margin: 0px;
|
|
26
|
+
}
|
|
27
|
+
* {
|
|
28
|
+
font-family: Lato, sans-serif;
|
|
29
|
+
font-style: normal;
|
|
30
|
+
}
|
|
31
|
+
|
|
33
32
|
.main-wrapper {
|
|
34
|
-
width:
|
|
33
|
+
width: 100%;
|
|
34
|
+
max-width: 461px;
|
|
35
35
|
.title {
|
|
36
36
|
margin-bottom: 8px;
|
|
37
37
|
font-size: 28px;
|
|
@@ -45,26 +45,6 @@
|
|
|
45
45
|
font-size: 15px;
|
|
46
46
|
line-height: 1.6;
|
|
47
47
|
}
|
|
48
|
-
.report-popover {
|
|
49
|
-
width: 100%;
|
|
50
|
-
max-width: 280px;
|
|
51
|
-
}
|
|
52
|
-
.popover-menu-item {
|
|
53
|
-
display: flex;
|
|
54
|
-
align-items: center;
|
|
55
|
-
width: 100%;
|
|
56
|
-
height: 36px;
|
|
57
|
-
padding: 0 16px;
|
|
58
|
-
font-size: 15px;
|
|
59
|
-
color: $white-color;
|
|
60
|
-
&:hover {
|
|
61
|
-
cursor: pointer;
|
|
62
|
-
background-color: $semigray-color;
|
|
63
|
-
}
|
|
64
|
-
&:focus {
|
|
65
|
-
outline: 1px solid $focus-color;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
48
|
.select-wrapper {
|
|
69
49
|
display: flex;
|
|
70
50
|
align-items: center;
|
|
@@ -84,6 +64,9 @@
|
|
|
84
64
|
font-size: 15px;
|
|
85
65
|
line-height: 1.6;
|
|
86
66
|
font-weight: bold;
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
text-overflow: ellipsis;
|
|
69
|
+
white-space: nowrap;
|
|
87
70
|
}
|
|
88
71
|
.down-arrow {
|
|
89
72
|
width: 14px;
|
|
@@ -156,14 +139,14 @@
|
|
|
156
139
|
text-align: center;
|
|
157
140
|
font-size: 14px;
|
|
158
141
|
font-weight: bold;
|
|
159
|
-
background-color: #
|
|
142
|
+
background-color: #006efa;
|
|
160
143
|
padding-left: 12px;
|
|
161
144
|
padding-right: 12px;
|
|
162
145
|
border: none;
|
|
163
146
|
outline: none !important; // overwrites player styles
|
|
164
147
|
cursor: pointer;
|
|
165
148
|
&.disabled {
|
|
166
|
-
background-color: rgba(0,0,0,0);
|
|
149
|
+
background-color: rgba(0, 0, 0, 0);
|
|
167
150
|
padding-left: 11px;
|
|
168
151
|
padding-right: 11px;
|
|
169
152
|
color: #888888;
|
|
@@ -173,44 +156,9 @@
|
|
|
173
156
|
box-shadow: 0px 0px 0px 1px $focus-color;
|
|
174
157
|
}
|
|
175
158
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
// TODO: remove once player fix the font
|
|
180
|
-
* {
|
|
181
|
-
font-family: sans-serif;
|
|
182
|
-
font-style: normal;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
:global {
|
|
187
|
-
.kaltura-moderation__root .playkit-tooltip {
|
|
188
|
-
width: auto;
|
|
189
|
-
}
|
|
190
|
-
.playkit-player.playkit-size-sm,
|
|
191
|
-
.playkit-player.playkit-size-xs {
|
|
192
|
-
.kaltura-moderation__close-button {
|
|
193
|
-
top: 10px;
|
|
194
|
-
right: 16px;
|
|
195
|
-
}
|
|
196
|
-
.kaltura-moderation__root {
|
|
197
|
-
padding: 14px 16px;
|
|
198
|
-
.kaltura-moderation__title {
|
|
199
|
-
margin-bottom: 16px;
|
|
200
|
-
font-size: 20px;
|
|
201
|
-
text-align: left;
|
|
159
|
+
:global(.playkit-tooltip) {
|
|
160
|
+
width: auto;
|
|
202
161
|
}
|
|
203
162
|
}
|
|
204
163
|
}
|
|
205
|
-
.playkit-player.playkit-size-ty {
|
|
206
|
-
.kaltura-moderation__root {
|
|
207
|
-
display: none;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// TODO: remove once core team fix alignment of plugin icons
|
|
213
|
-
:global(.playkit-player .playkit-top-bar .playkit-right-controls) {
|
|
214
|
-
display: flex;
|
|
215
|
-
flex-direction: row;
|
|
216
164
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {h, Component
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {OnClick, A11yWrapper} from '@playkit-js/common';
|
|
5
|
-
import {icons} from '../icons';
|
|
1
|
+
import {h, Component} from 'preact';
|
|
2
|
+
import {Popover} from '../popover';
|
|
3
|
+
import {OnClick, A11yWrapper, OverlayPortal} from '@playkit-js/common';
|
|
6
4
|
import * as styles from './moderation.scss';
|
|
7
5
|
import {DownIcon} from './down-icon';
|
|
8
6
|
|
|
9
|
-
const {Tooltip,
|
|
7
|
+
const {Tooltip, Overlay, PLAYER_SIZE} = KalturaPlayer.ui.components;
|
|
10
8
|
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
9
|
+
const {
|
|
10
|
+
redux: {connect}
|
|
11
|
+
} = KalturaPlayer.ui;
|
|
11
12
|
|
|
12
13
|
export interface ModerateOption {
|
|
13
14
|
id: number;
|
|
@@ -29,6 +30,12 @@ interface ModerationProps {
|
|
|
29
30
|
reportTitle?: string;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
interface ConnectProps {
|
|
34
|
+
playerSize?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type MergedProps = ModerationProps & ConnectProps;
|
|
38
|
+
|
|
32
39
|
interface ModerationState {
|
|
33
40
|
reportContentType: number;
|
|
34
41
|
reportContent: string;
|
|
@@ -49,15 +56,21 @@ const translates = {
|
|
|
49
56
|
reportTitle: <Text id="moderation.report_title">What’s wrong with this content?</Text>
|
|
50
57
|
};
|
|
51
58
|
|
|
59
|
+
const mapStateToProps = (state: Record<string, any>) => ({
|
|
60
|
+
playerSize: state.shell.playerSize
|
|
61
|
+
});
|
|
62
|
+
|
|
52
63
|
@withText(translates)
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
@connect(mapStateToProps)
|
|
65
|
+
export class Moderation extends Component<MergedProps, ModerationState> {
|
|
66
|
+
_buttonRef: null | HTMLButtonElement = null;
|
|
67
|
+
_textAreaElementRef: null | HTMLTextAreaElement = null;
|
|
55
68
|
|
|
56
69
|
state: ModerationState = {...initialState};
|
|
57
70
|
|
|
58
71
|
componentDidMount(): void {
|
|
59
|
-
if (this.
|
|
60
|
-
this.
|
|
72
|
+
if (this._buttonRef && this.props.closeButtonSelected) {
|
|
73
|
+
this._buttonRef.focus();
|
|
61
74
|
}
|
|
62
75
|
}
|
|
63
76
|
|
|
@@ -96,107 +109,84 @@ export class Moderation extends Component<ModerationProps, ModerationState> {
|
|
|
96
109
|
});
|
|
97
110
|
};
|
|
98
111
|
|
|
99
|
-
private _onKeyDown = (e: KeyboardEvent, callBack: Function) => {
|
|
100
|
-
if (e.keyCode !== KeyboardKeys.Enter && e.keyCode !== KeyboardKeys.Esc) {
|
|
101
|
-
// don't stopPropagation on ESC and Enter pressed as it prevent the popup closing
|
|
102
|
-
e.stopPropagation();
|
|
103
|
-
}
|
|
104
|
-
switch (e.keyCode) {
|
|
105
|
-
case KeyboardKeys.Enter: // Enter pressed
|
|
106
|
-
callBack();
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
private _popoverMenuItemRenderer = (el: PopoverMenuItem) => (
|
|
112
|
-
<div
|
|
113
|
-
tabIndex={1}
|
|
114
|
-
role="button"
|
|
115
|
-
onClick={() => el.onMenuChosen()}
|
|
116
|
-
onKeyDown={e => this._onKeyDown(e, el.onMenuChosen)}
|
|
117
|
-
className={styles.popoverMenuItem}>
|
|
118
|
-
{el.label}
|
|
119
|
-
</div>
|
|
120
|
-
);
|
|
121
|
-
|
|
122
112
|
private _getPopoverMenuOptions = () => {
|
|
123
113
|
return this.props.moderateOptions.map(({label, id}: ModerateOption) => ({
|
|
124
114
|
label: label || '',
|
|
125
|
-
onMenuChosen: () =>
|
|
115
|
+
onMenuChosen: (byKeyboard?: boolean) => {
|
|
116
|
+
this._onContentTypeChange(id || -1);
|
|
117
|
+
if (byKeyboard) {
|
|
118
|
+
this._textAreaElementRef?.focus();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
126
121
|
}));
|
|
127
122
|
};
|
|
128
123
|
|
|
129
|
-
private _popoverContent = () => {
|
|
130
|
-
return <PopoverMenu itemRenderer={this._popoverMenuItemRenderer} options={this._getPopoverMenuOptions()} />;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
124
|
private _getContentType = (): any => {
|
|
134
125
|
return this.props.moderateOptions.find((moderateOption: ModerateOption) => moderateOption.id === this.state.reportContentType) || {};
|
|
135
126
|
};
|
|
136
127
|
|
|
137
|
-
render(props:
|
|
138
|
-
const {reportLength, subtitle, tooltipMessage, onClick
|
|
128
|
+
render(props: MergedProps) {
|
|
129
|
+
const {playerSize = '', reportLength, subtitle, tooltipMessage, onClick} = props;
|
|
139
130
|
const {reportContent, reportContentType, isTextareaActive} = this.state;
|
|
131
|
+
if (playerSize === PLAYER_SIZE.TINY) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const submitButtonDisabled = reportContentType === -1;
|
|
140
135
|
return (
|
|
141
|
-
<
|
|
142
|
-
<
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
136
|
+
<OverlayPortal>
|
|
137
|
+
<Overlay open onClose={onClick}>
|
|
138
|
+
<div className={[styles.root, styles[playerSize]].join(' ')}>
|
|
139
|
+
<div className={styles.mainWrapper}>
|
|
140
|
+
<div className={styles.title}>{this.props.reportTitle}</div>
|
|
141
|
+
{subtitle ? <div className={[styles.subtitle].join(' ')}>{subtitle}</div> : null}
|
|
142
|
+
<Popover options={this._getPopoverMenuOptions()}>
|
|
143
|
+
<button
|
|
144
|
+
className={styles.selectWrapper}
|
|
145
|
+
tabIndex={0}
|
|
146
|
+
ref={node => {
|
|
147
|
+
this._buttonRef = node;
|
|
148
|
+
}}>
|
|
149
|
+
<div className={styles.select}>{reportContentType > -1 ? this._getContentType()?.label || '' : this.props.defaultContentType}</div>
|
|
150
|
+
<div className={styles.downArrow}>
|
|
151
|
+
<DownIcon />
|
|
152
|
+
</div>
|
|
153
|
+
</button>
|
|
154
|
+
</Popover>
|
|
155
|
+
<form>
|
|
156
|
+
<textarea
|
|
157
|
+
className={[styles.textarea, isTextareaActive ? styles.active : ''].join(' ')}
|
|
158
|
+
onInput={this._onContentChange}
|
|
159
|
+
onFocus={this._handleFocus}
|
|
160
|
+
onBlur={this._handleBlur}
|
|
161
|
+
tabIndex={0}
|
|
162
|
+
placeholder={this.props.reportPlaceholder}
|
|
163
|
+
aria-label={this.props.reportPlaceholder}
|
|
164
|
+
value={reportContent}
|
|
165
|
+
maxLength={reportLength}
|
|
166
|
+
ref={node => {
|
|
167
|
+
this._textAreaElementRef = node;
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
<div className={styles.submitWrapper}>
|
|
171
|
+
<div className={styles.characterCounter}>{`${reportContent.length}/${reportLength}`}</div>
|
|
172
|
+
<Tooltip label={tooltipMessage} classNames={styles.tooltip}>
|
|
173
|
+
<A11yWrapper onClick={this._handleSubmit}>
|
|
174
|
+
<button
|
|
175
|
+
role="button"
|
|
176
|
+
aria-disabled={submitButtonDisabled}
|
|
177
|
+
aria-label={this.props.sendReportLabel}
|
|
178
|
+
className={[styles.submitButton, submitButtonDisabled ? styles.disabled : ''].join(' ')}
|
|
179
|
+
tabIndex={0}>
|
|
180
|
+
{this.props.sendReportLabel}
|
|
181
|
+
</button>
|
|
182
|
+
</A11yWrapper>
|
|
183
|
+
</Tooltip>
|
|
172
184
|
</div>
|
|
173
|
-
</
|
|
174
|
-
</Fragment>
|
|
175
|
-
</Popover>
|
|
176
|
-
<form>
|
|
177
|
-
<textarea
|
|
178
|
-
className={[styles.textarea, isTextareaActive ? styles.active : ''].join(' ')}
|
|
179
|
-
onInput={this._onContentChange}
|
|
180
|
-
onFocus={this._handleFocus}
|
|
181
|
-
onBlur={this._handleBlur}
|
|
182
|
-
tabIndex={1}
|
|
183
|
-
placeholder={this.props.reportPlaceholder}
|
|
184
|
-
value={reportContent}
|
|
185
|
-
maxLength={reportLength}
|
|
186
|
-
/>
|
|
187
|
-
<div className={styles.submitWrapper}>
|
|
188
|
-
<div className={styles.characterCounter}>{`${reportContent.length}/${reportLength}`}</div>
|
|
189
|
-
<Tooltip label={tooltipMessage} classNames={styles.tooltip}>
|
|
190
|
-
<A11yWrapper onClick={this._handleSubmit}>
|
|
191
|
-
<button className={[styles.submitButton, reportContentType === -1 ? styles.disabled : ''].join(' ')} tabIndex={1}>
|
|
192
|
-
{this.props.sendReportLabel}
|
|
193
|
-
</button>
|
|
194
|
-
</A11yWrapper>
|
|
195
|
-
</Tooltip>
|
|
185
|
+
</form>
|
|
196
186
|
</div>
|
|
197
|
-
</
|
|
198
|
-
</
|
|
199
|
-
</
|
|
187
|
+
</div>
|
|
188
|
+
</Overlay>
|
|
189
|
+
</OverlayPortal>
|
|
200
190
|
);
|
|
201
191
|
}
|
|
202
192
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {h} from 'preact';
|
|
2
|
-
import * as styles from './plugin-button.scss';
|
|
3
2
|
import {icons} from '../icons';
|
|
3
|
+
import {ui} from 'kaltura-player-js';
|
|
4
4
|
import {A11yWrapper, OnClick} from '@playkit-js/common';
|
|
5
5
|
|
|
6
6
|
const {Tooltip, Icon} = KalturaPlayer.ui.components;
|
|
@@ -14,7 +14,7 @@ export const PluginButton = ({onClick, label}: PluginButtonProps) => {
|
|
|
14
14
|
return (
|
|
15
15
|
<Tooltip label={label} type="bottom">
|
|
16
16
|
<A11yWrapper onClick={onClick}>
|
|
17
|
-
<button aria-label={label} className={
|
|
17
|
+
<button aria-label={label} className={ui.style.upperBarIcon}>
|
|
18
18
|
<Icon
|
|
19
19
|
id="moderation-plugin-button"
|
|
20
20
|
height={icons.BigSize}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
@import '../../variables.scss';
|
|
2
|
+
|
|
1
3
|
.popover-container {
|
|
2
4
|
position: relative;
|
|
3
5
|
.popover-component {
|
|
6
|
+
z-index: 1;
|
|
4
7
|
background-color: #222222;
|
|
5
8
|
border-radius: 4px;
|
|
6
9
|
position: absolute;
|
|
@@ -28,3 +31,27 @@
|
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
}
|
|
34
|
+
.popover-menu {
|
|
35
|
+
padding-top: 6px;
|
|
36
|
+
padding-bottom: 6px;
|
|
37
|
+
}
|
|
38
|
+
.popover-menu-item {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
padding: 9px 24px 9px 16px;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
min-height: 30px;
|
|
44
|
+
line-height: 18px;
|
|
45
|
+
font-size: 15px;
|
|
46
|
+
&:hover {
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
background-color: $semigray-color;
|
|
49
|
+
}
|
|
50
|
+
&:focus {
|
|
51
|
+
outline: 1px solid $focus-color;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
.report-popover {
|
|
55
|
+
width: 100%;
|
|
56
|
+
max-width: 280px;
|
|
57
|
+
}
|