Page MenuHomePhabricator

D4310.diff
No OneTemporary

D4310.diff

diff --git a/web/components/button.react.js b/web/components/button.react.js
--- a/web/components/button.react.js
+++ b/web/components/button.react.js
@@ -5,10 +5,12 @@
import css from './button.css';
+export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'round';
+
type Props = {
+onClick: (event: SyntheticEvent<HTMLButtonElement>) => mixed,
+children: React.Node,
- +variant?: 'primary' | 'secondary' | 'danger' | 'round',
+ +variant?: ButtonVariant,
+type?: string,
+disabled?: boolean,
+className?: string,
diff --git a/web/settings/relationship/add-users-list.css b/web/settings/relationship/add-users-list.css
--- a/web/settings/relationship/add-users-list.css
+++ b/web/settings/relationship/add-users-list.css
@@ -1,5 +1,5 @@
.container {
- height: 580px;
+ height: 625px;
display: flex;
flex-direction: column;
}
@@ -8,6 +8,7 @@
display: flex;
flex-wrap: wrap;
gap: 6px;
+ margin: 8px;
}
.userRowsContainer {
@@ -15,6 +16,7 @@
display: flex;
flex-direction: column;
flex: 1;
+ margin-bottom: 8px;
}
.addUserButton {
@@ -34,3 +36,19 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+.buttons {
+ display: flex;
+ justify-content: space-between;
+}
+
+.confirmButtonContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.hidden {
+ visibility: hidden;
+ height: 0;
+}
diff --git a/web/settings/relationship/add-users-list.react.js b/web/settings/relationship/add-users-list.react.js
--- a/web/settings/relationship/add-users-list.react.js
+++ b/web/settings/relationship/add-users-list.react.js
@@ -2,24 +2,53 @@
import * as React from 'react';
+import {
+ updateRelationships,
+ updateRelationshipsActionTypes,
+} from 'lib/actions/relationship-actions.js';
import { searchUsers } from 'lib/actions/user-actions.js';
+import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { userStoreSearchIndex as userStoreSearchIndexSelector } from 'lib/selectors/user-selectors.js';
-import type { UserRelationshipStatus } from 'lib/types/relationship-types.js';
+import type {
+ UserRelationshipStatus,
+ RelationshipAction,
+} from 'lib/types/relationship-types.js';
import type { GlobalAccountUserInfo } from 'lib/types/user-types.js';
-import { useServerCall } from 'lib/utils/action-utils.js';
+import {
+ useDispatchActionPromise,
+ useServerCall,
+} from 'lib/utils/action-utils.js';
+import Button from '../../components/button.react.js';
+import type { ButtonVariant } from '../../components/button.react.js';
import Label from '../../components/label.react.js';
+import LoadingIndicator from '../../loading-indicator.react.js';
import { useSelector } from '../../redux/redux-utils.js';
import AddUsersListItem from './add-users-list-item.react.js';
import css from './add-users-list.css';
+const loadingStatusSelector = createLoadingStatusSelector(
+ updateRelationshipsActionTypes,
+);
+
type Props = {
+searchText: string,
+excludedStatuses?: $ReadOnlySet<UserRelationshipStatus>,
+ +closeModal: () => void,
+ +confirmButtonContent: React.Node,
+ +confirmButtonVariant: ButtonVariant,
+ +relationshipAction: RelationshipAction,
};
function AddUsersList(props: Props): React.Node {
- const { searchText, excludedStatuses = new Set() } = props;
+ const {
+ searchText,
+ excludedStatuses = new Set(),
+ closeModal,
+ confirmButtonContent,
+ confirmButtonVariant,
+ relationshipAction,
+ } = props;
const userStoreSearchIndex = useSelector(userStoreSearchIndexSelector);
const [userStoreSearchResults, setUserStoreSearchResults] = React.useState<
@@ -155,10 +184,52 @@
)),
[filteredUsers, selectUser],
);
+
+ const callUpdateRelationships = useServerCall(updateRelationships);
+ const dispatchActionPromise = useDispatchActionPromise();
+ const confirmSelection = React.useCallback(async () => {
+ await dispatchActionPromise(
+ updateRelationshipsActionTypes,
+ callUpdateRelationships({
+ action: relationshipAction,
+ userIDs: Array.from(pendingUserIDs),
+ }),
+ );
+ closeModal();
+ }, [
+ callUpdateRelationships,
+ dispatchActionPromise,
+ closeModal,
+ pendingUserIDs,
+ relationshipAction,
+ ]);
+ const loadingStatus = useSelector(loadingStatusSelector);
+ let buttonContent = confirmButtonContent;
+ if (loadingStatus === 'loading') {
+ buttonContent = (
+ <>
+ <div className={css.hidden}>{confirmButtonContent}</div>
+ <LoadingIndicator status="loading" />
+ </>
+ );
+ }
+
return (
<div className={css.container}>
{userTags}
<div className={css.userRowsContainer}>{userRows}</div>
+ <div className={css.buttons}>
+ <Button variant="secondary" onClick={closeModal}>
+ Cancel
+ </Button>
+ <Button
+ onClick={confirmSelection}
+ disabled={pendingUserIDs.size === 0 || loadingStatus === 'loading'}
+ variant={confirmButtonVariant}
+ >
+ <div className={css.confirmButtonContainer}>{buttonContent}</div>
+ </Button>
+ </div>
</div>
);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 19, 9:35 AM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2676589
Default Alt Text
D4310.diff (5 KB)

Event Timeline