mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-22 06:36:17 +00:00
Temp bans (#524)
* Updating translations. * Adding temp bans. * Using new lemmy-js-client with temp bans * Fixing some lint and dep issues
This commit is contained in:
parent
9abe811021
commit
4915193ae5
|
@ -1 +1 @@
|
|||
Subproject commit 1e0bb9920cda13bb128c87e85125b98ab8f319b6
|
||||
Subproject commit 27a29ad5411438e4792e8e298aa5f4a3b60bb908
|
12
package.json
12
package.json
|
@ -20,7 +20,7 @@
|
|||
"@typescript-eslint/parser": "^5.6.0",
|
||||
"autosize": "^5.0.1",
|
||||
"check-password-strength": "^2.0.3",
|
||||
"choices.js": "^9.0.1",
|
||||
"choices.js": "^10.0.0",
|
||||
"emoji-short-name": "^1.0.0",
|
||||
"express": "~4.17.1",
|
||||
"i18next": "^21.5.4",
|
||||
|
@ -41,6 +41,7 @@
|
|||
"moment": "^2.29.1",
|
||||
"register-service-worker": "^1.7.2",
|
||||
"rxjs": "^7.4.0",
|
||||
"sass": "^1.47.0",
|
||||
"serialize-javascript": "^6.0.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
"toastify-js": "^1.11.2",
|
||||
|
@ -51,12 +52,12 @@
|
|||
"@babel/core": "^7.16.0",
|
||||
"@babel/plugin-transform-runtime": "^7.16.4",
|
||||
"@babel/plugin-transform-typescript": "^7.16.1",
|
||||
"@babel/preset-env": "7.16.4",
|
||||
"@babel/preset-env": "7.16.7",
|
||||
"@babel/preset-typescript": "^7.16.0",
|
||||
"@babel/runtime": "^7.16.3",
|
||||
"@types/autosize": "^4.0.0",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^16.11.11",
|
||||
"@types/node": "^17.0.8",
|
||||
"@types/node-fetch": "^2.5.11",
|
||||
"@types/serialize-javascript": "^5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
||||
|
@ -72,11 +73,10 @@
|
|||
"husky": "^7.0.4",
|
||||
"import-sort-style-module": "^6.0.0",
|
||||
"iso-639-1": "^2.1.10",
|
||||
"lemmy-js-client": "0.15.0-rc.6",
|
||||
"lemmy-js-client": "0.15.0-rc.34",
|
||||
"lint-staged": "^12.1.2",
|
||||
"mini-css-extract-plugin": "^2.4.5",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-sass": "^7.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier-plugin-import-sort": "^0.0.7",
|
||||
"prettier-plugin-organize-imports": "^2.3.4",
|
||||
|
@ -90,7 +90,7 @@
|
|||
"typescript": "^4.5.2",
|
||||
"webpack": "5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"webpack-dev-server": "4.6.0",
|
||||
"webpack-dev-server": "4.7.2",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -28,7 +28,8 @@ import {
|
|||
authField,
|
||||
canMod,
|
||||
colorList,
|
||||
getUnixTime,
|
||||
futureDaysToUnixTime,
|
||||
isBanned,
|
||||
isMod,
|
||||
mdToHtml,
|
||||
numToSI,
|
||||
|
@ -51,7 +52,7 @@ interface CommentNodeState {
|
|||
showBanDialog: boolean;
|
||||
removeData: boolean;
|
||||
banReason: string;
|
||||
banExpires: string;
|
||||
banExpireDays: number;
|
||||
banType: BanType;
|
||||
showConfirmTransferSite: boolean;
|
||||
showConfirmTransferCommunity: boolean;
|
||||
|
@ -96,7 +97,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
showBanDialog: false,
|
||||
removeData: false,
|
||||
banReason: null,
|
||||
banExpires: null,
|
||||
banExpireDays: null,
|
||||
banType: BanType.Community,
|
||||
collapsed: false,
|
||||
viewSource: false,
|
||||
|
@ -187,7 +188,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
{i18n.t("bot_account").toLowerCase()}
|
||||
</div>
|
||||
)}
|
||||
{(cv.creator_banned_from_community || cv.creator.banned) && (
|
||||
{(cv.creator_banned_from_community || isBanned(cv.creator)) && (
|
||||
<div className="badge badge-danger mr-2">
|
||||
{i18n.t("banned")}
|
||||
</div>
|
||||
|
@ -614,7 +615,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
{this.canAdmin && (
|
||||
<>
|
||||
{!this.isAdmin &&
|
||||
(!cv.creator.banned ? (
|
||||
(!isBanned(cv.creator) ? (
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(
|
||||
|
@ -637,7 +638,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
{i18n.t("unban_from_site")}
|
||||
</button>
|
||||
))}
|
||||
{!cv.creator.banned &&
|
||||
{!isBanned(cv.creator) &&
|
||||
cv.creator.local &&
|
||||
(!this.state.showConfirmAppointAsAdmin ? (
|
||||
<button
|
||||
|
@ -797,7 +798,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
)}
|
||||
{this.state.showBanDialog && (
|
||||
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
|
||||
<div class="form-group row">
|
||||
<div class="form-group row col-12">
|
||||
<label
|
||||
class="col-form-label"
|
||||
htmlFor={`mod-ban-reason-${cv.comment.id}`}
|
||||
|
@ -812,6 +813,20 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
value={this.state.banReason}
|
||||
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
||||
/>
|
||||
<label
|
||||
class="col-form-label"
|
||||
htmlFor={`mod-ban-expires-${cv.comment.id}`}
|
||||
>
|
||||
{i18n.t("expires")}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id={`mod-ban-expires-${cv.comment.id}`}
|
||||
class="form-control mr-2"
|
||||
placeholder={i18n.t("number_of_days")}
|
||||
value={this.state.banExpireDays}
|
||||
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
||||
/>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
|
@ -1191,8 +1206,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleModBanExpiresChange(i: CommentNode, event: any) {
|
||||
i.state.banExpires = event.target.value;
|
||||
handleModBanExpireDaysChange(i: CommentNode, event: any) {
|
||||
i.state.banExpireDays = event.target.value;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
|
@ -1223,7 +1238,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
ban,
|
||||
remove_data: i.state.removeData,
|
||||
reason: i.state.banReason,
|
||||
expires: getUnixTime(i.state.banExpires),
|
||||
expires: futureDaysToUnixTime(i.state.banExpireDays),
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.banFromCommunity(form));
|
||||
|
@ -1238,7 +1253,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
ban,
|
||||
remove_data: i.state.removeData,
|
||||
reason: i.state.banReason,
|
||||
expires: getUnixTime(i.state.banExpires),
|
||||
expires: futureDaysToUnixTime(i.state.banExpireDays),
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.banPerson(form));
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import autosize from "autosize";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import {
|
||||
BannedPersonsResponse,
|
||||
GetBannedPersons,
|
||||
GetSiteConfig,
|
||||
GetSiteConfigResponse,
|
||||
GetSiteResponse,
|
||||
PersonViewSafe,
|
||||
SaveSiteConfig,
|
||||
SiteResponse,
|
||||
UserOperation,
|
||||
|
@ -34,6 +37,7 @@ interface AdminSettingsState {
|
|||
siteConfigRes: GetSiteConfigResponse;
|
||||
siteConfigForm: SaveSiteConfig;
|
||||
loading: boolean;
|
||||
banned: PersonViewSafe[];
|
||||
siteConfigLoading: boolean;
|
||||
}
|
||||
|
||||
|
@ -45,11 +49,12 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
siteRes: this.isoData.site_res,
|
||||
siteConfigForm: {
|
||||
config_hjson: null,
|
||||
auth: authField(),
|
||||
auth: null,
|
||||
},
|
||||
siteConfigRes: {
|
||||
config_hjson: null,
|
||||
},
|
||||
banned: [],
|
||||
loading: true,
|
||||
siteConfigLoading: null,
|
||||
};
|
||||
|
@ -67,20 +72,34 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
this.state.siteConfigRes = this.isoData.routeData[0];
|
||||
this.state.siteConfigForm.config_hjson =
|
||||
this.state.siteConfigRes.config_hjson;
|
||||
this.state.banned = this.isoData.routeData[1].banned;
|
||||
this.state.siteConfigLoading = false;
|
||||
this.state.loading = false;
|
||||
} else {
|
||||
this.state.siteConfigForm.auth = authField();
|
||||
WebSocketService.Instance.send(
|
||||
wsClient.getSiteConfig({
|
||||
auth: authField(),
|
||||
})
|
||||
);
|
||||
WebSocketService.Instance.send(
|
||||
wsClient.getBannedPersons({
|
||||
auth: authField(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
|
||||
let form: GetSiteConfig = { auth: req.auth };
|
||||
return [req.client.getSiteConfig(form)];
|
||||
let promises: Promise<any>[] = [];
|
||||
|
||||
let siteConfigForm: GetSiteConfig = { auth: req.auth };
|
||||
promises.push(req.client.getSiteConfig(siteConfigForm));
|
||||
|
||||
let bannedPersonsForm: GetBannedPersons = { auth: req.auth };
|
||||
promises.push(req.client.getBannedPersons(bannedPersonsForm));
|
||||
|
||||
return promises;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -105,10 +124,6 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
render() {
|
||||
return (
|
||||
<div class="container">
|
||||
<HtmlTags
|
||||
title={this.documentTitle}
|
||||
path={this.context.router.route.match.url}
|
||||
/>
|
||||
{this.state.loading ? (
|
||||
<h5>
|
||||
<Spinner large />
|
||||
|
@ -116,6 +131,10 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
) : (
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<HtmlTags
|
||||
title={this.documentTitle}
|
||||
path={this.context.router.route.match.url}
|
||||
/>
|
||||
{this.state.siteRes.site_view.site.id && (
|
||||
<SiteForm site={this.state.siteRes.site_view.site} />
|
||||
)}
|
||||
|
@ -149,7 +168,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
<>
|
||||
<h5>{i18n.t("banned_users")}</h5>
|
||||
<ul class="list-unstyled">
|
||||
{this.state.siteRes.banned.map(banned => (
|
||||
{this.state.banned.map(banned => (
|
||||
<li class="list-inline-item">
|
||||
<PersonListing person={banned.person} />
|
||||
</li>
|
||||
|
@ -225,6 +244,10 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
this.state.siteRes.site_view = data.site_view;
|
||||
this.setState(this.state);
|
||||
toast(i18n.t("site_saved"));
|
||||
} else if (op == UserOperation.GetBannedPersons) {
|
||||
let data = wsJsonToRes<BannedPersonsResponse>(msg).data;
|
||||
this.state.banned = data.banned;
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.GetSiteConfig) {
|
||||
let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
|
||||
this.state.siteConfigRes = data;
|
||||
|
|
|
@ -896,19 +896,6 @@ export class Home extends Component<any, HomeState> {
|
|||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BanPerson) {
|
||||
let data = wsJsonToRes<BanPersonResponse>(msg).data;
|
||||
let found = this.state.siteRes.banned.find(
|
||||
p => (p.person.id = data.person_view.person.id)
|
||||
);
|
||||
|
||||
// Remove the banned if its found in the list, and the action is an unban
|
||||
if (found && !data.banned) {
|
||||
this.state.siteRes.banned = this.state.siteRes.banned.filter(
|
||||
i => i.person.id !== data.person_view.person.id
|
||||
);
|
||||
} else {
|
||||
this.state.siteRes.banned.push(data.person_view);
|
||||
}
|
||||
|
||||
this.state.posts
|
||||
.filter(p => p.creator.id == data.person_view.person.id)
|
||||
.forEach(p => (p.creator.banned = data.banned));
|
||||
|
|
|
@ -26,8 +26,9 @@ import { UserService, WebSocketService } from "../../services";
|
|||
import {
|
||||
authField,
|
||||
canMod,
|
||||
getUnixTime,
|
||||
futureDaysToUnixTime,
|
||||
hostname,
|
||||
isBanned,
|
||||
isImage,
|
||||
isMod,
|
||||
isVideo,
|
||||
|
@ -54,7 +55,7 @@ interface PostListingState {
|
|||
showBanDialog: boolean;
|
||||
removeData: boolean;
|
||||
banReason: string;
|
||||
banExpires: string;
|
||||
banExpireDays: number;
|
||||
banType: BanType;
|
||||
showConfirmTransferSite: boolean;
|
||||
showConfirmTransferCommunity: boolean;
|
||||
|
@ -90,7 +91,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
showBanDialog: false,
|
||||
removeData: false,
|
||||
banReason: null,
|
||||
banExpires: null,
|
||||
banExpireDays: null,
|
||||
banType: BanType.Community,
|
||||
showConfirmTransferSite: false,
|
||||
showConfirmTransferCommunity: false,
|
||||
|
@ -294,7 +295,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</span>
|
||||
)}
|
||||
{(post_view.creator_banned_from_community ||
|
||||
post_view.creator.banned) && (
|
||||
isBanned(post_view.creator)) && (
|
||||
<span className="mx-1 badge badge-danger">{i18n.t("banned")}</span>
|
||||
)}
|
||||
{post_view.creator_blocked && (
|
||||
|
@ -900,7 +901,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{this.canAdmin && (
|
||||
<>
|
||||
{!this.isAdmin &&
|
||||
(!post_view.creator.banned ? (
|
||||
(!isBanned(post_view.creator) ? (
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted py-0"
|
||||
onClick={linkEvent(this, this.handleModBanShow)}
|
||||
|
@ -917,7 +918,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{i18n.t("unban_from_site")}
|
||||
</button>
|
||||
))}
|
||||
{!post_view.creator.banned && post_view.creator.local && (
|
||||
{!isBanned(post_view.creator) && post_view.creator.local && (
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted py-0"
|
||||
onClick={linkEvent(this, this.handleAddAdmin)}
|
||||
|
@ -1013,7 +1014,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
)}
|
||||
{this.state.showBanDialog && (
|
||||
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
|
||||
<div class="form-group row">
|
||||
<div class="form-group row col-12">
|
||||
<label class="col-form-label" htmlFor="post-listing-ban-reason">
|
||||
{i18n.t("reason")}
|
||||
</label>
|
||||
|
@ -1025,6 +1026,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
value={this.state.banReason}
|
||||
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
||||
/>
|
||||
<label class="col-form-label" htmlFor={`mod-ban-expires`}>
|
||||
{i18n.t("expires")}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id={`mod-ban-expires`}
|
||||
class="form-control mr-2"
|
||||
placeholder={i18n.t("number_of_days")}
|
||||
value={this.state.banExpireDays}
|
||||
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
||||
/>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
|
@ -1496,8 +1508,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleModBanExpiresChange(i: PostListing, event: any) {
|
||||
i.state.banExpires = event.target.value;
|
||||
handleModBanExpireDaysChange(i: PostListing, event: any) {
|
||||
i.state.banExpireDays = event.target.value;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
|
@ -1528,7 +1540,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
ban,
|
||||
remove_data: i.state.removeData,
|
||||
reason: i.state.banReason,
|
||||
expires: getUnixTime(i.state.banExpires),
|
||||
expires: futureDaysToUnixTime(i.state.banExpireDays),
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.banFromCommunity(form));
|
||||
|
@ -1543,7 +1555,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
ban,
|
||||
remove_data: i.state.removeData,
|
||||
reason: i.state.banReason,
|
||||
expires: getUnixTime(i.state.banExpires),
|
||||
expires: futureDaysToUnixTime(i.state.banExpireDays),
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.banPerson(form));
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
ListingType,
|
||||
MyUserInfo,
|
||||
PersonBlockView,
|
||||
PersonSafe,
|
||||
PersonViewSafe,
|
||||
PostReportView,
|
||||
PostView,
|
||||
|
@ -285,6 +286,14 @@ export function getUnixTime(text: string): number {
|
|||
return text ? new Date(text).getTime() / 1000 : undefined;
|
||||
}
|
||||
|
||||
export function futureDaysToUnixTime(days: number): number {
|
||||
return days
|
||||
? Math.trunc(
|
||||
new Date(Date.now() + 1000 * 60 * 60 * 24 * days).getTime() / 1000
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function canMod(
|
||||
myUserInfo: MyUserInfo,
|
||||
modIds: number[],
|
||||
|
@ -1517,3 +1526,16 @@ const SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", {
|
|||
export function numToSI(value: number): string {
|
||||
return SHORTNUM_SI_FORMAT.format(value);
|
||||
}
|
||||
|
||||
export function isBanned(ps: PersonSafe): boolean {
|
||||
// Add Z to convert from UTC date
|
||||
if (ps.ban_expires) {
|
||||
if (ps.banned && new Date(ps.ban_expires + "Z") > new Date()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return ps.banned;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue