mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-24 10:21:01 +00:00
Adding some site oriented settings.
- Adding option to close registration. Fixes #350 - Adding option to disable showing NSFW buttons. Fixes #364 - Adding option to disable downvotes. Fixes #239
This commit is contained in:
parent
688378aa5a
commit
aee6ee5a7c
25 changed files with 349 additions and 167 deletions
16
server/migrations/2019-12-11-181820_add_site_fields/down.sql
vendored
Normal file
16
server/migrations/2019-12-11-181820_add_site_fields/down.sql
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
-- Drop the columns
|
||||
drop view site_view;
|
||||
alter table site drop column enable_downvotes;
|
||||
alter table site drop column open_registration;
|
||||
alter table site drop column enable_nsfw;
|
||||
|
||||
-- Rebuild the views
|
||||
|
||||
create view site_view as
|
||||
select *,
|
||||
(select name from user_ u where s.creator_id = u.id) as creator_name,
|
||||
(select count(*) from user_) as number_of_users,
|
||||
(select count(*) from post) as number_of_posts,
|
||||
(select count(*) from comment) as number_of_comments,
|
||||
(select count(*) from community) as number_of_communities
|
||||
from site s;
|
16
server/migrations/2019-12-11-181820_add_site_fields/up.sql
vendored
Normal file
16
server/migrations/2019-12-11-181820_add_site_fields/up.sql
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
-- Add the column
|
||||
alter table site add column enable_downvotes boolean default true not null;
|
||||
alter table site add column open_registration boolean default true not null;
|
||||
alter table site add column enable_nsfw boolean default true not null;
|
||||
|
||||
-- Reload the view
|
||||
drop view site_view;
|
||||
|
||||
create view site_view as
|
||||
select *,
|
||||
(select name from user_ u where s.creator_id = u.id) as creator_name,
|
||||
(select count(*) from user_) as number_of_users,
|
||||
(select count(*) from post) as number_of_posts,
|
||||
(select count(*) from comment) as number_of_comments,
|
||||
(select count(*) from community) as number_of_communities
|
||||
from site s;
|
|
@ -298,6 +298,14 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
|
|||
|
||||
let user_id = claims.id;
|
||||
|
||||
// Don't do a downvote if site has downvotes disabled
|
||||
if data.score == -1 {
|
||||
let site = SiteView::read(&conn)?;
|
||||
if site.enable_downvotes == false {
|
||||
return Err(APIError::err(&self.op, "downvotes_disabled"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a community ban
|
||||
let post = Post::read(&conn, data.post_id)?;
|
||||
if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::db::moderator_views::*;
|
|||
use crate::db::password_reset_request::*;
|
||||
use crate::db::post::*;
|
||||
use crate::db::post_view::*;
|
||||
use crate::db::site::*;
|
||||
use crate::db::site_view::*;
|
||||
use crate::db::user::*;
|
||||
use crate::db::user_mention::*;
|
||||
use crate::db::user_mention_view::*;
|
||||
|
|
|
@ -265,6 +265,14 @@ impl Perform<CreatePostLikeResponse> for Oper<CreatePostLike> {
|
|||
|
||||
let user_id = claims.id;
|
||||
|
||||
// Don't do a downvote if site has downvotes disabled
|
||||
if data.score == -1 {
|
||||
let site = SiteView::read(&conn)?;
|
||||
if site.enable_downvotes == false {
|
||||
return Err(APIError::err(&self.op, "downvotes_disabled"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a community ban
|
||||
let post = Post::read(&conn, data.post_id)?;
|
||||
if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
|
||||
|
|
|
@ -56,6 +56,9 @@ pub struct GetModlogResponse {
|
|||
pub struct CreateSite {
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
enable_downvotes: bool,
|
||||
open_registration: bool,
|
||||
enable_nsfw: bool,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
|
@ -63,6 +66,9 @@ pub struct CreateSite {
|
|||
pub struct EditSite {
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
enable_downvotes: bool,
|
||||
open_registration: bool,
|
||||
enable_nsfw: bool,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
|
@ -208,6 +214,9 @@ impl Perform<SiteResponse> for Oper<CreateSite> {
|
|||
name: data.name.to_owned(),
|
||||
description: data.description.to_owned(),
|
||||
creator_id: user_id,
|
||||
enable_downvotes: data.enable_downvotes,
|
||||
open_registration: data.open_registration,
|
||||
enable_nsfw: data.enable_nsfw,
|
||||
updated: None,
|
||||
};
|
||||
|
||||
|
@ -255,6 +264,9 @@ impl Perform<SiteResponse> for Oper<EditSite> {
|
|||
description: data.description.to_owned(),
|
||||
creator_id: found_site.creator_id,
|
||||
updated: Some(naive_now()),
|
||||
enable_downvotes: data.enable_downvotes,
|
||||
open_registration: data.open_registration,
|
||||
enable_nsfw: data.enable_nsfw,
|
||||
};
|
||||
|
||||
match Site::update(&conn, 1, &site_form) {
|
||||
|
@ -431,6 +443,9 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
|
|||
description: read_site.description,
|
||||
creator_id: data.user_id,
|
||||
updated: Some(naive_now()),
|
||||
enable_downvotes: read_site.enable_downvotes,
|
||||
open_registration: read_site.open_registration,
|
||||
enable_nsfw: read_site.enable_nsfw,
|
||||
};
|
||||
|
||||
match Site::update(&conn, 1, &site_form) {
|
||||
|
|
|
@ -193,6 +193,13 @@ impl Perform<LoginResponse> for Oper<Register> {
|
|||
let data: &Register = &self.data;
|
||||
let conn = establish_connection();
|
||||
|
||||
// Make sure site has open registration
|
||||
if let Ok(site) = SiteView::read(&conn) {
|
||||
if !site.open_registration {
|
||||
return Err(APIError::err(&self.op, "registration_closed"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure passwords match
|
||||
if &data.password != &data.password_verify {
|
||||
return Err(APIError::err(&self.op, "passwords_dont_match"))?;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::*;
|
||||
use crate::schema::{community, community_follower, community_moderator, community_user_ban, site};
|
||||
use crate::schema::{community, community_follower, community_moderator, community_user_ban};
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[table_name = "community"]
|
||||
|
@ -202,50 +202,6 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[table_name = "site"]
|
||||
pub struct Site {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize)]
|
||||
#[table_name = "site"]
|
||||
pub struct SiteForm {
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
}
|
||||
|
||||
impl Crud<SiteForm> for Site {
|
||||
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
site.first::<Self>(conn)
|
||||
}
|
||||
|
||||
fn delete(conn: &PgConnection, site_id: i32) -> Result<usize, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
diesel::delete(site.find(site_id)).execute(conn)
|
||||
}
|
||||
|
||||
fn create(conn: &PgConnection, new_site: &SiteForm) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
insert_into(site).values(new_site).get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
fn update(conn: &PgConnection, site_id: i32, new_site: &SiteForm) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
diesel::update(site.find(site_id))
|
||||
.set(new_site)
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::user::*;
|
||||
|
|
|
@ -59,22 +59,6 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
site_view (id) {
|
||||
id -> Int4,
|
||||
name -> Varchar,
|
||||
description -> Nullable<Text>,
|
||||
creator_id -> Int4,
|
||||
published -> Timestamp,
|
||||
updated -> Nullable<Timestamp>,
|
||||
creator_name -> Varchar,
|
||||
number_of_users -> BigInt,
|
||||
number_of_posts -> BigInt,
|
||||
number_of_comments -> BigInt,
|
||||
number_of_communities -> BigInt,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
|
||||
)]
|
||||
|
@ -328,28 +312,3 @@ impl CommunityUserBanView {
|
|||
.first::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
|
||||
)]
|
||||
#[table_name = "site_view"]
|
||||
pub struct SiteView {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub creator_name: String,
|
||||
pub number_of_users: i64,
|
||||
pub number_of_posts: i64,
|
||||
pub number_of_comments: i64,
|
||||
pub number_of_communities: i64,
|
||||
}
|
||||
|
||||
impl SiteView {
|
||||
pub fn read(conn: &PgConnection) -> Result<Self, Error> {
|
||||
use super::community_view::site_view::dsl::*;
|
||||
site_view.first::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ pub mod moderator_views;
|
|||
pub mod password_reset_request;
|
||||
pub mod post;
|
||||
pub mod post_view;
|
||||
pub mod site;
|
||||
pub mod site_view;
|
||||
pub mod user;
|
||||
pub mod user_mention;
|
||||
pub mod user_mention_view;
|
||||
|
|
52
server/src/db/site.rs
Normal file
52
server/src/db/site.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use super::*;
|
||||
use crate::schema::site;
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[table_name = "site"]
|
||||
pub struct Site {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub enable_downvotes: bool,
|
||||
pub open_registration: bool,
|
||||
pub enable_nsfw: bool,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize)]
|
||||
#[table_name = "site"]
|
||||
pub struct SiteForm {
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub enable_downvotes: bool,
|
||||
pub open_registration: bool,
|
||||
pub enable_nsfw: bool,
|
||||
}
|
||||
|
||||
impl Crud<SiteForm> for Site {
|
||||
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
site.first::<Self>(conn)
|
||||
}
|
||||
|
||||
fn delete(conn: &PgConnection, site_id: i32) -> Result<usize, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
diesel::delete(site.find(site_id)).execute(conn)
|
||||
}
|
||||
|
||||
fn create(conn: &PgConnection, new_site: &SiteForm) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
insert_into(site).values(new_site).get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
fn update(conn: &PgConnection, site_id: i32, new_site: &SiteForm) -> Result<Self, Error> {
|
||||
use crate::schema::site::dsl::*;
|
||||
diesel::update(site.find(site_id))
|
||||
.set(new_site)
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
}
|
48
server/src/db/site_view.rs
Normal file
48
server/src/db/site_view.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
use super::*;
|
||||
|
||||
table! {
|
||||
site_view (id) {
|
||||
id -> Int4,
|
||||
name -> Varchar,
|
||||
description -> Nullable<Text>,
|
||||
creator_id -> Int4,
|
||||
published -> Timestamp,
|
||||
updated -> Nullable<Timestamp>,
|
||||
enable_downvotes -> Bool,
|
||||
open_registration -> Bool,
|
||||
enable_nsfw -> Bool,
|
||||
creator_name -> Varchar,
|
||||
number_of_users -> BigInt,
|
||||
number_of_posts -> BigInt,
|
||||
number_of_comments -> BigInt,
|
||||
number_of_communities -> BigInt,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
|
||||
)]
|
||||
#[table_name = "site_view"]
|
||||
pub struct SiteView {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub enable_downvotes: bool,
|
||||
pub open_registration: bool,
|
||||
pub enable_nsfw: bool,
|
||||
pub creator_name: String,
|
||||
pub number_of_users: i64,
|
||||
pub number_of_posts: i64,
|
||||
pub number_of_comments: i64,
|
||||
pub number_of_communities: i64,
|
||||
}
|
||||
|
||||
impl SiteView {
|
||||
pub fn read(conn: &PgConnection) -> Result<Self, Error> {
|
||||
use super::site_view::site_view::dsl::*;
|
||||
site_view.first::<Self>(conn)
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@ extern crate rss;
|
|||
use super::*;
|
||||
use crate::db::comment_view::{ReplyQueryBuilder, ReplyView};
|
||||
use crate::db::community::Community;
|
||||
use crate::db::community_view::SiteView;
|
||||
use crate::db::post_view::{PostQueryBuilder, PostView};
|
||||
use crate::db::site_view::SiteView;
|
||||
use crate::db::user::User_;
|
||||
use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView};
|
||||
use crate::db::{establish_connection, ListingType, SortType};
|
||||
|
|
|
@ -118,7 +118,7 @@ impl Settings {
|
|||
.unwrap_or("3600".to_string())
|
||||
.parse()
|
||||
.unwrap(),
|
||||
email_config: email_config,
|
||||
email_config,
|
||||
}
|
||||
}
|
||||
fn api_endpoint(&self) -> String {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::db::community_view::SiteView;
|
||||
use crate::db::establish_connection;
|
||||
use crate::db::site_view::SiteView;
|
||||
use crate::version;
|
||||
use crate::Settings;
|
||||
use actix_web::body::Body;
|
||||
|
|
|
@ -246,6 +246,9 @@ table! {
|
|||
creator_id -> Int4,
|
||||
published -> Timestamp,
|
||||
updated -> Nullable<Timestamp>,
|
||||
enable_downvotes -> Bool,
|
||||
open_registration -> Bool,
|
||||
enable_nsfw -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
ui/src/components/comment-node.tsx
vendored
22
ui/src/components/comment-node.tsx
vendored
|
@ -102,16 +102,18 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
<div class={`font-weight-bold text-muted`}>
|
||||
{node.comment.score}
|
||||
</div>
|
||||
<button
|
||||
className={`btn p-0 ${
|
||||
node.comment.my_vote == -1 ? 'text-danger' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(node, this.handleCommentDisLike)}
|
||||
>
|
||||
<svg class="icon downvote">
|
||||
<use xlinkHref="#icon-arrow-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
{WebSocketService.Instance.site.enable_downvotes && (
|
||||
<button
|
||||
className={`btn p-0 ${
|
||||
node.comment.my_vote == -1 ? 'text-danger' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(node, this.handleCommentDisLike)}
|
||||
>
|
||||
<svg class="icon downvote">
|
||||
<use xlinkHref="#icon-arrow-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
|
|
29
ui/src/components/community-form.tsx
vendored
29
ui/src/components/community-form.tsx
vendored
|
@ -156,21 +156,24 @@ export class CommunityForm extends Component<
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.communityForm.nsfw}
|
||||
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="nsfw">#</T>
|
||||
</label>
|
||||
|
||||
{WebSocketService.Instance.site.enable_nsfw && (
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.communityForm.nsfw}
|
||||
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="nsfw">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-secondary mr-2">
|
||||
|
|
28
ui/src/components/login.tsx
vendored
28
ui/src/components/login.tsx
vendored
|
@ -205,21 +205,23 @@ export class Login extends Component<any, State> {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.registerForm.show_nsfw}
|
||||
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="show_nsfw">#</T>
|
||||
</label>
|
||||
{WebSocketService.Instance.site.enable_nsfw && (
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.registerForm.show_nsfw}
|
||||
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="show_nsfw">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-secondary">
|
||||
|
|
28
ui/src/components/post-form.tsx
vendored
28
ui/src/components/post-form.tsx
vendored
|
@ -280,21 +280,23 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.postForm.nsfw}
|
||||
onChange={linkEvent(this, this.handlePostNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="nsfw">#</T>
|
||||
</label>
|
||||
{WebSocketService.Instance.site.enable_nsfw && (
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.postForm.nsfw}
|
||||
onChange={linkEvent(this, this.handlePostNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="nsfw">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-secondary mr-2">
|
||||
|
|
22
ui/src/components/post-listing.tsx
vendored
22
ui/src/components/post-listing.tsx
vendored
|
@ -114,16 +114,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</svg>
|
||||
</button>
|
||||
<div class={`font-weight-bold text-muted`}>{post.score}</div>
|
||||
<button
|
||||
className={`btn p-0 ${
|
||||
post.my_vote == -1 ? 'text-danger' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(this, this.handlePostDisLike)}
|
||||
>
|
||||
<svg class="icon downvote">
|
||||
<use xlinkHref="#icon-arrow-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
{WebSocketService.Instance.site.enable_downvotes && (
|
||||
<button
|
||||
className={`btn p-0 ${
|
||||
post.my_vote == -1 ? 'text-danger' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(this, this.handlePostDisLike)}
|
||||
>
|
||||
<svg class="icon downvote">
|
||||
<use xlinkHref="#icon-arrow-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{post.url && isImage(post.url) && !post.nsfw && !post.community_nsfw && (
|
||||
<span
|
||||
|
|
69
ui/src/components/site-form.tsx
vendored
69
ui/src/components/site-form.tsx
vendored
|
@ -19,6 +19,9 @@ interface SiteFormState {
|
|||
export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||
private emptyState: SiteFormState = {
|
||||
siteForm: {
|
||||
enable_downvotes: true,
|
||||
open_registration: true,
|
||||
enable_nsfw: true,
|
||||
name: null,
|
||||
},
|
||||
loading: false,
|
||||
|
@ -31,6 +34,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
|||
this.state.siteForm = {
|
||||
name: this.props.site.name,
|
||||
description: this.props.site.description,
|
||||
enable_downvotes: this.props.site.enable_downvotes,
|
||||
open_registration: this.props.site.open_registration,
|
||||
enable_nsfw: this.props.site.enable_nsfw,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +83,54 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.siteForm.enable_downvotes}
|
||||
onChange={linkEvent(this, this.handleSiteEnableDownvotesChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="enable_downvotes">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.siteForm.enable_nsfw}
|
||||
onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="enable_nsfw">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.siteForm.open_registration}
|
||||
onChange={linkEvent(
|
||||
this,
|
||||
this.handleSiteOpenRegistrationChange
|
||||
)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="open_registration">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-secondary mr-2">
|
||||
|
@ -126,6 +180,21 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleSiteEnableNsfwChange(i: SiteForm, event: any) {
|
||||
i.state.siteForm.enable_nsfw = event.target.checked;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
|
||||
i.state.siteForm.open_registration = event.target.checked;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
|
||||
i.state.siteForm.enable_downvotes = event.target.checked;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleCancel(i: SiteForm) {
|
||||
i.props.onCancel();
|
||||
}
|
||||
|
|
34
ui/src/components/user.tsx
vendored
34
ui/src/components/user.tsx
vendored
|
@ -496,24 +496,26 @@ export class User extends Component<any, UserState> {
|
|||
/>
|
||||
</div>
|
||||
</form>
|
||||
<div class="form-group">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.userSettingsForm.show_nsfw}
|
||||
onChange={linkEvent(
|
||||
this,
|
||||
this.handleUserSettingsShowNsfwChange
|
||||
)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="show_nsfw">#</T>
|
||||
</label>
|
||||
{WebSocketService.Instance.site.enable_nsfw && (
|
||||
<div class="form-group">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
checked={this.state.userSettingsForm.show_nsfw}
|
||||
onChange={linkEvent(
|
||||
this,
|
||||
this.handleUserSettingsShowNsfwChange
|
||||
)}
|
||||
/>
|
||||
<label class="form-check-label">
|
||||
<T i18nKey="show_nsfw">#</T>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div class="form-group">
|
||||
<div class="col-12">
|
||||
<button
|
||||
|
|
9
ui/src/interfaces.ts
vendored
9
ui/src/interfaces.ts
vendored
|
@ -199,6 +199,9 @@ export interface Site {
|
|||
number_of_posts: number;
|
||||
number_of_comments: number;
|
||||
number_of_communities: number;
|
||||
enable_downvotes: boolean;
|
||||
open_registration: boolean;
|
||||
enable_nsfw: boolean;
|
||||
}
|
||||
|
||||
export enum BanType {
|
||||
|
@ -625,9 +628,9 @@ export interface CreatePostLikeResponse {
|
|||
export interface SiteForm {
|
||||
name: string;
|
||||
description?: string;
|
||||
removed?: boolean;
|
||||
reason?: string;
|
||||
expires?: number;
|
||||
enable_downvotes: boolean;
|
||||
open_registration: boolean;
|
||||
enable_nsfw: boolean;
|
||||
auth?: string;
|
||||
}
|
||||
|
||||
|
|
5
ui/src/translations/en.ts
vendored
5
ui/src/translations/en.ts
vendored
|
@ -127,6 +127,11 @@ export const en = {
|
|||
expires: 'Expires',
|
||||
language: 'Language',
|
||||
browser_default: 'Browser Default',
|
||||
downvotes_disabled: 'Downvotes disabled',
|
||||
enable_downvotes: 'Enable Downvotes',
|
||||
open_registration: 'Open Registration',
|
||||
registration_closed: 'Registration closed',
|
||||
enable_nsfw: 'Enable NSFW',
|
||||
url: 'URL',
|
||||
body: 'Body',
|
||||
copy_suggested_title: 'copy suggested title: {{title}}',
|
||||
|
|
Loading…
Reference in a new issue