Page MenuHomePhabricator

D8593.diff
No OneTemporary

D8593.diff

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

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)

Event Timeline