mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 00:13:12 +03:00
groups: add componentised spinner and behaviours
This commit is contained in:
parent
48e65499e2
commit
afec74cb2e
Before Width: | Height: | Size: 679 B After Width: | Height: | Size: 679 B |
@ -181,16 +181,6 @@ class UrbitApi {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setSpinner(boolean) {
|
|
||||||
store.handleEvent({
|
|
||||||
data: {
|
|
||||||
local: {
|
|
||||||
spinner: boolean
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelected(selected) {
|
setSelected(selected) {
|
||||||
store.handleEvent({
|
store.handleEvent({
|
||||||
data: {
|
data: {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Route, Link } from 'react-router-dom';
|
import { Route, Link } from 'react-router-dom';
|
||||||
import { InviteSearch } from './invite-search';
|
import { InviteSearch } from './invite-search';
|
||||||
|
import { Spinner } from './icons/icon-spinner';
|
||||||
|
|
||||||
|
|
||||||
export class AddScreen extends Component {
|
export class AddScreen extends Component {
|
||||||
@ -11,7 +12,8 @@ export class AddScreen extends Component {
|
|||||||
invites: {
|
invites: {
|
||||||
groups: [],
|
groups: [],
|
||||||
ships: []
|
ships: []
|
||||||
}
|
},
|
||||||
|
awaiting: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.invChange = this.invChange.bind(this);
|
this.invChange = this.invChange.bind(this);
|
||||||
@ -38,12 +40,12 @@ export class AddScreen extends Component {
|
|||||||
invites: {
|
invites: {
|
||||||
groups: [],
|
groups: [],
|
||||||
ships: []
|
ships: []
|
||||||
}
|
},
|
||||||
|
awaiting: true
|
||||||
}, () => {
|
}, () => {
|
||||||
props.api.setSpinner(true);
|
|
||||||
let submit = props.api.group.add(props.path, aud);
|
let submit = props.api.group.add(props.path, aud);
|
||||||
submit.then(() => {
|
submit.then(() => {
|
||||||
props.api.setSpinner(false);
|
this.setState({awaiting: false});
|
||||||
props.history.push("/~groups" + props.path);
|
props.history.push("/~groups" + props.path);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -51,14 +53,6 @@ export class AddScreen extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
let invErrElem = (<span />);
|
|
||||||
if (this.state.inviteError) {
|
|
||||||
invErrElem = (
|
|
||||||
<span className="f9 inter red2 ml3 mb5 db">
|
|
||||||
Invites must be validly formatted ship names.
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-100 w-100 flex flex-column overflow-y-scroll white-d">
|
<div className="h-100 w-100 flex flex-column overflow-y-scroll white-d">
|
||||||
@ -86,6 +80,7 @@ export class AddScreen extends Component {
|
|||||||
<Link to="/~groups">
|
<Link to="/~groups">
|
||||||
<button className="f8 ml4 ba pa2 b--black pointer bg-transparent b--white-d white-d">Cancel</button>
|
<button className="f8 ml4 ba pa2 b--black pointer bg-transparent b--white-d white-d">Cancel</button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Spinner awaiting={this.state.awaiting} classes="mt4 pl4" text="Inviting to group..." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -4,6 +4,7 @@ import { Sigil } from './icons/sigil';
|
|||||||
import { api } from '/api';
|
import { api } from '/api';
|
||||||
import { Route, Link } from 'react-router-dom';
|
import { Route, Link } from 'react-router-dom';
|
||||||
import { EditElement } from '/components/lib/edit-element';
|
import { EditElement } from '/components/lib/edit-element';
|
||||||
|
import { Spinner } from './icons/icon-spinner';
|
||||||
import { uxToHex } from '/lib/util';
|
import { uxToHex } from '/lib/util';
|
||||||
|
|
||||||
export class ContactCard extends Component {
|
export class ContactCard extends Component {
|
||||||
@ -16,7 +17,9 @@ export class ContactCard extends Component {
|
|||||||
emailToSet: null,
|
emailToSet: null,
|
||||||
phoneToSet: null,
|
phoneToSet: null,
|
||||||
websiteToSet: null,
|
websiteToSet: null,
|
||||||
notesToSet: null
|
notesToSet: null,
|
||||||
|
awaiting: false,
|
||||||
|
type: "Saving to group"
|
||||||
};
|
};
|
||||||
this.editToggle = this.editToggle.bind(this);
|
this.editToggle = this.editToggle.bind(this);
|
||||||
this.sigilColorSet = this.sigilColorSet.bind(this);
|
this.sigilColorSet = this.sigilColorSet.bind(this);
|
||||||
@ -44,16 +47,6 @@ export class ContactCard extends Component {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// sigil color updates are done by keystroke parsing on update
|
|
||||||
// other field edits are exclusively handled by setField()
|
|
||||||
let currentColor = (props.contact.color) ? props.contact.color : "000000";
|
|
||||||
currentColor = uxToHex(currentColor);
|
|
||||||
let hexExp = /([0-9A-Fa-f]{6})/
|
|
||||||
let hexTest = hexExp.exec(this.state.colorToSet);
|
|
||||||
|
|
||||||
if (hexTest && (hexTest[1] !== currentColor) && !props.share) {
|
|
||||||
api.contactEdit(props.path, `~${props.ship}`, {color: hexTest[1]});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editToggle() {
|
editToggle() {
|
||||||
@ -123,8 +116,11 @@ export class ContactCard extends Component {
|
|||||||
let hexTest = hexExp.exec(this.state.colorToSet);
|
let hexTest = hexExp.exec(this.state.colorToSet);
|
||||||
|
|
||||||
if (hexTest && (hexTest[1] !== currentColor) && !props.share) {
|
if (hexTest && (hexTest[1] !== currentColor) && !props.share) {
|
||||||
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
api.contactEdit(props.path, `~${props.ship}`, { color: hexTest[1] }).then(() => {
|
api.contactEdit(props.path, `~${props.ship}`, { color: hexTest[1] }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
});
|
});
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -137,7 +133,11 @@ export class ContactCard extends Component {
|
|||||||
}
|
}
|
||||||
let emailTestResult = emailTest.exec(state.emailToSet);
|
let emailTestResult = emailTest.exec(state.emailToSet);
|
||||||
if (emailTestResult) {
|
if (emailTestResult) {
|
||||||
api.contactEdit(props.path, ship, { email: state.emailToSet });
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { email: state.emailToSet }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -148,7 +148,12 @@ export class ContactCard extends Component {
|
|||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
api.contactEdit(props.path, ship, { nickname: state.nickNameToSet });
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { nickname: state.nickNameToSet }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
|
});
|
||||||
|
}))
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "notes": {
|
case "notes": {
|
||||||
@ -158,7 +163,11 @@ export class ContactCard extends Component {
|
|||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
api.contactEdit(props.path, ship, { notes: state.notesToSet });
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { notes: state.notesToSet }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
|
});
|
||||||
|
}))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "phone": {
|
case "phone": {
|
||||||
@ -170,7 +179,11 @@ export class ContactCard extends Component {
|
|||||||
}
|
}
|
||||||
let phoneTestResult = phoneTest.exec(state.phoneToSet);
|
let phoneTestResult = phoneTest.exec(state.phoneToSet);
|
||||||
if (phoneTestResult) {
|
if (phoneTestResult) {
|
||||||
api.contactEdit(props.path, ship, { phone: state.phoneToSet });
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { phone: state.phoneToSet }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
|
});
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -183,37 +196,60 @@ export class ContactCard extends Component {
|
|||||||
}
|
}
|
||||||
let websiteTestResult = websiteTest.exec(state.websiteToSet);
|
let websiteTestResult = websiteTest.exec(state.websiteToSet);
|
||||||
if (websiteTestResult) {
|
if (websiteTestResult) {
|
||||||
api.contactEdit(props.path, ship, { website: state.websiteToSet });
|
this.setState({ awaiting: true, type: "Saving to group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { website: state.websiteToSet }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
|
});
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeAvatar": {
|
case "removeAvatar": {
|
||||||
api.contactEdit(props.path, ship, { avatar: null });
|
this.setState({ awaiting: true, type: "Removing from group" }, (() => {
|
||||||
|
api.contactEdit(props.path, ship, { avatar: null }).then(() => {
|
||||||
|
this.setState({ awaiting: false });
|
||||||
|
});
|
||||||
|
}))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeEmail": {
|
case "removeEmail": {
|
||||||
this.setState({ emailToSet: "" });
|
this.setState({ emailToSet: "", awaiting: true, type: "Removing from group" }, (() => {
|
||||||
api.contactEdit(props.path, ship, { email: "" });
|
api.contactEdit(props.path, ship, { email: "" }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeNickname": {
|
case "removeNickname": {
|
||||||
this.setState({ nicknameToSet: "" });
|
this.setState({ nicknameToSet: "", awaiting: true, type: "Removing from group" }, (() => {
|
||||||
api.contactEdit(props.path, ship, { nickname: "" });
|
api.contactEdit(props.path, ship, { nickname: "" }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removePhone": {
|
case "removePhone": {
|
||||||
this.setState({ phoneToSet: "" });
|
this.setState({ phoneToSet: "", awaiting: true, type: "Removing from group" }, (() => {
|
||||||
api.contactEdit(props.path, ship, { phone: "" });
|
api.contactEdit(props.path, ship, { phone: "" }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeWebsite": {
|
case "removeWebsite": {
|
||||||
this.setState({ websiteToSet: "" });
|
this.setState({ websiteToSet: "", awaiting: true, type: "Removing from group" }, (() => {
|
||||||
api.contactEdit(props.path, ship, { website: "" });
|
api.contactEdit(props.path, ship, { website: "" }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeNotes": {
|
case "removeNotes": {
|
||||||
this.setState({ notesToSet: "" });
|
this.setState({ notesToSet: "", awaiting: true, type: "Removing from group" }, (() => {
|
||||||
api.contactEdit(props.path, ship, { notes: "" });
|
api.contactEdit(props.path, ship, { notes: "" }).then(() => {
|
||||||
|
this.setState({awaiting: false});
|
||||||
|
});
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,13 +289,13 @@ export class ContactCard extends Component {
|
|||||||
color: this.pickFunction(state.colorToSet, defaultVal.color),
|
color: this.pickFunction(state.colorToSet, defaultVal.color),
|
||||||
avatar: null
|
avatar: null
|
||||||
};
|
};
|
||||||
api.setSpinner(true);
|
this.setState({awaiting: true, type: "Sharing with group"}, (() => {
|
||||||
api.contactView.share(
|
api.contactView.share(
|
||||||
`~${props.ship}`, props.path, `~${window.ship}`, contact
|
`~${props.ship}`, props.path, `~${window.ship}`, contact
|
||||||
).then(() => {
|
).then(() => {
|
||||||
api.setSpinner(false);
|
props.history.push(`/~groups/view${props.path}/${window.ship}`)
|
||||||
props.history.push(`/~groups/view${props.path}/${window.ship}`)
|
});
|
||||||
});
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFromGroup() {
|
removeFromGroup() {
|
||||||
@ -280,13 +316,14 @@ export class ContactCard extends Component {
|
|||||||
`~${props.ship}`, props.path, `~${window.ship}`, contact
|
`~${props.ship}`, props.path, `~${window.ship}`, contact
|
||||||
);
|
);
|
||||||
|
|
||||||
api.setSpinner(true);
|
this.setState({awaiting: true, type: "Removing from group"}, (() => {
|
||||||
api.contactHook.remove(props.path, `~${props.ship}`).then(() => {
|
api.contactHook.remove(props.path, `~${props.ship}`).then(() => {
|
||||||
api.setSpinner(false);
|
let destination = (props.ship === window.ship)
|
||||||
let destination = (props.ship === window.ship)
|
? "" : props.path;
|
||||||
? "" : props.path;
|
this.setState({awaiting: false});
|
||||||
props.history.push(`/~groups${destination}`);
|
props.history.push(`/~groups${destination}`);
|
||||||
});
|
});
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEditCard() {
|
renderEditCard() {
|
||||||
@ -548,6 +585,7 @@ export class ContactCard extends Component {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-100 w-100 overflow-x-hidden pb8 white-d">{card}</div>
|
<div className="h-100 w-100 overflow-x-hidden pb8 white-d">{card}</div>
|
||||||
|
<Spinner awaiting={this.state.awaiting} text={`${this.state.type}...`} classes="absolute right-1 bottom-1 ba pa2 b--gray1-d" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,16 @@ import { Route, Link } from 'react-router-dom';
|
|||||||
import { ContactItem } from '/components/lib/contact-item';
|
import { ContactItem } from '/components/lib/contact-item';
|
||||||
import { ShareSheet } from '/components/lib/share-sheet';
|
import { ShareSheet } from '/components/lib/share-sheet';
|
||||||
import { Sigil } from '../lib/icons/sigil';
|
import { Sigil } from '../lib/icons/sigil';
|
||||||
|
import { Spinner } from '../lib/icons/icon-spinner';
|
||||||
import { cite } from '../../lib/util';
|
import { cite } from '../../lib/util';
|
||||||
|
|
||||||
export class ContactSidebar extends Component {
|
export class ContactSidebar extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
awaiting: false
|
||||||
|
}
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
@ -71,11 +78,12 @@ export class ContactSidebar extends Component {
|
|||||||
<p className={"v-mid f9 mh3 red2 pointer " + adminOpt}
|
<p className={"v-mid f9 mh3 red2 pointer " + adminOpt}
|
||||||
style={{paddingTop: 6}}
|
style={{paddingTop: 6}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.api.setSpinner(true);
|
this.setState({awaiting: true}, (() => {
|
||||||
props.api.groupRemove(props.path, [`~${member}`])
|
props.api.groupRemove(props.path, [`~${member}`])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
props.api.setSpinner(false);
|
this.setState({awaiting: false})
|
||||||
})
|
})
|
||||||
|
}))
|
||||||
}}>
|
}}>
|
||||||
Remove
|
Remove
|
||||||
</p>
|
</p>
|
||||||
@ -107,6 +115,7 @@ export class ContactSidebar extends Component {
|
|||||||
{contactItems}
|
{contactItems}
|
||||||
{groupItems}
|
{groupItems}
|
||||||
</div>
|
</div>
|
||||||
|
<Spinner awaiting={this.state.awaiting} text="Removing from group..." classes="pa2 ba absolute right-1 bottom-1 b--gray1-d" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Route, Link } from 'react-router-dom';
|
import { Route, Link } from 'react-router-dom';
|
||||||
|
import { Spinner } from './icons/icon-spinner';
|
||||||
import { deSig, uxToHex } from '/lib/util.js';
|
import { deSig, uxToHex } from '/lib/util.js';
|
||||||
|
|
||||||
export class GroupDetail extends Component {
|
export class GroupDetail extends Component {
|
||||||
@ -8,6 +9,8 @@ export class GroupDetail extends Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
title: "",
|
title: "",
|
||||||
description: "",
|
description: "",
|
||||||
|
awaiting: false,
|
||||||
|
type: "Editing"
|
||||||
}
|
}
|
||||||
this.changeTitle = this.changeTitle.bind(this);
|
this.changeTitle = this.changeTitle.bind(this);
|
||||||
this.changeDescription = this.changeDescription.bind(this);
|
this.changeDescription = this.changeDescription.bind(this);
|
||||||
@ -199,17 +202,18 @@ export class GroupDetail extends Component {
|
|||||||
onChange={this.changeTitle}
|
onChange={this.changeTitle}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (groupOwner) {
|
if (groupOwner) {
|
||||||
props.api.setSpinner(true);
|
this.setState({awaiting: true}, (() => {
|
||||||
props.api.metadataAdd(
|
props.api.metadataAdd(
|
||||||
association['app-path'],
|
association['app-path'],
|
||||||
association['group-path'],
|
association['group-path'],
|
||||||
this.state.title,
|
this.state.title,
|
||||||
association.metadata.description,
|
association.metadata.description,
|
||||||
association.metadata['date-created'],
|
association.metadata['date-created'],
|
||||||
uxToHex(association.metadata.color)
|
uxToHex(association.metadata.color)
|
||||||
).then(() => {
|
).then(() => {
|
||||||
props.api.setSpinner(false);
|
this.setState({awaiting: false})
|
||||||
})
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -226,17 +230,18 @@ export class GroupDetail extends Component {
|
|||||||
onChange={this.changeDescription}
|
onChange={this.changeDescription}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (groupOwner) {
|
if (groupOwner) {
|
||||||
props.api.setSpinner(true);
|
this.setState({awaiting: true}, (() => {
|
||||||
props.api.metadataAdd(
|
props.api.metadataAdd(
|
||||||
association['app-path'],
|
association['app-path'],
|
||||||
association['group-path'],
|
association['group-path'],
|
||||||
association.metadata.title,
|
association.metadata.title,
|
||||||
this.state.description,
|
this.state.description,
|
||||||
association.metadata['date-created'],
|
association.metadata['date-created'],
|
||||||
uxToHex(association.metadata.color)
|
uxToHex(association.metadata.color)
|
||||||
).then(() => {
|
).then(() => {
|
||||||
props.api.setSpinner(false);
|
this.setState({awaiting: false})
|
||||||
})
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -248,14 +253,15 @@ export class GroupDetail extends Component {
|
|||||||
<a className={"dib f9 ba pa2 " + deleteButtonClasses}
|
<a className={"dib f9 ba pa2 " + deleteButtonClasses}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (groupOwner) {
|
if (groupOwner) {
|
||||||
props.api.setSpinner(true);
|
this.setState({awaiting: true, type: "Deleting"}, (() => {
|
||||||
props.api.contactView.delete(props.path).then(() => {
|
props.api.contactView.delete(props.path).then(() => {
|
||||||
props.api.setSpinner(false);
|
props.history.push("/~groups");
|
||||||
props.history.push("/~groups");
|
})
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}}>Delete this group</a>
|
}}>Delete this group</a>
|
||||||
</div>
|
</div>
|
||||||
|
<Spinner awaiting={this.state.awaiting} text={`${this.state.type} group...`} classes="pa2 ba absolute right-1 bottom-1 b--gray1-d"/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,6 @@ export class HeaderBar extends Component {
|
|||||||
let popout = window.location.href.includes("popout/")
|
let popout = window.location.href.includes("popout/")
|
||||||
? "dn" : "dn db-m db-l db-xl";
|
? "dn" : "dn db-m db-l db-xl";
|
||||||
|
|
||||||
// let spinner = !!this.props.spinner
|
|
||||||
// ? this.props.spinner : false;
|
|
||||||
|
|
||||||
// let spinnerClasses = "";
|
|
||||||
|
|
||||||
// if (spinner === true) {
|
|
||||||
// spinnerClasses = "spin-active";
|
|
||||||
// }
|
|
||||||
|
|
||||||
let invites = (this.props.invites && this.props.invites.contacts)
|
let invites = (this.props.invites && this.props.invites.contacts)
|
||||||
? this.props.invites.contacts
|
? this.props.invites.contacts
|
||||||
: {};
|
: {};
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import React, { Component } from "react";
|
|
||||||
|
|
||||||
export class IconHome extends Component {
|
|
||||||
render() {
|
|
||||||
|
|
||||||
let classes = !!this.props.classes ? this.props.classes : "";
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
className={"invert-d " + classes}
|
|
||||||
src="/~groups/img/Home.png"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,25 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
export class IconSpinner extends Component {
|
export class Spinner extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
|
||||||
<div className="spinner-pending"></div>
|
let classes = !!this.props.classes ? this.props.classes : "";
|
||||||
);
|
let text = !!this.props.text ? this.props.text : "";
|
||||||
|
let awaiting = !!this.props.awaiting ? this.props.awaiting : false;
|
||||||
|
|
||||||
|
if (awaiting) {
|
||||||
|
return (
|
||||||
|
<div className={classes + " z-2 bg-white bg-gray0-d white-d"}>
|
||||||
|
<img className="invert-d spin-active v-mid"
|
||||||
|
src="/~groups/img/Spinner.png"
|
||||||
|
width={16}
|
||||||
|
height={16} />
|
||||||
|
<p className="dib f9 ml2 v-mid inter">{text}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import React, { Component } from 'react'
|
|||||||
|
|
||||||
import { Route, Link } from 'react-router-dom';
|
import { Route, Link } from 'react-router-dom';
|
||||||
import { InviteSearch } from './lib/invite-search';
|
import { InviteSearch } from './lib/invite-search';
|
||||||
|
import { Spinner } from './lib/icons/icon-spinner';
|
||||||
import { deSig } from '/lib/util';
|
import { deSig } from '/lib/util';
|
||||||
import urbitOb from 'urbit-ob';
|
import urbitOb from 'urbit-ob';
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ export class NewScreen extends Component {
|
|||||||
},
|
},
|
||||||
// color: '',
|
// color: '',
|
||||||
groupNameError: false,
|
groupNameError: false,
|
||||||
|
awaiting: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.groupNameChange = this.groupNameChange.bind(this);
|
this.groupNameChange = this.groupNameChange.bind(this);
|
||||||
@ -64,16 +66,16 @@ export class NewScreen extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
error: false,
|
error: false,
|
||||||
success: true,
|
success: true,
|
||||||
invites: ''
|
invites: '',
|
||||||
|
awaiting: true
|
||||||
}, () => {
|
}, () => {
|
||||||
props.api.setSpinner(true);
|
|
||||||
props.api.contactView.create(
|
props.api.contactView.create(
|
||||||
group,
|
group,
|
||||||
aud,
|
aud,
|
||||||
this.state.title,
|
this.state.title,
|
||||||
this.state.description
|
this.state.description
|
||||||
).then(() => {
|
).then(() => {
|
||||||
props.api.setSpinner(false);
|
this.setState({awaiting: false});
|
||||||
props.history.push(`/~groups${group}`);
|
props.history.push(`/~groups${group}`);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -147,6 +149,7 @@ export class NewScreen extends Component {
|
|||||||
<Link to="/~groups">
|
<Link to="/~groups">
|
||||||
<button className="f9 ml3 ba pa2 b--black pointer bg-transparent b--white-d white-d">Cancel</button>
|
<button className="f9 ml3 ba pa2 b--black pointer bg-transparent b--white-d white-d">Cancel</button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Spinner awaiting={this.state.awaiting} classes="mt4" text="Creating group..." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -45,7 +45,6 @@ export class Root extends Component {
|
|||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
activeDrawer="groups"
|
activeDrawer="groups"
|
||||||
spinner={state.spinner}
|
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
history={props.history}
|
history={props.history}
|
||||||
api={api}
|
api={api}
|
||||||
@ -67,7 +66,6 @@ export class Root extends Component {
|
|||||||
render={ (props) => {
|
render={ (props) => {
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
api={api}
|
api={api}
|
||||||
@ -100,7 +98,6 @@ export class Root extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
api={api}
|
api={api}
|
||||||
@ -141,7 +138,6 @@ export class Root extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
api={api}
|
api={api}
|
||||||
@ -185,7 +181,6 @@ export class Root extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
api={api}
|
api={api}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -235,7 +230,6 @@ export class Root extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
api={api}
|
api={api}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -271,7 +265,6 @@ export class Root extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
spinner={state.spinner}
|
|
||||||
history={props.history}
|
history={props.history}
|
||||||
api={api}
|
api={api}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
|
@ -12,7 +12,7 @@ export class Skeleton extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-100 w-100 ph4-m ph4-l ph4-xl pb4-m pb4-l pb4-xl">
|
<div className="h-100 w-100 ph4-m ph4-l ph4-xl pb4-m pb4-l pb4-xl">
|
||||||
<HeaderBar spinner={props.spinner} invites={props.invites} associations={props.associations} />
|
<HeaderBar invites={props.invites} associations={props.associations} />
|
||||||
<div className="cf w-100 h-100 h-100-m-40-ns flex ba-m ba-l ba-xl b--gray4 b--gray1-d br1">
|
<div className="cf w-100 h-100 h-100-m-40-ns flex ba-m ba-l ba-xl b--gray4 b--gray1-d br1">
|
||||||
<GroupSidebar
|
<GroupSidebar
|
||||||
contacts={props.contacts}
|
contacts={props.contacts}
|
||||||
@ -26,7 +26,7 @@ export class Skeleton extends Component {
|
|||||||
associations={props.associations}
|
associations={props.associations}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={"h-100 w-100 " + rightPanelClasses}
|
className={"h-100 w-100 relative " + rightPanelClasses}
|
||||||
style={{ flexGrow: 1 }}>
|
style={{ flexGrow: 1 }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,17 +4,10 @@ export class LocalReducer {
|
|||||||
reduce(json, state) {
|
reduce(json, state) {
|
||||||
let data = _.get(json, 'local', false);
|
let data = _.get(json, 'local', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
this.setSpinner(data, state);
|
|
||||||
this.setSelected(data, state);
|
this.setSelected(data, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setSpinner(json, state) {
|
|
||||||
let data = _.has(json, 'spinner', false);
|
|
||||||
if (data) {
|
|
||||||
state.spinner = json.spinner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setSelected(json, state) {
|
setSelected(json, state) {
|
||||||
let data = _.has(json, 'selected', false);
|
let data = _.has(json, 'selected', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -15,8 +15,7 @@ class Store {
|
|||||||
associations: {},
|
associations: {},
|
||||||
permissions: {},
|
permissions: {},
|
||||||
invites: {},
|
invites: {},
|
||||||
selectedGroups: [],
|
selectedGroups: []
|
||||||
spinner: false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initialReducer = new InitialReducer();
|
this.initialReducer = new InitialReducer();
|
||||||
|
Loading…
Reference in New Issue
Block a user