Skip to content
GitLab
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
Commits on Source (3)
(feat): flip labels if on appeal - closes
· dbbc295d
Mark Harding
authored
May 17, 2019
#1311
dbbc295d
(feat): various changes to ui and ux
· 99f1db74
Mark Harding
authored
May 17, 2019
99f1db74
(fix): mark can not spell Violence
· b6bb91bc
Mark Harding
authored
May 17, 2019
b6bb91bc
Hide whitespace changes
Inline
Side-by-side
src/app/app.component.html
View file @
b6bb91bc
...
...
@@ -42,6 +42,7 @@
<m-overlay-modal></m-overlay-modal>
<m--blockchain--transaction-overlay></m--blockchain--transaction-overlay>
<m-modal--tos-updated
*ngIf=
"session.isLoggedIn()"
></m-modal--tos-updated>
<m-juryDutySession__summons
*ngIf=
"session.isLoggedIn()"
></m-juryDutySession__summons>
<m-modal-signup-on-scroll></m-modal-signup-on-scroll>
...
...
src/app/modules/report/console/appeal.component.html
View file @
b6bb91bc
...
...
@@ -13,20 +13,21 @@
<div
class=
"m-moderationAppeal__composer"
*ngIf=
"!appeal.note"
>
<textarea
#appealContent
[(ngModel)]=
"note"
placeholder=
"Please type in this box if you wish to appeal this decision, explaining your reasons"
i18n=
"@@REPORT__CONSOLE__APPEAL_COMPOSER_PLACEHOLDER"
></textarea>
<button
class=
"m-moderationAppeal__button"
[disabled]=
"appeal.inProgress"
(click)=
"sendAppeal(
appeal, appealContent.value, i
)"
(click)=
"sendAppeal()"
i18n=
"@@REPORT__CONSOLE__APPEAL_ACTION"
>
Appeal
</button>
</div>
<div
class=
"m-moderationAppeal__appealNote"
*ngIf=
"appeal.note"
>
<p>
{{appeal.
appeal_
note}}
</p>
<p>
{{appeal.note}}
</p>
</div>
</div>
...
...
src/app/modules/report/console/appeal.component.ts
View file @
b6bb91bc
...
...
@@ -2,6 +2,7 @@ import {
Component
,
OnInit
,
Input
,
ChangeDetectorRef
,
}
from
'
@angular/core
'
;
import
{
Client
}
from
'
../../../services/api/client
'
;
...
...
@@ -20,6 +21,7 @@ export class ModerationAppealComponent {
constructor
(
private
client
:
Client
,
public
service
:
JurySessionService
,
private
cd
:
ChangeDetectorRef
,
)
{
}
async
sendAppeal
()
{
...
...
@@ -31,8 +33,12 @@ export class ModerationAppealComponent {
});
this
.
appeal
.
note
=
this
.
note
;
this
.
detectChanges
();
}
catch
(
e
)
{
alert
((
e
&&
e
.
message
)
||
'
Error sending appeal
'
);
}
finally
{
this
.
appeal
.
inProgress
=
false
;
}
}
...
...
@@ -42,4 +48,8 @@ export class ModerationAppealComponent {
action
;
}
detectChanges
()
{
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
}
src/app/modules/report/juryduty/session/content.component.html
View file @
b6bb91bc
...
...
@@ -24,13 +24,15 @@
class=
"m-btn m-btn--slim"
(click)=
"uphold()"
>
Uphold Report
<ng-container
*ngIf=
"report.is_appeal; else upholdLabel"
>
Reject Appeal
</ng-container>
<ng-template
#upholdLabel
>
Uphold Report
</ng-template>
</button>
<button
class=
"m-btn m-btn--slim"
(click)=
"overturn()"
>
Overturn Report
<ng-container
*ngIf=
"report.is_appeal; else overturnLabel"
>
Accept Appeal
</ng-container>
<ng-template
#overturnLabel
>
Overturn Report
</ng-template>
</button>
</div>
</ng-container>
...
...
src/app/modules/report/juryduty/session/session.service.ts
View file @
b6bb91bc
...
...
@@ -15,6 +15,10 @@ export class JurySessionService {
return
await
this
.
client
.
get
(
'
api/v2/moderation/jury/
'
+
opts
.
juryType
);
}
async
getReport
(
urn
)
{
return
(
<
any
>
(
await
this
.
client
.
get
(
'
api/v2/moderation/jury/appeal/
'
+
urn
))).
report
;
}
async
overturn
(
report
)
{
const
juryType
=
report
.
is_appeal
?
'
appeal
'
:
'
initial
'
;
return
await
this
.
client
.
post
(
`api/v2/moderation/jury/
${
juryType
}
/
${
report
.
urn
}
`
,
{
...
...
@@ -32,11 +36,14 @@ export class JurySessionService {
getReasonString
(
report
)
{
return
REASONS
.
filter
((
item
)
=>
{
if
(
item
.
hasMore
&&
item
.
reasons
)
{
return
item
.
reasons
[
report
.
sub_reason_code
].
value
===
report
.
sub_reason_code
;
return
item
.
value
===
report
.
reason_code
&&
item
.
reasons
[
report
.
sub_reason_code
-
1
].
value
===
report
.
sub_reason_code
;
}
return
item
.
value
===
report
.
reason_code
;
})
.
map
((
item
)
=>
{
if
(
item
.
hasMore
&&
item
.
reasons
)
{
return
item
.
reasons
[
report
.
sub_reason_code
-
1
].
label
;
}
return
item
.
label
;
})
.
join
(
'
,
'
);
...
...
@@ -49,6 +56,11 @@ export class JurySessionService {
case
2
:
friendlyString
=
'
marked NSFW
'
;
break
;
case
4
:
case
8
:
if
(
report
.
entity
&&
report
.
entity
.
type
==
'
user
'
)
friendlyString
=
'
given a strike
'
;
break
;
}
return
friendlyString
;
...
...
src/app/modules/report/juryduty/session/summons.component.html
0 → 100644
View file @
b6bb91bc
<m-modal
[open]=
"true"
(closed)=
"onClose($event)"
*ngIf=
"showModal"
>
<div
class=
"m-juryDutySession__summons"
>
<h2>
You've been selected for Jury Duty
</h2>
<p>
The Minds Jury decides on what content is within the terms of service.
We randomly select 12 members of the community to uphold or overturn decisions made.
</p>
<div
class=
"m-juryDutySessionSummons__buttons"
*ngIf=
"!accepted"
>
<button
class=
"m-btn m-btn--slim m-btn--action"
(click)=
"accept()"
>
Accept
</button>
<button
class=
"m-btn m-btn--slim"
(click)=
"decline()"
>
<span>
Decline -
</span>
<span
class=
"countdown"
>
{{ expires | timediff: true }}
</span>
</button>
</div>
<div
*ngIf=
"inProgress"
class=
"mdl-spinner mdl-js-spinner is-active"
[
mdl
]
></div>
<div
class=
"m-juryDutySessionSummons__report"
*ngIf=
"report"
>
<m-juryDutySession__content
[report]=
"report"
>
</m-juryDutySession__content>
</div>
</div>
</m-modal>
src/app/modules/report/juryduty/session/summons.component.scss
0 → 100644
View file @
b6bb91bc
.m-juryDutySession__summons
{
padding
:
24px
16px
;
h2
{
font-weight
:
600
;
font-size
:
26px
;
line-height
:
1
;
margin
:
0
;
}
p
{
line-height
:
1
.25
;
font-size
:
16px
;
margin-top
:
16px
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-400
);
}
}
.m-btn
{
margin
:
8px
;
.countdown
{
font-weight
:
bold
;
}
}
}
.m-juryDutySessionSummons__countdown
{
padding
:
16px
0
;
span
{
font-weight
:
600
;
font-size
:
24px
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-300
);
}
}
}
src/app/modules/report/juryduty/session/summons.component.ts
0 → 100644
View file @
b6bb91bc
import
{
Component
,
Input
,
AfterViewInit
,
ViewChild
,
ElementRef
,
ChangeDetectorRef
}
from
'
@angular/core
'
;
import
{
interval
,
Subscription
}
from
'
rxjs
'
;
import
{
map
,
take
}
from
"
rxjs/operators
"
;
import
{
OverlayModalService
}
from
'
../../../../services/ux/overlay-modal
'
;
import
{
Client
}
from
'
../../../../services/api
'
;
import
{
Session
}
from
'
../../../../services/session
'
;
import
{
REASONS
}
from
'
../../../../services/list-options
'
;
import
{
JurySessionService
}
from
'
./session.service
'
;
import
{
SocketsService
}
from
'
../../../../services/sockets
'
;
@
Component
({
selector
:
'
m-juryDutySession__summons
'
,
templateUrl
:
'
summons.component.html
'
})
export
class
JuryDutySessionSummonsComponent
{
showModal
:
boolean
=
false
;
expires
:
number
=
0
;
expiresCountdown$
:
Subscription
;
accepted
:
boolean
=
false
;
inProgress
:
boolean
=
false
;
summons
;
reportUrn
:
string
=
''
;
report
;
constructor
(
private
sessionService
:
JurySessionService
,
private
client
:
Client
,
private
socketsService
:
SocketsService
,
private
cd
:
ChangeDetectorRef
,
)
{
this
.
expires
=
60
;
// 60 seconds
}
ngOnInit
()
{
this
.
socketsService
.
join
(
`moderation_summon`
);
this
.
socketsService
.
subscribe
(
`moderation_summon`
,
(
summons
)
=>
{
this
.
summons
=
JSON
.
parse
(
summons
);
this
.
startSummons
();
});
}
startSummons
()
{
if
(
this
.
expiresCountdown$
)
this
.
expiresCountdown$
.
unsubscribe
();
this
.
expires
=
parseInt
(
this
.
summons
.
ttl
)
/
2
;
this
.
reportUrn
=
this
.
summons
.
report_urn
;
this
.
showModal
=
true
;
this
.
detectChanges
();
this
.
expiresCountdown$
=
interval
(
1000
)
.
pipe
(
take
(
this
.
expires
),
map
((
v
)
=>
--
this
.
expires
)
)
.
subscribe
((
expires
)
=>
{
this
.
expires
=
expires
;
if
(
this
.
expires
<=
0
&&
!
this
.
accepted
)
this
.
showModal
=
false
;
this
.
detectChanges
()
});
}
ngOnDestroy
()
{
if
(
this
.
expiresCountdown$
)
this
.
expiresCountdown$
.
unsubscribe
();
}
async
accept
()
{
if
(
!
confirm
(
"
I am 18 years old and volunteer to participate in this jury. I acknowledge that I may be exposed to content not safe for work (NSFW) and understand that the purpose of the trial is to enforce the site content policy.
"
))
{
return
;
}
this
.
accepted
=
true
;
this
.
detectChanges
();
this
.
inProgress
=
true
;
this
.
report
=
(
<
any
>
await
this
.
client
.
post
(
`api/v2/moderation/summons`
,
{
report_urn
:
this
.
summons
.
report_urn
,
jury_type
:
this
.
summons
.
jury_type
,
status
:
'
accepted
'
,
})).
report
;
this
.
inProgress
=
false
;
}
async
decline
()
{
await
this
.
client
.
post
(
`api/v2/moderation/summons`
,
{
report_urn
:
this
.
summons
.
report_urn
,
jury_type
:
this
.
summons
.
jury_type
,
status
:
'
declined
'
,
});
this
.
showModal
=
false
;
this
.
detectChanges
();
}
onClose
(
e
)
{
this
.
showModal
=
false
;
this
.
detectChanges
();
}
detectChanges
()
{
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
}
src/app/modules/report/marketing/marketing.component.html
View file @
b6bb91bc
...
...
@@ -11,7 +11,7 @@
The Minds Jury decides on what content is within the terms of service.
</h3>
<button
class=
"m-btn m-btn--slim"
(click)=
"startJuryDuty()"
>
<button
class=
"m-btn m-btn--slim"
(click)=
"startJuryDuty()"
*ngIf=
"session.isAdmin()"
>
Start Jury Duty
</button>
</div>
...
...
@@ -53,11 +53,11 @@
<span>
Content Reported
</span>
</div>
<div
class=
"m-layout__cell"
>
<b>
{{ stats.appealedPct }}%
</b>
<b>
{{ stats.appealedPct
| number
}}%
</b>
<span>
Appealed
</span>
</div>
<div
class=
"m-layout__cell"
>
<b>
{{ stats.upheldPct }}%
</b>
<b>
{{ stats.upheldPct
| number
}}%
</b>
<span>
Upheld by Community Jury
</span>
</div>
</div>
...
...
src/app/modules/report/marketing/marketing.component.scss
View file @
b6bb91bc
...
...
@@ -3,7 +3,7 @@
.m-marketing__hero
{
background
:
#132552
;
background
-color
:
#132552
!
important
;
padding-bottom
:
72px
;
.m-marketingHero__inner
{
...
...
src/app/modules/report/marketing/marketing.component.ts
View file @
b6bb91bc
...
...
@@ -10,7 +10,7 @@ import { Router } from '@angular/router';
import
{
Client
}
from
'
../../../common/api/client.service
'
;
import
{
MindsTitle
}
from
'
../../../services/ux/title
'
;
import
{
REASONS
as
REASONS_LIST
}
from
'
../../../services/list-options
'
;
import
{
Session
}
from
'
../../../services/session
'
;
@
Component
({
selector
:
'
m-reports__marketing
'
,
...
...
@@ -35,6 +35,7 @@ export class ReportsMarketingComponent {
private
cd
:
ChangeDetectorRef
,
private
router
:
Router
,
private
title
:
MindsTitle
,
public
session
:
Session
,
)
{
title
.
setTitle
(
'
Community Moderation
'
);
}
...
...
@@ -44,7 +45,7 @@ export class ReportsMarketingComponent {
}
startJuryDuty
()
{
this
.
router
.
navigate
([
'
/moderation/juryduty/
appe
al
'
]);
this
.
router
.
navigate
([
'
/moderation/juryduty/
initi
al
'
]);
}
async
loadStats
()
{
...
...
src/app/modules/report/report.module.ts
View file @
b6bb91bc
...
...
@@ -14,6 +14,7 @@ import { CommentsModule } from '../comments/comments.module';
import
{
JuryDutySessionListComponent
}
from
'
./juryduty/session/list.component
'
;
import
{
JurySessionService
}
from
'
./juryduty/session/session.service
'
;
import
{
JuryDutySessionContentComponent
}
from
'
./juryduty/session/content.component
'
;
import
{
JuryDutySessionSummonsComponent
}
from
'
./juryduty/session/summons.component
'
;
import
{
StrikesComponent
}
from
'
./strikes/strikes.component
'
;
import
{
BannedService
}
from
'
./banned/banned.service
'
;
import
{
BannedComponent
}
from
'
./banned/banned.component
'
;
...
...
@@ -43,17 +44,20 @@ import { ModerationAppealComponent } from './console/appeal.component';
JuryDutySessionComponent
,
JuryDutySessionListComponent
,
JuryDutySessionContentComponent
,
JuryDutySessionSummonsComponent
,
StrikesComponent
,
BannedComponent
,
ModerationAppealComponent
,
],
exports
:
[
ReportConsoleComponent
ReportConsoleComponent
,
JuryDutySessionSummonsComponent
,
],
entryComponents
:
[
ReportCreatorComponent
,
ReportsMarketingComponent
,
JuryDutySessionComponent
,
JuryDutySessionSummonsComponent
,
StrikesComponent
,
BannedComponent
,
],
...
...
src/app/modules/report/strikes/strikes.component.html
View file @
b6bb91bc
...
...
@@ -3,13 +3,13 @@
<h2>
Strikes
</h2>
<p>
Strikes are imposed for violations against the terms of service. Following 3 strikes, channels are banned.
</p>
<ul>
<li
*ngFor=
"let strike of strikes"
>
{{ strike['@timestamp'] | date: 'medium' }}
<ul
class=
"m-moderationStrike__list"
>
<li
*ngFor=
"let strike of strikes"
class=
"m-border m-moderation__strike"
>
{{ strike['@timestamp'] * 1000 | date: 'medium' }}
<div>
<b>
{{ service.getAction(strike) }}
</b>
<span>
for
</span>
<b>
{{ service.getReasonString(strike) }}
</b>
</div>
</li>
...
...
src/app/modules/report/strikes/strikes.component.scss
View file @
b6bb91bc
m-moderation__strikes
h2
{
font-weight
:
600
;
}
\ No newline at end of file
}
.m-moderationStrike__list
{
list-style
:
none
;
margin
:
0
;
padding
:
0
;
}
.m-moderation__strike
{
@include
m-theme
()
{
background-color
:
themed
(
$m-white
);
}
padding
:
16px
;
margin-bottom
:
16px
;
}
src/app/services/list-options.ts
View file @
b6bb91bc
...
...
@@ -46,7 +46,7 @@ export const REASONS : Array<any> = [
{
value
:
1
,
label
:
'
Nudity
'
},
{
value
:
2
,
label
:
'
Pornography
'
},
{
value
:
3
,
label
:
'
Profanity
'
},
{
value
:
4
,
label
:
'
Viol
a
nce and Gore
'
},
{
value
:
4
,
label
:
'
Viol
e
nce and Gore
'
},
{
value
:
5
,
label
:
'
Race, Religion, Gender
'
},
],
},
...
...