Page MenuHomePhabricator

D7847.id26568.diff
No OneTemporary

D7847.id26568.diff

diff --git a/web/sidebar/community-creation/community-creation-modal.css b/web/sidebar/community-creation/community-creation-modal.css
--- a/web/sidebar/community-creation/community-creation-modal.css
+++ b/web/sidebar/community-creation/community-creation-modal.css
@@ -85,6 +85,13 @@
margin-top: 20px;
}
+div.createCommunityButtonContent {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 24px;
+}
+
.keyserverContainer {
display: flex;
justify-content: center;
diff --git a/web/sidebar/community-creation/community-creation-modal.react.js b/web/sidebar/community-creation/community-creation-modal.react.js
--- a/web/sidebar/community-creation/community-creation-modal.react.js
+++ b/web/sidebar/community-creation/community-creation-modal.react.js
@@ -1,16 +1,30 @@
// @flow
import * as React from 'react';
+import { useDispatch } from 'react-redux';
+import { newThread, newThreadActionTypes } from 'lib/actions/thread-actions.js';
import { useModalContext } from 'lib/components/modal-provider.react.js';
+import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
+import type { LoadingStatus } from 'lib/types/loading-types.js';
+import { threadTypes } from 'lib/types/thread-types-enum.js';
+import type { NewThreadResult } from 'lib/types/thread-types.js';
+import {
+ useDispatchActionPromise,
+ useServerCall,
+} from 'lib/utils/action-utils.js';
import css from './community-creation-modal.css';
import CommIcon from '../../CommIcon.react.js';
-import Button from '../../components/button.react.js';
+import Button, { buttonThemes } from '../../components/button.react.js';
import EnumSettingsOption from '../../components/enum-settings-option.react.js';
import UserAvatar from '../../components/user-avatar.react.js';
+import LoadingIndicator from '../../loading-indicator.react.js';
import Input from '../../modals/input.react.js';
import Modal from '../../modals/modal.react.js';
+import { updateNavInfoActionType } from '../../redux/action-types.js';
+import { useSelector } from '../../redux/redux-utils.js';
+import { nonThreadCalendarQuery } from '../../selectors/nav-selectors.js';
const announcementStatements = [
{
@@ -23,23 +37,80 @@
},
];
+const createNewCommunityLoadingStatusSelector =
+ createLoadingStatusSelector(newThreadActionTypes);
+
function CommunityCreationModal(): React.Node {
const modalContext = useModalContext();
+ const dispatch = useDispatch();
+ const dispatchActionPromise = useDispatchActionPromise();
+
+ const callNewThread = useServerCall(newThread);
+ const calendarQueryFunc = useSelector(nonThreadCalendarQuery);
+
+ const [errorMessage, setErrorMessage] = React.useState<?string>();
+
const [pendingCommunityName, setPendingCommunityName] =
React.useState<string>('');
const onChangePendingCommunityName = React.useCallback(
- (event: SyntheticEvent<HTMLInputElement>) =>
- setPendingCommunityName(event.currentTarget.value),
+ (event: SyntheticEvent<HTMLInputElement>) => {
+ setErrorMessage();
+ setPendingCommunityName(event.currentTarget.value);
+ },
[],
);
const [announcementSetting, setAnnouncementSetting] = React.useState(false);
const onAnnouncementSelected = React.useCallback(() => {
+ setErrorMessage();
setAnnouncementSetting(!announcementSetting);
}, [announcementSetting]);
+ const callCreateNewCommunity = React.useCallback(async () => {
+ const calendarQuery = calendarQueryFunc();
+
+ try {
+ const newThreadResult: NewThreadResult = await callNewThread({
+ name: pendingCommunityName,
+ type: announcementSetting
+ ? threadTypes.COMMUNITY_ANNOUNCEMENT_ROOT
+ : threadTypes.COMMUNITY_ROOT,
+ calendarQuery,
+ });
+ return newThreadResult;
+ } catch (e) {
+ setErrorMessage('Community creation failed. Please try again.');
+ throw e;
+ }
+ }, [
+ announcementSetting,
+ calendarQueryFunc,
+ callNewThread,
+ pendingCommunityName,
+ ]);
+
+ const createNewCommunity = React.useCallback(async () => {
+ setErrorMessage();
+
+ const newThreadResultPromise = callCreateNewCommunity();
+ dispatchActionPromise(newThreadActionTypes, newThreadResultPromise);
+ const newThreadResult: NewThreadResult = await newThreadResultPromise;
+
+ if (newThreadResult) {
+ const { newThreadID } = newThreadResult;
+ await dispatch({
+ type: updateNavInfoActionType,
+ payload: {
+ activeChatThreadID: newThreadID,
+ },
+ });
+
+ modalContext.popModal();
+ }
+ }, [callCreateNewCommunity, dispatch, dispatchActionPromise, modalContext]);
+
const megaphoneIcon = React.useMemo(
() => <CommIcon icon="megaphone" size={24} />,
[],
@@ -55,6 +126,23 @@
);
}
+ const createNewCommunityLoadingStatus: LoadingStatus = useSelector(
+ createNewCommunityLoadingStatusSelector,
+ );
+ let buttonContent;
+ if (createNewCommunityLoadingStatus === 'loading') {
+ buttonContent = (
+ <LoadingIndicator
+ status={createNewCommunityLoadingStatus}
+ size="medium"
+ />
+ );
+ } else if (errorMessage) {
+ buttonContent = errorMessage;
+ } else {
+ buttonContent = 'Create community';
+ }
+
return (
<Modal
name="Create a community"
@@ -99,7 +187,17 @@
/>
</div>
<div className={css.createCommunityButtonContainer}>
- <Button variant="filled">Create community</Button>
+ <Button
+ onClick={createNewCommunity}
+ variant="filled"
+ buttonColor={
+ errorMessage ? buttonThemes.danger : buttonThemes.standard
+ }
+ >
+ <div className={css.createCommunityButtonContent}>
+ {buttonContent}
+ </div>
+ </Button>
</div>
</form>
</div>

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 24, 2:47 AM (20 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2572711
Default Alt Text
D7847.id26568.diff (5 KB)

Event Timeline