diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index 7c8ef80b80..26f8c4a413 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -458,6 +458,8 @@ export default React.createClass({ } this.setState({ summary, + isGroupPublicised: this._groupStore.getGroupPublicity(), + isUserPrivileged: this._groupStore.isUserPrivileged(), error: null, }); }); @@ -606,22 +608,15 @@ export default React.createClass({ }); }, - _onPubliciseOffClick: function() { - this._setPublicity(false); - }, - - _onPubliciseOnClick: function() { - this._setPublicity(true); - }, - _onAddRoomsClick: function() { showGroupAddRoomDialog(this.props.groupId); }, - _setPublicity: function(publicity) { + _onPublicityToggle: function() { this.setState({ publicityBusy: true, }); + const publicity = !this.state.isGroupPublicised; this._groupStore.setGroupPublicity(publicity).then(() => { this.setState({ publicityBusy: false, @@ -745,100 +740,113 @@ export default React.createClass({ <Spinner /> </div>; } - return <div className="mx_GroupView_membershipSection mx_GroupView_membershipSection_invited"> - <div className="mx_GroupView_membershipSection_description"> - { _t("%(inviter)s has invited you to join this group", {inviter: group.inviter.userId}) } - </div> - <div className="mx_GroupView_membership_buttonContainer"> - <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" - onClick={this._onAcceptInviteClick} - > - { _t("Accept") } - </AccessibleButton> - <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" - onClick={this._onRejectInviteClick} - > - { _t("Decline") } - </AccessibleButton> - </div> - </div>; - } else if (group.myMembership === 'join') { - let youAreAMemberText = _t("You are a member of this group"); - if (this.state.summary.user && this.state.summary.user.is_privileged) { - youAreAMemberText = _t("You are an administrator of this group"); - } - - let publicisedButton; - if (this.state.publicityBusy) { - publicisedButton = <Spinner />; - } - - let publicisedSection; - if (this.state.summary.user && this.state.summary.user.is_publicised) { - if (!this.state.publicityBusy) { - publicisedButton = <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" - onClick={this._onPubliciseOffClick} - > - { _t("Unpublish") } - </AccessibleButton>; - } - publicisedSection = <div className="mx_GroupView_membershipSubSection"> - { _t("This group is published on your profile") } - <div className="mx_GroupView_membership_buttonContainer"> - { publicisedButton } - </div> - </div>; - } else { - if (!this.state.publicityBusy) { - publicisedButton = <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" - onClick={this._onPubliciseOnClick} - > - { _t("Publish") } - </AccessibleButton>; - } - publicisedSection = <div className="mx_GroupView_membershipSubSection"> - { _t("This group is not published on your profile") } - <div className="mx_GroupView_membership_buttonContainer"> - { publicisedButton } - </div> - </div>; - } - - return <div className="mx_GroupView_membershipSection mx_GroupView_membershipSection_joined"> <div className="mx_GroupView_membershipSubSection"> <div className="mx_GroupView_membershipSection_description"> - { youAreAMemberText } + { _t("%(inviter)s has invited you to join this group", {inviter: group.inviter.userId}) } </div> <div className="mx_GroupView_membership_buttonContainer"> <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" + onClick={this._onAcceptInviteClick} + > + { _t("Accept") } + </AccessibleButton> + <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" + onClick={this._onRejectInviteClick} + > + { _t("Decline") } + </AccessibleButton> + </div> + </div> + </div>; + } else if (group.myMembership === 'join' && this.state.editing) { + const leaveButtonTooltip = this.state.isUserPrivileged ? + _t("You are a member of this group") : + _t("You are an administrator of this group"); + const leaveButtonClasses = classnames({ + "mx_RoomHeader_textButton": true, + "mx_GroupView_textButton": true, + "mx_GroupView_leaveButton": true, + "mx_RoomHeader_textButton_danger": this.state.isUserPrivileged, + }); + return <div className="mx_GroupView_membershipSection mx_GroupView_membershipSection_joined"> + <div className="mx_GroupView_membershipSubSection"> + { /* Empty div for flex alignment */ } + <div /> + <div className="mx_GroupView_membership_buttonContainer"> + <AccessibleButton + className={leaveButtonClasses} onClick={this._onLeaveClick} + title={leaveButtonTooltip} > { _t("Leave") } </AccessibleButton> </div> </div> - { publicisedSection } </div>; } - return null; }, + _getMemberSettingsSection: function() { + return <div className="mx_GroupView_memberSettings"> + <h3> { _t("Community Member Settings") } </h3> + <div className="mx_GroupView_memberSettings_toggle"> + <input type="checkbox" + onClick={this._onPublicityToggle} + checked={this.state.isGroupPublicised} + tabIndex="3" + id="isGroupPublicised" + /> + <label htmlFor="isGroupPublicised" + onClick={this._onPublicityToggle} + > + { _t("Publish this community on your profile") } + </label> + </div> + </div>; + }, + + _getLongDescriptionNode: function() { + const summary = this.state.summary; + let description = null; + if (summary.profile && summary.profile.long_description) { + description = sanitizedHtmlNode(summary.profile.long_description); + } + return this.state.editing && this.state.isUserPrivileged ? + <div className="mx_GroupView_groupDesc"> + <h3> { _t("Long Description (HTML)") } </h3> + <textarea + value={this.state.profileForm.long_description} + onChange={this._onLongDescChange} + tabIndex="4" + key="editLongDesc" + /> + </div> : + <div className="mx_GroupView_groupDesc"> + { description } + </div>; + }, + render: function() { const GroupAvatar = sdk.getComponent("avatars.GroupAvatar"); - const Loader = sdk.getComponent("elements.Spinner"); + const Spinner = sdk.getComponent("elements.Spinner"); const TintableSvg = sdk.getComponent("elements.TintableSvg"); if (this.state.summary === null && this.state.error === null || this.state.saving) { - return <Loader />; + return <Spinner />; } else if (this.state.summary) { const summary = this.state.summary; let avatarNode; let nameNode; let shortDescNode; - let bodyNodes = []; + const bodyNodes = [ + this._getMembershipSection(), + this.state.editing ? this._getMemberSettingsSection() : null, + this._getLongDescriptionNode(), + this._getRoomsNode(), + ]; const rightButtons = []; const headerClasses = { mx_GroupView_header: true, @@ -846,7 +854,7 @@ export default React.createClass({ if (this.state.editing) { let avatarImage; if (this.state.uploadingAvatar) { - avatarImage = <Loader />; + avatarImage = <Spinner />; } else { const GroupAvatar = sdk.getComponent('avatars.GroupAvatar'); avatarImage = <GroupAvatar groupId={this.props.groupId} @@ -895,15 +903,6 @@ export default React.createClass({ width="18" height="18" alt={_t("Cancel")} /> </AccessibleButton>, ); - bodyNodes = [ - <textarea className="mx_GroupView_editLongDesc" - value={this.state.profileForm.long_description} - onChange={this._onLongDescChange} - tabIndex="3" - key="editLongDesc" - />, - this._getRoomsNode(), - ]; } else { const groupAvatarUrl = summary.profile ? summary.profile.avatar_url : null; avatarNode = <GroupAvatar @@ -924,25 +923,13 @@ export default React.createClass({ if (summary.profile && summary.profile.short_description) { shortDescNode = <span>{ summary.profile.short_description }</span>; } - - let description = null; - if (summary.profile && summary.profile.long_description) { - description = sanitizedHtmlNode(summary.profile.long_description); - } - bodyNodes = [ - this._getMembershipSection(), - <div key="groupDesc" className="mx_GroupView_groupDesc">{ description }</div>, - this._getRoomsNode(), - ]; - if (summary.user && summary.user.is_privileged) { - rightButtons.push( - <AccessibleButton className="mx_GroupHeader_button" - onClick={this._onEditClick} title={_t("Edit Group")} key="_editButton" - > - <TintableSvg src="img/icons-settings-room.svg" width="16" height="16" /> - </AccessibleButton>, - ); - } + rightButtons.push( + <AccessibleButton className="mx_GroupHeader_button" + onClick={this._onEditClick} title={_t("Community Settings")} key="_editButton" + > + <TintableSvg src="img/icons-settings-room.svg" width="16" height="16" /> + </AccessibleButton>, + ); if (this.props.collapsedRhs) { rightButtons.push( <AccessibleButton className="mx_GroupHeader_button" diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a28e532073..53abbb5584 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -927,5 +927,9 @@ "%(serverName)s Matrix ID": "%(serverName)s Matrix ID", "Add rooms to this group": "Add rooms to this group", "Invites sent": "Invites sent", - "Your group invitations have been sent.": "Your group invitations have been sent." + "Your group invitations have been sent.": "Your group invitations have been sent.", + "Publish this community on your profile": "Publish this community on your profile", + "Community Member Settings": "Community Member Settings", + "Long Description (HTML)": "Long Description (HTML)", + "Community Settings": "Community Settings" } diff --git a/src/stores/GroupStore.js b/src/stores/GroupStore.js index 73118993f9..c1ef4619cd 100644 --- a/src/stores/GroupStore.js +++ b/src/stores/GroupStore.js @@ -61,6 +61,14 @@ export default class GroupStore extends EventEmitter { return this._rooms; } + getGroupPublicity() { + return this._summary.user ? this._summary.user.is_publicised : null; + } + + isUserPrivileged() { + return this._summary.user ? this._summary.user.is_privileged : null; + } + addRoomToGroup(roomId) { return this._matrixClient .addRoomToGroup(this.groupId, roomId)