Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3388668
D8593.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D8593.diff
View Options
diff --git a/web/components/community-actions-menu.react.js b/web/components/community-actions-menu.react.js
--- a/web/components/community-actions-menu.react.js
+++ b/web/components/community-actions-menu.react.js
@@ -16,6 +16,7 @@
import ManageInviteLinksModal from '../invite-links/manage-invite-links-modal.react.js';
import ViewInviteLinkModal from '../invite-links/view-invite-link-modal.react.js';
import { useSelector } from '../redux/redux-utils.js';
+import CommunityRolesModal from '../roles/community-roles-modal.react.js';
import { AddLink } from '../vectors.react.js';
type Props = {
@@ -52,7 +53,10 @@
pushModal(<ManageInviteLinksModal communityID={communityID} />);
}, [communityID, pushModal]);
- const openCommunityRolesModal = React.useCallback(() => {}, []);
+ const openCommunityRolesModal = React.useCallback(
+ () => pushModal(<CommunityRolesModal community={community} />),
+ [community, pushModal],
+ );
const items = React.useMemo(() => {
const itemSpecs = [];
diff --git a/web/roles/community-roles-modal.css b/web/roles/community-roles-modal.css
new file mode 100644
--- /dev/null
+++ b/web/roles/community-roles-modal.css
@@ -0,0 +1,52 @@
+.modalDescription {
+ color: var(--modal-fg);
+ padding: 16px 32px 0 32px;
+ font-size: var(--m-font-16);
+}
+
+.rolePanelTitleContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin: 32px 32px 16px 32px;
+}
+
+.rolePanelTitle {
+ color: var(--community-roles-text-color);
+ font-size: var(--l-font-18);
+}
+
+.rolePanelTitle:last-of-type {
+ margin-right: 32px;
+}
+
+.separator {
+ border: 0;
+ margin: 0 32px 8px 32px;
+ width: 85%;
+ align-self: center;
+ height: 2px;
+ border: none;
+ border-top: var(--modal-separator) solid 1px;
+}
+
+.rolePanelList {
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ max-height: 400px;
+ margin: 0 32px 16px 24px;
+}
+
+.createRoleButtonContainer {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-self: center;
+ align-items: stretch;
+ margin-bottom: 16px;
+}
+
+.createRoleButton {
+ margin: 0 32px 0 32px;
+}
diff --git a/web/roles/community-roles-modal.react.js b/web/roles/community-roles-modal.react.js
new file mode 100644
--- /dev/null
+++ b/web/roles/community-roles-modal.react.js
@@ -0,0 +1,82 @@
+// @flow
+
+import * as React from 'react';
+
+import { useModalContext } from 'lib/components/modal-provider.react.js';
+import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
+import { useRoleMemberCountsForCommunity } from 'lib/shared/thread-utils.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
+
+import css from './community-roles-modal.css';
+import RolePanelEntry from './role-panel-entry.react.js';
+import Button, { buttonThemes } from '../components/button.react.js';
+import Modal from '../modals/modal.react.js';
+import { useSelector } from '../redux/redux-utils.js';
+
+type CommunityRolesModalProps = {
+ +community: ThreadInfo,
+};
+
+function CommunityRolesModal(props: CommunityRolesModalProps): React.Node {
+ const { popModal } = useModalContext();
+ const { community } = props;
+
+ const [threadInfo, setThreadInfo] = React.useState<ThreadInfo>(community);
+ const threadID = threadInfo.id;
+ const reduxThreadInfo: ?ThreadInfo = useSelector(
+ state => threadInfoSelector(state)[threadID],
+ );
+
+ React.useEffect(() => {
+ if (reduxThreadInfo) {
+ setThreadInfo(reduxThreadInfo);
+ }
+ }, [reduxThreadInfo]);
+
+ const roleNamesToMembers = useRoleMemberCountsForCommunity(threadInfo);
+
+ const rolePanelList = React.useMemo(
+ () =>
+ Object.keys(roleNamesToMembers).map(roleName => (
+ <RolePanelEntry
+ key={roleName}
+ roleName={roleName}
+ memberCount={roleNamesToMembers[roleName]}
+ />
+ )),
+ [roleNamesToMembers],
+ );
+
+ const onClickCreateRole = React.useCallback(() => {}, []);
+
+ return (
+ <Modal name="Roles" onClose={popModal} size="large">
+ <div className={css.modalDescription}>
+ Roles help you group community members together and assign them certain
+ permissions. When people join the community, they are automatically
+ assigned the Members role.
+ </div>
+ <div className={css.modalDescription}>
+ Communities must always have the Admins and Members role.
+ </div>
+ <div className={css.rolePanelTitleContainer}>
+ <div className={css.rolePanelTitle}>Roles</div>
+ <div className={css.rolePanelTitle}>Members</div>
+ </div>
+ <hr className={css.separator} />
+ <div className={css.rolePanelList}>{rolePanelList}</div>
+ <div className={css.createRoleButtonContainer}>
+ <Button
+ variant="filled"
+ className={css.createRoleButton}
+ buttonColor={buttonThemes.standard}
+ onClick={onClickCreateRole}
+ >
+ Create Role
+ </Button>
+ </div>
+ </Modal>
+ );
+}
+
+export default CommunityRolesModal;
diff --git a/web/roles/role-panel-entry.css b/web/roles/role-panel-entry.css
new file mode 100644
--- /dev/null
+++ b/web/roles/role-panel-entry.css
@@ -0,0 +1,24 @@
+.rolePanelEntry {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12px;
+ color: var(--community-roles-text-color);
+ font-weight: 500;
+}
+
+.rolePanelNameEntry {
+ font-size: var(--s-font-14);
+}
+
+.rolePanelCountEntryContainer {
+ margin-right: 40px;
+ display: flex;
+ align-items: flex-end;
+}
+
+.rolePanelCountEntry {
+ font-size: var(--s-font-14);
+ margin-right: 2px;
+}
diff --git a/web/roles/role-panel-entry.react.js b/web/roles/role-panel-entry.react.js
new file mode 100644
--- /dev/null
+++ b/web/roles/role-panel-entry.react.js
@@ -0,0 +1,26 @@
+// @flow
+
+import * as React from 'react';
+
+import css from './role-panel-entry.css';
+import CommIcon from '../CommIcon.react.js';
+
+type RolePanelEntryProps = {
+ +roleName: string,
+ +memberCount: number,
+};
+
+function RolePanelEntry(props: RolePanelEntryProps): React.Node {
+ const { roleName, memberCount } = props;
+ return (
+ <div className={css.rolePanelEntry}>
+ <div className={css.rolePanelNameEntry}>{roleName}</div>
+ <div className={css.rolePanelCountEntryContainer}>
+ <div className={css.rolePanelCountEntry}>{memberCount}</div>
+ <CommIcon icon="user-filled" size={18} />
+ </div>
+ </div>
+ );
+}
+
+export default RolePanelEntry;
diff --git a/web/theme.css b/web/theme.css
--- a/web/theme.css
+++ b/web/theme.css
@@ -239,4 +239,6 @@
--change-member-role-modal-disabled-background: var(--shades-black-80);
--unsaved-changes-modal-text-color: var(--shades-white-60);
--modal-secondary-label: var(--shades-black-60);
+ --community-roles-text-color: var(--shades-white-100);
+ --modal-separator: var(--shades-black-80);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 30, 3:33 PM (21 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2601451
Default Alt Text
D8593.diff (6 KB)
Attached To
Mode
D8593: [web] Create a community roles modal to display all roles and member counts
Attached
Detach File
Event Timeline
Log In to Comment