mirror of
https://github.com/urbit/shrub.git
synced 2024-12-18 15:55:00 +03:00
publish: componentise spinner as part of layout
This commit pulls the spinner out of the header bar -- and reincorporates it as a component that hooks into local state when awaiting a new prop, or disabling an input.
This commit is contained in:
parent
a21294f02e
commit
48c9bdc702
Before Width: | Height: | Size: 679 B After Width: | Height: | Size: 679 B |
@ -130,15 +130,6 @@ class UrbitApi {
|
||||
});
|
||||
}
|
||||
|
||||
setSpinner(boolean) {
|
||||
store.handleEvent({
|
||||
type: "local",
|
||||
data: {
|
||||
'spinner': boolean
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setSelected(selected) {
|
||||
store.handleEvent({
|
||||
type: "local",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import { CommentItem } from './comment-item';
|
||||
import { dateToDa } from '/lib/util';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
|
||||
export class Comments extends Component {
|
||||
constructor(props){
|
||||
@ -49,11 +50,9 @@ export class Comments extends Component {
|
||||
this.setState({pending: pendingState});
|
||||
|
||||
this.textArea.value = '';
|
||||
window.api.setSpinner(true);
|
||||
this.setState({commentBody: ""});
|
||||
this.setState({commentBody: "", disabled: true});
|
||||
let submit = window.api.action("publish", "publish-action", comment);
|
||||
submit.then(() => {
|
||||
window.api.setSpinner(false);
|
||||
this.setState({ disabled: false });
|
||||
})
|
||||
}
|
||||
@ -105,7 +104,7 @@ export class Comments extends Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mv8">
|
||||
<div className="mv8 relative">
|
||||
<div>
|
||||
<textarea style={{resize:'vertical'}}
|
||||
ref={(el) => {this.textArea = el}}
|
||||
@ -130,6 +129,7 @@ export class Comments extends Component {
|
||||
className={commentClass}>
|
||||
Add comment
|
||||
</button>
|
||||
<Spinner text="Posting comment..." awaiting={this.state.disabled} classes="absolute bottom-0 right-0 pb2"/>
|
||||
</div>
|
||||
{pendingArray}
|
||||
{commentArray}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SidebarSwitcher } from './icons/icon-sidebar-switch';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
||||
import { dateToDa } from '/lib/util';
|
||||
@ -11,7 +12,8 @@ export class EditPost extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
body: '',
|
||||
submit: false
|
||||
submit: false,
|
||||
awaiting: false
|
||||
}
|
||||
this.postSubmit = this.postSubmit.bind(this);
|
||||
this.bodyChange = this.bodyChange.bind(this);
|
||||
@ -48,11 +50,11 @@ export class EditPost extends Component {
|
||||
body: state.body
|
||||
}
|
||||
}
|
||||
window.api.setSpinner(true);
|
||||
this.setState({awaiting: true});
|
||||
window.api.action("publish", "publish-action", editNote).then(() => {
|
||||
let editIndex = props.location.pathname.indexOf("/edit");
|
||||
let noteHref = props.location.pathname.slice(0, editIndex);
|
||||
window.api.setSpinner(false);
|
||||
this.setState({awaiting: false});
|
||||
props.history.push(noteHref);
|
||||
});
|
||||
}
|
||||
@ -125,6 +127,7 @@ export class EditPost extends Component {
|
||||
onBeforeChange={(e, d, v) => this.bodyChange(e, d, v)}
|
||||
onChange={(editor, data, value) => {}}
|
||||
/>
|
||||
<Spinner text="Editing post..." awaiting={this.state.awaiting} classes="absolute bottom-1 right-1 ba b--gray1-d pa2"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,15 +7,6 @@ export class HeaderBar extends Component {
|
||||
let popout = window.location.href.includes("popout/")
|
||||
? "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)
|
||||
? this.props.invites.contacts
|
||||
: {};
|
||||
|
@ -1,15 +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="/~publish/Home.png"
|
||||
width={16}
|
||||
height={16} />
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export class Spinner extends Component {
|
||||
render() {
|
||||
|
||||
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="/~publish/Spinner.png"
|
||||
width={16}
|
||||
height={16} />
|
||||
<p className="dib f9 ml2 v-mid">{text}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import classnames from 'classnames';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import urbitOb from 'urbit-ob';
|
||||
|
||||
export class JoinScreen extends Component {
|
||||
@ -8,7 +9,7 @@ export class JoinScreen extends Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
book: '/',
|
||||
book: '',
|
||||
error: false,
|
||||
awaiting: null,
|
||||
disable: false
|
||||
@ -36,6 +37,7 @@ export class JoinScreen extends Component {
|
||||
let notebook = book[1];
|
||||
if ((ship in this.props.notebooks) &&
|
||||
(notebook in this.props.notebooks[ship])) {
|
||||
this.setState({disable: false, book: "/"});
|
||||
this.props.history.push(`/~publish/notebook/${ship}/${notebook}`)
|
||||
}
|
||||
}
|
||||
@ -91,13 +93,11 @@ export class JoinScreen extends Component {
|
||||
}
|
||||
|
||||
// TODO: askHistory setting
|
||||
window.api.setSpinner(true);
|
||||
this.setState({disable: true});
|
||||
window.api.action("publish","publish-action", actionData).catch((err) => {
|
||||
console.log(err)
|
||||
}).then(() => {
|
||||
this.setState({awaiting: text, disable: false, book: ""})
|
||||
window.api.setSpinner(false);
|
||||
this.setState({awaiting: text})
|
||||
});
|
||||
|
||||
}
|
||||
@ -152,7 +152,9 @@ export class JoinScreen extends Component {
|
||||
style={{
|
||||
resize: 'none',
|
||||
}}
|
||||
onChange={this.bookChange} />
|
||||
onChange={this.bookChange}
|
||||
value={this.state.book}
|
||||
/>
|
||||
{errElem}
|
||||
<br />
|
||||
<button
|
||||
@ -160,10 +162,11 @@ export class JoinScreen extends Component {
|
||||
onClick={this.onClickJoin.bind(this)}
|
||||
className={joinClasses}
|
||||
>Join Notebook</button>
|
||||
<Spinner awaiting={this.state.disable} classes="mt4" text="Joining notebook..." />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default JoinScreen
|
||||
export default JoinScreen;
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react'
|
||||
import { SidebarSwitcher } from './icons/icon-sidebar-switch';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { Controlled as CodeMirror } from 'react-codemirror2'
|
||||
import { dateToDa, stringToSymbol } from '/lib/util';
|
||||
@ -35,7 +36,6 @@ export class NewPost extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
window.api.setSpinner(true);
|
||||
this.setState({ disabled: true });
|
||||
window.api.action("publish", "publish-action", newNote).then(() => {
|
||||
this.setState({ awaiting: newNote["new-note"].note, disabled: false });
|
||||
@ -57,7 +57,6 @@ export class NewPost extends Component {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
let notebook = this.props.notebooks[this.props.ship][this.props.book];
|
||||
if (notebook.notes[this.state.awaiting]) {
|
||||
window.api.setSpinner(false);
|
||||
let popout = (this.props.popout) ? "popout/" : "";
|
||||
let redirect =
|
||||
`/~publish/${popout}note/${this.props.ship}/${this.props.book}/${this.state.awaiting}`;
|
||||
@ -151,6 +150,7 @@ export class NewPost extends Component {
|
||||
onBeforeChange={(e, d, v) => this.bodyChange(e, d, v)}
|
||||
onChange={(editor, data, value) => {}}
|
||||
/>
|
||||
<Spinner text="Creating post..." awaiting={this.state.disabled} classes="absolute bottom-1 right-1 ba b--gray1-d pa2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { InviteSearch } from './invite-search';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { uuid, isPatTa, deSig, stringToSymbol } from "/lib/util";
|
||||
import urbitOb from 'urbit-ob';
|
||||
@ -30,7 +31,6 @@ export class NewScreen extends Component {
|
||||
const { props, state } = this;
|
||||
if (props.notebooks && (("~" + window.ship) in props.notebooks)) {
|
||||
if (state.awaiting in props.notebooks["~" + window.ship]) {
|
||||
props.api.setSpinner(false);
|
||||
let notebook = `/~${window.ship}/${state.awaiting}`;
|
||||
props.history.push("/~publish/notebook" + notebook);
|
||||
}
|
||||
@ -93,10 +93,8 @@ export class NewScreen extends Component {
|
||||
group: groupInfo
|
||||
}
|
||||
}
|
||||
props.api.setSpinner(true);
|
||||
this.setState({awaiting: bookId, disabled: true}, () => {
|
||||
props.api.action("publish", "publish-action", action).then(() => {
|
||||
props.api.setSpinner(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -135,7 +133,7 @@ export class NewScreen extends Component {
|
||||
Notebook must have a valid name.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -202,6 +200,7 @@ export class NewScreen extends Component {
|
||||
className={createClasses}>
|
||||
Create Notebook
|
||||
</button>
|
||||
<Spinner awaiting={this.state.awaiting} classes="mt3" text="Creating notebook..."/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { SidebarSwitcher } from './icons/icon-sidebar-switch';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import { Comments } from './comments';
|
||||
import { NoteNavigation } from './note-navigation';
|
||||
import moment from 'moment';
|
||||
@ -8,8 +9,11 @@ import ReactMarkdown from 'react-markdown';
|
||||
import { cite } from '../../lib/util';
|
||||
|
||||
export class Note extends Component {
|
||||
constructor(props){
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
deleting: false
|
||||
}
|
||||
moment.updateLocale('en', {
|
||||
relativeTime: {
|
||||
past: function(input) {
|
||||
@ -119,10 +123,9 @@ export class Note extends Component {
|
||||
}
|
||||
let popout = (props.popout) ? "popout/" : "";
|
||||
let baseUrl = `/~publish/${popout}notebook/${props.ship}/${props.book}`;
|
||||
window.api.setSpinner(true);
|
||||
this.setState({deleting: true});
|
||||
window.api.action("publish", "publish-action", deleteAction)
|
||||
.then(() => {
|
||||
window.api.setSpinner(false);
|
||||
props.history.push(baseUrl);
|
||||
});
|
||||
}
|
||||
@ -251,6 +254,7 @@ export class Note extends Component {
|
||||
comments={comments}
|
||||
contacts={props.contacts}
|
||||
/>
|
||||
<Spinner text="Deleting post..." awaiting={this.state.deleting} classes="absolute bottom-1 right-1 ba b--gray1-d pa2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { writeText } from '../../lib/util';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
|
||||
export class Settings extends Component {
|
||||
constructor(props){
|
||||
@ -8,7 +9,8 @@ export class Settings extends Component {
|
||||
title: "",
|
||||
description: "",
|
||||
comments: false,
|
||||
disabled: false
|
||||
disabled: false,
|
||||
type: "Editing"
|
||||
}
|
||||
this.deleteNotebook = this.deleteNotebook.bind(this);
|
||||
this.changeTitle = this.changeTitle.bind(this);
|
||||
@ -55,8 +57,7 @@ export class Settings extends Component {
|
||||
}
|
||||
|
||||
changeComments() {
|
||||
this.setState({comments: !this.state.comments}, (() => {
|
||||
window.api.setSpinner(true);
|
||||
this.setState({comments: !this.state.comments, disabled: true}, (() => {
|
||||
window.api.action("publish", "publish-action", {
|
||||
"edit-book": {
|
||||
book: this.props.book,
|
||||
@ -66,7 +67,7 @@ export class Settings extends Component {
|
||||
group: null
|
||||
}
|
||||
}).then(() => {
|
||||
window.api.setSpinner(false);
|
||||
this.setState({disabled: false});
|
||||
})
|
||||
}));
|
||||
}
|
||||
@ -77,9 +78,8 @@ export class Settings extends Component {
|
||||
book: this.props.book
|
||||
}
|
||||
}
|
||||
window.api.setSpinner(true);
|
||||
this.setState({ disabled: true, type: "Deleting" });
|
||||
window.api.action("publish", "publish-action", action).then(() => {
|
||||
window.api.setSpinner(false);
|
||||
this.props.history.push("/~publish");
|
||||
});
|
||||
}
|
||||
@ -138,7 +138,6 @@ export class Settings extends Component {
|
||||
disabled={this.state.disabled}
|
||||
onBlur={() => {
|
||||
this.setState({ disabled: true });
|
||||
window.api.setSpinner(true);
|
||||
window.api
|
||||
.action("publish", "publish-action", {
|
||||
"edit-book": {
|
||||
@ -151,7 +150,6 @@ export class Settings extends Component {
|
||||
})
|
||||
.then(() => {
|
||||
this.setState({ disabled: false })
|
||||
window.api.setSpinner(false);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@ -168,7 +166,6 @@ export class Settings extends Component {
|
||||
onChange={this.changeDescription}
|
||||
onBlur={() => {
|
||||
this.setState({ disabled: true });
|
||||
window.api.setSpinner(true);
|
||||
window.api
|
||||
.action("publish", "publish-action", {
|
||||
"edit-book": {
|
||||
@ -181,7 +178,6 @@ export class Settings extends Component {
|
||||
})
|
||||
.then(() => {
|
||||
this.setState({ disabled: false });
|
||||
window.api.setSpinner(false);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@ -198,6 +194,11 @@ export class Settings extends Component {
|
||||
Subscribers may comment when enabled
|
||||
</p>
|
||||
</div>
|
||||
<Spinner
|
||||
awaiting={this.state.disabled}
|
||||
classes="absolute right-1 bottom-1 pa2 ba b--black b--gray0-d white-d"
|
||||
text={`${this.state.type} notebook...`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
@ -19,6 +19,11 @@ export class Root extends Component {
|
||||
store.setStateHandler(this.setState.bind(this));
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
//preload spinner asset
|
||||
new Image().src = "/~publish/Spinner.png";
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props, state } = this;
|
||||
|
||||
@ -36,7 +41,6 @@ export class Root extends Component {
|
||||
active={"sidebar"}
|
||||
rightPanelHide={true}
|
||||
sidebarShown={true}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
@ -62,7 +66,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
@ -89,7 +92,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
@ -128,7 +130,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
@ -153,7 +154,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
@ -199,7 +199,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
selectedGroups={selectedGroups}
|
||||
@ -224,7 +223,6 @@ export class Root extends Component {
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={state.sidebarShown}
|
||||
spinner={state.spinner}
|
||||
invites={state.invites}
|
||||
notebooks={state.notebooks}
|
||||
associations={associations}
|
||||
|
@ -21,7 +21,6 @@ export class Skeleton extends Component {
|
||||
return (
|
||||
<div className={"absolute h-100 w-100 " + popoutWindow}>
|
||||
<HeaderBar
|
||||
spinner={props.spinner}
|
||||
invites={props.invites}
|
||||
associations={props.associations} />
|
||||
<div className={`cf w-100 h-100 flex ` + popoutBorder}>
|
||||
|
@ -20,7 +20,6 @@ export class ResponseReducer {
|
||||
break;
|
||||
case "local":
|
||||
this.sidebarToggle(json, state);
|
||||
this.setSpinner(json, state);
|
||||
this.setSelected(json, state);
|
||||
break;
|
||||
default:
|
||||
@ -205,12 +204,6 @@ export class ResponseReducer {
|
||||
}
|
||||
}
|
||||
|
||||
setSpinner(json, state) {
|
||||
let data = _.has(json.data, 'spinner', false);
|
||||
if (data) {
|
||||
state.spinner = json.data.spinner;
|
||||
}
|
||||
}
|
||||
setSelected(json, state) {
|
||||
let data = _.has(json.data, 'selected', false);
|
||||
if (data) {
|
||||
|
@ -18,7 +18,6 @@ class Store {
|
||||
permissions: {},
|
||||
invites: {},
|
||||
selectedGroups: [],
|
||||
spinner: false,
|
||||
sidebarShown: true
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user