diff --git a/lemmy-translations b/lemmy-translations index 0412b6b3..1e0bb992 160000 --- a/lemmy-translations +++ b/lemmy-translations @@ -1 +1 @@ -Subproject commit 0412b6b349e5e8d6ac3ed88801187833e95c72c9 +Subproject commit 1e0bb9920cda13bb128c87e85125b98ab8f319b6 diff --git a/package.json b/package.json index 7621abb5..ba0665ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "lemmy-ui", "description": "An isomorphic UI for lemmy", - "version": "0.14.5", + "version": "0.15.0-rc.6", "author": "Dessalines ", "license": "AGPL-3.0", "scripts": { @@ -72,7 +72,7 @@ "husky": "^7.0.4", "import-sort-style-module": "^6.0.0", "iso-639-1": "^2.1.10", - "lemmy-js-client": "0.14.0-rc.1", + "lemmy-js-client": "0.15.0-rc.6", "lint-staged": "^12.1.2", "mini-css-extract-plugin": "^2.4.5", "node-fetch": "^2.6.1", diff --git a/src/server/index.tsx b/src/server/index.tsx index 5bf79f17..82d0379b 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -91,7 +91,11 @@ server.get("/*", async (req, res) => { if (routeData[0] && routeData[0].error) { let errCode = routeData[0].error; console.error(errCode); - return res.redirect(`/404?err=${errCode}`); + if (errCode == "instance_is_private") { + return res.redirect(`/signup`); + } else { + return res.redirect(`/404?err=${errCode}`); + } } let isoData: IsoData = { diff --git a/src/shared/components/app/navbar.tsx b/src/shared/components/app/navbar.tsx index 2a40915d..57555410 100644 --- a/src/shared/components/app/navbar.tsx +++ b/src/shared/components/app/navbar.tsx @@ -7,6 +7,8 @@ import { GetSiteResponse, GetUnreadCount, GetUnreadCountResponse, + GetUnreadRegistrationApplicationCount, + GetUnreadRegistrationApplicationCountResponse, PrivateMessageResponse, UserOperation, } from "lemmy-js-client"; @@ -41,6 +43,7 @@ interface NavbarState { expanded: boolean; unreadInboxCount: number; unreadReportCount: number; + unreadApplicationCount: number; searchParam: string; toggleSearch: boolean; showDropdown: boolean; @@ -52,11 +55,13 @@ export class Navbar extends Component { private userSub: Subscription; private unreadInboxCountSub: Subscription; private unreadReportCountSub: Subscription; + private unreadApplicationCountSub: Subscription; private searchTextField: RefObject; emptyState: NavbarState = { isLoggedIn: !!this.props.site_res.my_user, unreadInboxCount: 0, unreadReportCount: 0, + unreadApplicationCount: 0, expanded: false, searchParam: "", toggleSearch: false, @@ -115,6 +120,11 @@ export class Navbar extends Component { UserService.Instance.unreadReportCountSub.subscribe(res => { this.setState({ unreadReportCount: res }); }); + // Subscribe to unread application count + this.unreadApplicationCountSub = + UserService.Instance.unreadApplicationCountSub.subscribe(res => { + this.setState({ unreadApplicationCount: res }); + }); } } @@ -123,6 +133,7 @@ export class Navbar extends Component { this.userSub.unsubscribe(); this.unreadInboxCountSub.unsubscribe(); this.unreadReportCountSub.unsubscribe(); + this.unreadApplicationCountSub.unsubscribe(); } updateUrl() { @@ -215,6 +226,31 @@ export class Navbar extends Component { )} + {UserService.Instance.myUserInfo?.local_user_view.person + .admin && ( + + )} )} + )} + {(!ra.admin_id || (ra.admin_id && accepted)) && ( + + )} + + ); + } + + handleApprove(i: RegistrationApplication) { + i.setState({ denyExpanded: false }); + let form: ApproveRegistrationApplication = { + id: i.props.application.registration_application.id, + deny_reason: "", + approve: true, + auth: authField(), + }; + WebSocketService.Instance.send( + wsClient.approveRegistrationApplication(form) + ); + } + + handleDeny(i: RegistrationApplication) { + if (i.state.denyExpanded) { + i.setState({ denyExpanded: false }); + let form: ApproveRegistrationApplication = { + id: i.props.application.registration_application.id, + approve: false, + deny_reason: i.state.denyReason, + auth: authField(), + }; + WebSocketService.Instance.send( + wsClient.approveRegistrationApplication(form) + ); + } else { + i.setState({ denyExpanded: true }); + } + } + + handleDenyReasonChange(val: string) { + this.state.denyReason = val; + this.setState(this.state); + } +} diff --git a/src/shared/components/common/symbols.tsx b/src/shared/components/common/symbols.tsx index 2035d3c4..d730c15e 100644 --- a/src/shared/components/common/symbols.tsx +++ b/src/shared/components/common/symbols.tsx @@ -12,6 +12,9 @@ export const SYMBOLS = ( xmlnsXlink="http://www.w3.org/1999/xlink" > + + + diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index f44d4cc0..d1451451 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -239,6 +239,7 @@ export class Home extends Component { sort: SortType.Hot, limit: 6, }; + setOptionalAuth(trendingCommunitiesForm, req.auth); promises.push(req.client.listCommunities(trendingCommunitiesForm)); return promises; diff --git a/src/shared/components/home/login.tsx b/src/shared/components/home/login.tsx index 73d7dbeb..5a61d136 100644 --- a/src/shared/components/home/login.tsx +++ b/src/shared/components/home/login.tsx @@ -185,8 +185,6 @@ export class Login extends Component { if (msg.error) { toast(i18n.t(msg.error), "danger"); this.state = this.emptyState; - // Refetch another captcha - WebSocketService.Instance.send(wsClient.getCaptcha()); this.setState(this.state); return; } else { diff --git a/src/shared/components/home/signup.tsx b/src/shared/components/home/signup.tsx index c3fcd20e..75e78561 100644 --- a/src/shared/components/home/signup.tsx +++ b/src/shared/components/home/signup.tsx @@ -17,6 +17,7 @@ import { authField, isBrowser, joinLemmyUrl, + mdToHtml, setIsoData, toast, validEmail, @@ -27,6 +28,7 @@ import { } from "../../utils"; import { HtmlTags } from "../common/html-tags"; import { Icon, Spinner } from "../common/icon"; +import { MarkdownTextArea } from "../common/markdown-textarea"; const passwordStrengthOptions: Options = [ { @@ -77,6 +79,7 @@ export class Signup extends Component { captcha_uuid: undefined, captcha_answer: undefined, honeypot: undefined, + answer: undefined, }, registerLoading: false, captcha: undefined, @@ -88,6 +91,7 @@ export class Signup extends Component { super(props, context); this.state = this.emptyState; + this.handleAnswerChange = this.handleAnswerChange.bind(this); this.parseMessage = this.parseMessage.bind(this); this.subscription = wsSubscribe(this.parseMessage); @@ -104,7 +108,13 @@ export class Signup extends Component { } get documentTitle(): string { - return `${i18n.t("login")} - ${this.state.site_view.site.name}`; + return `${this.titleName} - ${this.state.site_view.site.name}`; + } + + get titleName(): string { + return `${i18n.t( + this.state.site_view.site.private_instance ? "apply_to_join" : "sign_up" + )}`; } get isLemmyMl(): boolean { @@ -128,7 +138,7 @@ export class Signup extends Component { registerForm() { return (
-
{i18n.t("sign_up")}
+
{this.titleName}
@@ -219,6 +235,40 @@ export class Signup extends Component { + {this.state.site_view.site.require_application && ( + <> +
+
+ +
+
+
+ +
+ +
+ +
+
+ + )} + {this.state.captcha && (
- +
{ />
+ {this.state.siteForm.require_application && ( +
+ +
+ +
+
+ )}
@@ -255,6 +273,66 @@ export class SiteForm extends Component {
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+