mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 09:28:11 +00:00
Page to list unapproved w2l templates
This commit is contained in:
1 parent
4116ea8425
commit
8d94167bc5
6 files changed
+228
No files matched your search
@@ -266,6 +266,10 @@ class ApiConfig {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/jobs/w2l_inference_queue_stats`;
|
||||
}
|
||||
|
||||
getModerationPendingW2lTemplates(): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/pending/w2l_templates`;
|
||||
}
|
||||
|
||||
private getScheme() : string {
|
||||
return this.isLocalDev ? "http" : "https";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { ApiConfig } from "../../../common/ApiConfig";
|
||||
|
||||
export interface PendingW2lTemplates {
|
||||
success: boolean,
|
||||
templates: Array<PendingW2lTemplatesEntryForList>
|
||||
}
|
||||
|
||||
export interface PendingW2lTemplatesEntryForList {
|
||||
template_token: string,
|
||||
title: string,
|
||||
template_type: string,
|
||||
duration_millis: number,
|
||||
frame_width: number,
|
||||
frame_height: number,
|
||||
creator_user_token: string,
|
||||
creator_username: string,
|
||||
creator_display_name: string,
|
||||
creator_gravatar_hash: string,
|
||||
created_at: Date,
|
||||
}
|
||||
|
||||
export enum PendingW2lTemplatesLookupError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
FrontendError,
|
||||
}
|
||||
|
||||
export type GetPendingW2lTemplatesResponse = PendingW2lTemplates | PendingW2lTemplatesLookupError;
|
||||
|
||||
export function GetPendingW2lTemplatesIsOk(response: GetPendingW2lTemplatesResponse): response is PendingW2lTemplates {
|
||||
return response.hasOwnProperty('templates');
|
||||
}
|
||||
|
||||
export function GetPendingW2lTemplatesIsErr(response: GetPendingW2lTemplatesResponse): response is PendingW2lTemplatesLookupError {
|
||||
return !response.hasOwnProperty('templates');
|
||||
}
|
||||
|
||||
interface PendingW2lTemplatesResponsePayload {
|
||||
success: boolean,
|
||||
error_reason?: string,
|
||||
templates?: PendingW2lTemplates,
|
||||
}
|
||||
|
||||
|
||||
export async function GetPendingW2lTemplates() : Promise<GetPendingW2lTemplatesResponse>
|
||||
{
|
||||
const endpoint = new ApiConfig().getModerationPendingW2lTemplates();
|
||||
|
||||
return await fetch(endpoint, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const response : PendingW2lTemplatesResponsePayload = res;
|
||||
|
||||
if (response?.success) {
|
||||
return res as PendingW2lTemplates; // TODO: This is not the way.
|
||||
}
|
||||
|
||||
if (response?.success === false) {
|
||||
if (response.error_reason?.includes("authorized")) {
|
||||
return PendingW2lTemplatesLookupError.NotAuthorized;
|
||||
} else {
|
||||
return PendingW2lTemplatesLookupError.ServerError;
|
||||
}
|
||||
}
|
||||
|
||||
return PendingW2lTemplatesLookupError.FrontendError;
|
||||
})
|
||||
.catch(e => {
|
||||
return PendingW2lTemplatesLookupError.FrontendError;
|
||||
});
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import { ProfileBanFc } from './profile/profile_ban/ProfileBanFc';
|
||||
import { ModerationUserListFc } from './moderation/moderation_user_list/ModerationUserList';
|
||||
import { LeaderboardFc } from './leaderboard/LeaderboardFc';
|
||||
import { ModerationJobStatsFc } from './moderation/moderation_job_stats/ModerationJobStatsFc';
|
||||
import { ModerationPendingW2lTemplatesFc } from './moderation/moderation_pending_w2l_templates/ModerationPendingW2lTemplatesFc';
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
@@ -285,6 +286,12 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/moderation/approve/w2l_templates">
|
||||
<ModerationPendingW2lTemplatesFc
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/moderation">
|
||||
<ModerationFc
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faPhotoVideo } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
interface Props {
|
||||
title?: string,
|
||||
}
|
||||
|
||||
export function PhotoVideoIcon(props: Props) {
|
||||
const title = props.title === undefined ? 'Media' : props.title;
|
||||
return (
|
||||
<FontAwesomeIcon icon={faPhotoVideo} title={title} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,13 @@ function ModerationFc(props: Props) {
|
||||
|
||||
<br />
|
||||
|
||||
<Link
|
||||
to="/moderation/approve/w2l_templates"
|
||||
className="button is-link is-large is-fullwidth is-light"
|
||||
>Unapproved W2L Templates</Link>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
More mod controls will be added in the future: user roles, activity tracking,
|
||||
timed bans, account bans, etc.
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { SessionWrapper } from '../../../../session/SessionWrapper';
|
||||
import { formatDistance } from 'date-fns';
|
||||
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
|
||||
import { GravatarFc } from '../../_common/GravatarFc';
|
||||
import { BackLink } from '../../_common/BackLink';
|
||||
import { GetPendingW2lTemplates, GetPendingW2lTemplatesIsOk, PendingW2lTemplatesEntryForList } from '../../../api/moderation/GetPendingW2lTemplates';
|
||||
import { PhotoVideoIcon } from '../../_icons/PhotoVideoIcon';
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
}
|
||||
|
||||
function ModerationPendingW2lTemplatesFc(props: Props) {
|
||||
const [templates, setTemplates] = useState<Array<PendingW2lTemplatesEntryForList>>([]);
|
||||
|
||||
const getUsers = useCallback(async () => {
|
||||
const response = await GetPendingW2lTemplates();
|
||||
|
||||
if (GetPendingW2lTemplatesIsOk(response)) {
|
||||
setTemplates(response.templates);
|
||||
}
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getUsers();
|
||||
}, [getUsers]);
|
||||
|
||||
|
||||
if (!templates) {
|
||||
return <div />
|
||||
}
|
||||
|
||||
if (!props.sessionWrapper.canApproveW2lTemplates()) {
|
||||
return <h1>Unauthorized</h1>;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
let rows : Array<JSX.Element> = [];
|
||||
|
||||
templates.forEach(template=> {
|
||||
const createTime = new Date(template.created_at);
|
||||
const relativeCreateTime = formatDistance(createTime, now, { addSuffix: true });
|
||||
|
||||
rows.push(
|
||||
<tr key={template.template_token}>
|
||||
<td>
|
||||
<Link to={FrontendUrlConfig.w2lTemplatePage(template.template_token)}>
|
||||
<PhotoVideoIcon title="W2l Template" />
|
||||
|
||||
{template.title}
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
<Link to={FrontendUrlConfig.userProfilePage(template.creator_display_name)}>
|
||||
<GravatarFc username={template.creator_display_name} email_hash={template.creator_gravatar_hash} size={12} />
|
||||
|
||||
{template.creator_display_name}
|
||||
</Link>
|
||||
</td>
|
||||
<td>{template.template_type}</td>
|
||||
<td>{relativeCreateTime}</td>
|
||||
</tr>
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title is-1"> Unapproved W2L Templates </h1>
|
||||
|
||||
<BackLink link={FrontendUrlConfig.moderationMain()} text="Back to moderation" />
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<p>
|
||||
This lists the templates that haven't yet been approved for display.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
Don't delete templates unless they overwhelmingly break the rules.
|
||||
Users can use templates in private without them necessarily being approved for public use.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
Setting approved = TRUE will show the template on the main site for everyone to use.
|
||||
Setting approved = FALSE will still let the author and people directly accessing via
|
||||
URL to use the template, but will not make it public.
|
||||
It will also remove it from the moderation queue.
|
||||
</p>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<table className="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Template</th>
|
||||
<th>Creator</th>
|
||||
<th>Type</th>
|
||||
<th>Created At</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { ModerationPendingW2lTemplatesFc };
|
||||
Reference in new issue
Block a user