mirror of
https://github.com/ilyakooo0/urbit.git
synced 2025-01-06 23:16:29 +03:00
Merge pull request #3171 from urbit/mp/toggle-public
groups: add private group toggle
This commit is contained in:
commit
3f78392c2c
@ -6,6 +6,7 @@ import { Spinner } from '../../../components/Spinner';
|
|||||||
import { ChatTabBar } from './lib/chat-tabbar';
|
import { ChatTabBar } from './lib/chat-tabbar';
|
||||||
import { InviteSearch } from '../../../components/InviteSearch';
|
import { InviteSearch } from '../../../components/InviteSearch';
|
||||||
import SidebarSwitcher from '../../../components/SidebarSwitch';
|
import SidebarSwitcher from '../../../components/SidebarSwitch';
|
||||||
|
import Toggle from '../../../components/toggle';
|
||||||
|
|
||||||
export class SettingsScreen extends Component {
|
export class SettingsScreen extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -195,18 +196,12 @@ export class SettingsScreen extends Component {
|
|||||||
} else {
|
} else {
|
||||||
let inclusiveToggle = <div />;
|
let inclusiveToggle = <div />;
|
||||||
if (state.targetGroup) {
|
if (state.targetGroup) {
|
||||||
// TODO toggle component into /lib
|
|
||||||
const inclusiveClasses = state.inclusive
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
inclusiveToggle = (
|
inclusiveToggle = (
|
||||||
<div className="mt4">
|
<div className="mt4">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={state.inclusive}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeInclusive}
|
||||||
className={inclusiveClasses}
|
/>
|
||||||
onChange={this.changeInclusive}
|
|
||||||
/>
|
|
||||||
<span className="dib f9 white-d inter ml3">
|
<span className="dib f9 white-d inter ml3">
|
||||||
Add all members to group
|
Add all members to group
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Spinner } from '../../../../components/Spinner';
|
import { Spinner } from '../../../../components/Spinner';
|
||||||
|
import { Toggle } from '../../../../components/toggle';
|
||||||
import { GroupView } from '../../../../components/Group';
|
import { GroupView } from '../../../../components/Group';
|
||||||
import { deSig, uxToHex, writeText } from '../../../../lib/util';
|
import { deSig, uxToHex, writeText } from '../../../../lib/util';
|
||||||
|
import { roleForShip, resourceFromPath } from '../../../../lib/group';
|
||||||
|
|
||||||
export class GroupDetail extends Component {
|
export class GroupDetail extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -15,6 +17,7 @@ export class GroupDetail extends Component {
|
|||||||
};
|
};
|
||||||
this.changeTitle = this.changeTitle.bind(this);
|
this.changeTitle = this.changeTitle.bind(this);
|
||||||
this.changeDescription = this.changeDescription.bind(this);
|
this.changeDescription = this.changeDescription.bind(this);
|
||||||
|
this.changePolicy = this.changePolicy.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -47,6 +50,17 @@ export class GroupDetail extends Component {
|
|||||||
this.setState({ description: event.target.value });
|
this.setState({ description: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePolicy() {
|
||||||
|
this.setState({ awaiting: true }, () => {
|
||||||
|
this.props.api.groups.changePolicy(resourceFromPath(this.props.path),
|
||||||
|
Boolean(this.props.group?.policy?.open)
|
||||||
|
? { replace: { invite: { pending: [] } } }
|
||||||
|
: { replace: { open: { banned: [], banRanks: [] } } }
|
||||||
|
).then(() => this.setState({ awaiting: false }));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderDetail() {
|
renderDetail() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
@ -175,7 +189,8 @@ export class GroupDetail extends Component {
|
|||||||
|
|
||||||
const { group, association } = props;
|
const { group, association } = props;
|
||||||
|
|
||||||
const groupOwner = (deSig(props.match.params.ship) === window.ship);
|
const ourRole = roleForShip(group, window.ship);
|
||||||
|
const groupOwner = (ourRole === 'admin');
|
||||||
|
|
||||||
const deleteButtonClasses = (groupOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--gray3 gray3 bg-gray0-d c-default';
|
const deleteButtonClasses = (groupOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--gray3 gray3 bg-gray0-d c-default';
|
||||||
|
|
||||||
@ -280,7 +295,17 @@ export class GroupDetail extends Component {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="f9 mt3 lh-copy">Delete Group</p>
|
<div className="relative w-100 mt6" style={{ maxWidth: '29rem' }}>
|
||||||
|
<Toggle
|
||||||
|
boolean={(Boolean(group?.policy?.invite))}
|
||||||
|
change={this.changePolicy}
|
||||||
|
/>
|
||||||
|
<span className="dib f9 white-d inter ml3">Private Group</span>
|
||||||
|
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
||||||
|
If private, members must be invited
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="f9 mt6 lh-copy">Delete Group</p>
|
||||||
<p className="f9 gray2 mb2">
|
<p className="f9 gray2 mb2">
|
||||||
Permanently delete this group. All current members will no longer see this group.
|
Permanently delete this group. All current members will no longer see this group.
|
||||||
</p>
|
</p>
|
||||||
|
@ -3,6 +3,7 @@ import React, { Component } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { InviteSearch, Invites } from '../../../components/InviteSearch';
|
import { InviteSearch, Invites } from '../../../components/InviteSearch';
|
||||||
import { Spinner } from '../../../components/Spinner';
|
import { Spinner } from '../../../components/Spinner';
|
||||||
|
import { Toggle } from '../../../components/toggle';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
import { Groups, GroupPolicy, Resource } from '../../../types/group-update';
|
import { Groups, GroupPolicy, Resource } from '../../../types/group-update';
|
||||||
import { Contacts, Rolodex } from '../../../types/contact-update';
|
import { Contacts, Rolodex } from '../../../types/contact-update';
|
||||||
@ -129,9 +130,6 @@ export class NewScreen extends Component<NewScreenProps, NewScreenState> {
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const privacySwitchClasses = this.state.privacy
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='h-100 w-100 mw6 pa3 pt4 overflow-x-hidden bg-gray0-d white-d flex flex-column'>
|
<div className='h-100 w-100 mw6 pa3 pt4 overflow-x-hidden bg-gray0-d white-d flex flex-column'>
|
||||||
@ -174,11 +172,9 @@ export class NewScreen extends Component<NewScreenProps, NewScreenState> {
|
|||||||
onChange={this.descriptionChange}
|
onChange={this.descriptionChange}
|
||||||
/>
|
/>
|
||||||
<div className='mv7'>
|
<div className='mv7'>
|
||||||
<input
|
<Toggle
|
||||||
type='checkbox'
|
boolean={this.state.privacy}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.groupPrivacyChange}
|
||||||
onChange={this.groupPrivacyChange}
|
|
||||||
className={privacySwitchClasses}
|
|
||||||
/>
|
/>
|
||||||
<span className='dib f9 white-d inter ml3'>Private Group</span>
|
<span className='dib f9 white-d inter ml3'>Private Group</span>
|
||||||
<p className='f9 gray2 pt1' style={{ paddingLeft: 40 }}>
|
<p className='f9 gray2 pt1' style={{ paddingLeft: 40 }}>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { writeText } from '../../../../lib/util';
|
|
||||||
import { Spinner } from '../../../../components/Spinner';
|
import { Spinner } from '../../../../components/Spinner';
|
||||||
import { InviteSearch } from '../../../../components/InviteSearch';
|
import { InviteSearch } from '../../../../components/InviteSearch';
|
||||||
|
import Toggle from '../../../../components/toggle';
|
||||||
|
|
||||||
export class Settings extends Component {
|
export class Settings extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -133,22 +133,16 @@ export class Settings extends Component {
|
|||||||
// don't give the option to make inclusive if we don't own the target
|
// don't give the option to make inclusive if we don't own the target
|
||||||
// group
|
// group
|
||||||
const targetOwned = (state.targetGroup)
|
const targetOwned = (state.targetGroup)
|
||||||
? state.targetGroup.slice(0, window.ship.length+3) === `/~${window.ship}/`
|
? Boolean(state.targetGroup.includes(`/~${window.ship}/`))
|
||||||
: false;
|
: false;
|
||||||
let inclusiveToggle = <div />;
|
let inclusiveToggle = <div />;
|
||||||
if (targetOwned) {
|
if (targetOwned) {
|
||||||
// TODO toggle component into /lib
|
|
||||||
const inclusiveClasses = state.inclusive
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
inclusiveToggle = (
|
inclusiveToggle = (
|
||||||
<div className="mt4">
|
<div className="mt4">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={state.inclusive}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeInclusive}
|
||||||
className={inclusiveClasses}
|
/>
|
||||||
onChange={this.changeInclusive}
|
|
||||||
/>
|
|
||||||
<span className="dib f9 white-d inter ml3">
|
<span className="dib f9 white-d inter ml3">
|
||||||
Add all members to group
|
Add all members to group
|
||||||
</span>
|
</span>
|
||||||
@ -201,10 +195,6 @@ export class Settings extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const commentsSwitchClasses = (this.state.comments)
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
|
|
||||||
if (this.props.host.slice(1) === window.ship) {
|
if (this.props.host.slice(1) === window.ship) {
|
||||||
return (
|
return (
|
||||||
<div className="flex-column">
|
<div className="flex-column">
|
||||||
@ -274,11 +264,9 @@ export class Settings extends Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mv6">
|
<div className="mv6">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={this.state.comments}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeComments}
|
||||||
className={commentsSwitchClasses}
|
|
||||||
onChange={this.changeComments}
|
|
||||||
/>
|
/>
|
||||||
<span className="dib f9 white-d inter ml3">Comments</span>
|
<span className="dib f9 white-d inter ml3">Comments</span>
|
||||||
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
||||||
@ -293,7 +281,7 @@ export class Settings extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return copyShortcode;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
pkg/interface/src/components/toggle.js
Normal file
20
pkg/interface/src/components/toggle.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export class Toggle extends Component {
|
||||||
|
render() {
|
||||||
|
const switchClasses = (this.props.boolean)
|
||||||
|
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
||||||
|
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
style={{ WebkitAppearance: 'none', width: 28 }}
|
||||||
|
className={switchClasses}
|
||||||
|
onChange={this.props.change}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Toggle;
|
@ -6,6 +6,7 @@ import {
|
|||||||
Group,
|
Group,
|
||||||
Tags,
|
Tags,
|
||||||
GroupPolicy,
|
GroupPolicy,
|
||||||
|
GroupPolicyDiff,
|
||||||
OpenPolicyDiff,
|
OpenPolicyDiff,
|
||||||
OpenPolicy,
|
OpenPolicy,
|
||||||
InvitePolicyDiff,
|
InvitePolicyDiff,
|
||||||
@ -179,6 +180,8 @@ export default class GroupReducer<S extends GroupState> {
|
|||||||
this.openChangePolicy(diff.open, policy);
|
this.openChangePolicy(diff.open, policy);
|
||||||
} else if ('invite' in policy && 'invite' in diff) {
|
} else if ('invite' in policy && 'invite' in diff) {
|
||||||
this.inviteChangePolicy(diff.invite, policy);
|
this.inviteChangePolicy(diff.invite, policy);
|
||||||
|
} else if ('replace' in diff) {
|
||||||
|
state.groups[resourcePath].policy = diff.replace;
|
||||||
} else {
|
} else {
|
||||||
console.log('bad policy diff');
|
console.log('bad policy diff');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user