loading states for buttons

This commit is contained in:
Martina 2020-09-14 14:29:41 -07:00
parent f048f40be7
commit d588eb5462
4 changed files with 108 additions and 71 deletions

View File

@ -22,22 +22,27 @@ const STYLES_ICON_CIRCLE = css`
justify-content: center;
`;
const STYLES_MODAL = css`
position: relative;
width: 95vw;
max-width: 680px;
box-sizing: border-box;
height: 60vh;
max-height: 500px;
padding: 24px;
const STYLES_CONTAINER = css`
padding: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
background-color: ${Constants.system.white};
box-shadow: 0 0 60px 8px rgba(0, 0, 0, 0.03);
`;
const STYLES_MODAL = css`
position: relative;
width: 95vw;
max-width: 640px;
box-sizing: border-box;
height: 60vh;
max-height: 480px;
`;
const STYLES_SEARCH_DROPDOWN = {
height: "calc(100% - 80px)",
width: "calc(100% - 48px)",
height: "calc(100% - 16px)",
overflowY: "scroll",
};
@ -311,16 +316,18 @@ export class SearchModal extends React.Component {
}
}
return (
<div css={STYLES_MODAL}>
<SearchDropdown
disabled={this.state.loading}
placeholder="Search..."
results={results}
onSelect={this._handleSelect}
onChange={this._handleChange}
inputValue={this.state.inputValue}
style={STYLES_SEARCH_DROPDOWN}
/>
<div css={STYLES_CONTAINER}>
<div css={STYLES_MODAL}>
<SearchDropdown
disabled={this.state.loading}
placeholder="Search..."
results={results}
onSelect={this._handleSelect}
onChange={this._handleChange}
inputValue={this.state.inputValue}
style={STYLES_SEARCH_DROPDOWN}
/>
</div>
</div>
);
}

View File

@ -353,7 +353,8 @@ export default class SlatePreviewBlock extends React.Component {
) : (
<div style={{ height: "8px" }} />
)}
{this.props.slate.data.objects.length ? (
{this.props.slate.data.objects &&
this.props.slate.data.objects.length ? (
<SlatePreviewRow
{...this.props}
previewStyle={this.props.previewStyle}

View File

@ -14,6 +14,12 @@ import { dispatchCustomEvent } from "~/common/custom-events";
import ScenePage from "~/components/core/ScenePage";
import Profile from "~/components/core/Profile";
const STYLES_BUTTONS = css`
display: inline-flex;
flex-direction: row;
align-items: center;
`;
const STATUS_BUTTON_MAP = {
trusted: "Remove peer",
untrusted: "Add peer",
@ -26,6 +32,8 @@ export default class SceneProfile extends React.Component {
loading: false,
trustStatus: "untrusted",
followStatus: false,
followLoading: false,
trustLoading: false,
};
componentDidMount = () => {
@ -39,7 +47,12 @@ export default class SceneProfile extends React.Component {
}
setStatus = (viewer) => {
let newState = { trustStatus: "untrusted", followStatus: false };
let newState = {
trustStatus: "untrusted",
followStatus: false,
followLoading: false,
trustLoading: false,
};
let trust = viewer.trusted.filter((entry) => {
return entry.target_user_id === this.props.data.id;
});
@ -102,52 +115,58 @@ export default class SceneProfile extends React.Component {
this.setStatus(viewer);
};
_handleTrust = async () => {
let response;
if (
this.state.trustStatus === "untrusted" ||
this.state.trustStatus === "sent"
) {
response = await Actions.createTrustRelationship({
userId: this.props.data.id,
});
console.log(response);
} else if (this.state.trustStatus === "received") {
response = await Actions.updateTrustRelationship({
userId: this.props.data.id,
});
console.log(response);
} else {
response = await Actions.deleteTrustRelationship({
id: this.state.trustId,
});
console.log(response);
}
await this._handleUpdate();
_handleTrust = () => {
this.setState({ trustLoading: true }, async () => {
let response;
if (
this.state.trustStatus === "untrusted" ||
this.state.trustStatus === "sent"
) {
response = await Actions.createTrustRelationship({
userId: this.props.data.id,
});
console.log(response);
} else if (this.state.trustStatus === "received") {
response = await Actions.updateTrustRelationship({
userId: this.props.data.id,
});
console.log(response);
} else {
response = await Actions.deleteTrustRelationship({
id: this.state.trustId,
});
console.log(response);
}
await this._handleUpdate();
});
};
_handleFollow = async () => {
let response = await Actions.createSubscription({
userId: this.props.data.id,
_handleFollow = () => {
this.setState({ followLoading: true }, async () => {
let response = await Actions.createSubscription({
userId: this.props.data.id,
});
console.log(response);
await this._handleUpdate();
});
console.log(response);
await this._handleUpdate();
};
render() {
console.log(this.props.data);
let buttons = (
<div>
<div css={STYLES_BUTTONS}>
{this.state.followStatus ? (
<ButtonSecondary
style={{ margin: "0px 8px" }}
loading={this.state.followLoading}
style={{ margin: "0px 8px", minWidth: 152 }}
onClick={this._handleFollow}
>
Unfollow
</ButtonSecondary>
) : (
<ButtonPrimary
style={{ margin: "0px 8px" }}
loading={this.state.followLoading}
style={{ margin: "0px 8px", minWidth: 152 }}
onClick={this._handleFollow}
>
Follow
@ -156,14 +175,16 @@ export default class SceneProfile extends React.Component {
{this.state.trustStatus === "untrusted" ||
this.state.trustStatus === "received" ? (
<ButtonPrimary
style={{ margin: "0px 8px" }}
loading={this.state.trustLoading}
style={{ margin: "0px 8px", minWidth: 152 }}
onClick={this._handleTrust}
>
{STATUS_BUTTON_MAP[this.state.trustStatus]}
</ButtonPrimary>
) : (
<ButtonSecondary
style={{ margin: "0px 8px" }}
loading={this.state.trustLoading}
style={{ margin: "0px 8px", minWidth: 152 }}
onClick={this._handleTrust}
>
{STATUS_BUTTON_MAP[this.state.trustStatus]}

View File

@ -8,6 +8,10 @@ import * as Window from "~/common/window";
import { css } from "@emotion/react";
import { ProcessedText } from "~/components/system/components/Typography";
import {
ButtonPrimary,
ButtonSecondary,
} from "~/components/system/components/Buttons";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
@ -16,16 +20,6 @@ import SlateMediaObject from "~/components/core/SlateMediaObject";
import CircleButtonGray from "~/components/core/CircleButtonGray";
import EmptyState from "~/components/core/EmptyState";
const STYLES_BUTTON = css`
color: ${Constants.system.brand};
cursor: pointer;
padding: 4px 8px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
`;
const STYLES_ICONS = css`
display: flex;
flex-direction: row;
@ -68,6 +62,7 @@ export default class SceneSlate extends React.Component {
loading: false,
saving: "IDLE",
editing: this.props.current.data.ownerId === this.props.viewer.id,
followLoading: false,
};
// NOTE(jim):
@ -172,12 +167,15 @@ export default class SceneSlate extends React.Component {
}
};
_handleFollow = async () => {
let response = await Actions.createSubscription({
slateId: this.props.current.id,
_handleFollow = () => {
this.setState({ followLoading: true }, async () => {
let response = await Actions.createSubscription({
slateId: this.props.current.id,
});
console.log(response);
await this.props.onRehydrate();
this.setState({ followLoading: false });
});
console.log(response);
this.props.onRehydrate();
};
_handleChangeLayout = async (layout, layouts) => {
@ -517,9 +515,19 @@ export default class SceneSlate extends React.Component {
) : (
<div onClick={this._handleFollow}>
{following ? (
<div css={STYLES_BUTTON}>Unfollow</div>
<ButtonSecondary
style={{ minWidth: 120 }}
loading={this.state.followLoading}
>
Unfollow
</ButtonSecondary>
) : (
<div css={STYLES_BUTTON}>Follow</div>
<ButtonPrimary
style={{ minWidth: 120 }}
loading={this.state.followLoading}
>
Follow
</ButtonPrimary>
)}
</div>
)