slate-scenes: unifies section headers

This commit is contained in:
@wwwjim 2020-08-21 21:25:34 -07:00
parent f40eaa6700
commit ed00d86455
12 changed files with 211 additions and 80 deletions

View File

@ -118,14 +118,6 @@ export const DataMeterBar = (props) => {
export default (props) => {
return (
<div css={STYLES_CONTAINER} style={props.style}>
<System.P style={{ fontSize: 12 }}>
<strong css={STYLES_TITLE}>Usage</strong>
Slate users get 1GB of IPFS storage from Textile. In the future you can
extend this with your own plugins using our SDK.
<br />
<br />
</System.P>
<DataMeterBar
leftLabel="used"
rightLabel="total"

View File

@ -0,0 +1,60 @@
import * as React from "react";
import * as Constants from "~/common/constants";
import * as Strings from "~/common/strings";
import { css } from "@emotion/react";
import { TooltipAnchor } from "~/components/system/components/fragments/TooltipAnchor";
const STYLES_ROOT = css`
display: flex;
align-items: flex-start;
justify-content: space-between;
max-width: 578px;
width: 100%;
`;
const STYLES_LEFT = css`
min-width: 10%;
width: 100%;
`;
const STYLES_RIGHT = css`
flex-shrink: 0;
`;
const STYLES_HEADER = css`
box-sizing: border-box;
font-family: ${Constants.font.semiBold};
font-size: 20px;
padding: 0;
margin-bottom: 8px;
display: block;
width: 100%;
white-space: pre-wrap;
overflow-wrap: break-word;
`;
const STYLES_DESCRIPTION = css`
box-sizing: border-box;
font-family: ${Constants.font.text};
font-size: 14px;
margin-bottom: 12px;
line-height: 1.5;
display: block;
width: 100%;
white-space: pre-wrap;
overflow-wrap: break-word;
`;
export default (props) => {
return (
<header css={STYLES_ROOT} style={props.style}>
<div css={STYLES_LEFT}>
<div css={STYLES_HEADER}>{props.title}</div>
<div css={STYLES_DESCRIPTION}>{props.children}</div>
</div>
<div css={STYLES_RIGHT}>{props.actions}</div>
</header>
);
};

View File

@ -4,16 +4,16 @@ import * as System from "~/components/system";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
// TODO(jim): Figure out the activity story.
export default class SceneActivity extends React.Component {
render() {
return (
<ScenePage>
<System.DescriptionGroup
label="Coming soon"
description="Your activity on Slate will appear here."
/>
<ScenePageHeader title="Network [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
</ScenePage>
);
}

View File

@ -7,6 +7,7 @@ import { css } from "@emotion/react";
import Section from "~/components/core/Section";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
const STYLES_NESTED_TABLE = css`
display: grid;
@ -41,7 +42,9 @@ export default class SceneDeals extends React.Component {
console.log(this.props);
return (
<ScenePage>
<System.H1>Deals</System.H1>
<ScenePageHeader title="Deals [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
<Section title="Filecoin storage deal history">
<System.Table

View File

@ -4,16 +4,16 @@ import * as System from "~/components/system";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
// TODO(jim): Figure out the activity story.
export default class SceneDirectory extends React.Component {
render() {
return (
<ScenePage>
<System.DescriptionGroup
label="Coming soon"
description="Your directory on Slate will appear here."
/>
<ScenePageHeader title="Directory [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
</ScenePage>
);
}

View File

@ -7,6 +7,7 @@ import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import DataView from "~/components/core/DataView";
import DataMeter from "~/components/core/DataMeter";
import ScenePageHeader from "~/components/core/ScenePageHeader";
const POLLING_INTERVAL = 10000;
@ -63,14 +64,18 @@ export default class SceneFilesFolder extends React.Component {
render() {
return (
<ScenePage>
<System.DescriptionGroup
label="Are Filecoin deals working?"
description="At the moment there are some bugs with deals on our Devnet but our team is working through them."
<ScenePageHeader title="Data [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
<DataMeter
stats={this.props.viewer.stats}
style={{ margin: "48px 0 24px 0" }}
/>
<DataMeter stats={this.props.viewer.stats} style={{ margin: "48px 0 24px 0" }} />
<System.H1 style={{ marginTop: 48 }}>{this.props.current.name}</System.H1>
<System.H1 style={{ marginTop: 48 }}>
{this.props.current.name}
</System.H1>
<DataView
buttons={[

View File

@ -7,6 +7,7 @@ import { css } from "@emotion/react";
import Section from "~/components/core/Section";
import ScenePage from "~/components/core/ScenePage";
import DataView from "~/components/core/DataView";
import ScenePageHeader from "~/components/core/ScenePageHeader";
const STYLES_NUMBER = css`
font-family: ${Constants.font.semiBold};
@ -75,11 +76,9 @@ export default class SceneHome extends React.Component {
return (
<ScenePage>
<System.DescriptionGroup
label="Will the Home page look like this in the final product?"
description="No! Consider this page just a functionality test. Home will have Filecoin network analytics and updates from the people you engage with."
/>
<System.H1 style={{ marginTop: 48 }}>Home</System.H1>
<ScenePageHeader title="Home [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
{this.props.viewer.addresses[0] ? (
<Section

View File

@ -4,16 +4,16 @@ import * as System from "~/components/system";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
// TODO(jim): Figure out the local data story.
export default class SceneLocalData extends React.Component {
render() {
return (
<ScenePage>
<System.DescriptionGroup
label="Coming soon"
description="An offline client for Slate with local file storage."
/>
<ScenePageHeader title="Local [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
</ScenePage>
);
}

View File

@ -7,6 +7,7 @@ import * as SVG from "~/components/system/svg";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import CodeBlock from "~/components/system/CodeBlock";
const STYLES_KEY = css`
@ -72,7 +73,9 @@ class Key extends React.Component {
{this.state.visible ? (
<div css={STYLES_KEY_LEFT}>{this.props.data.key}</div>
) : (
<div css={STYLES_KEY_LEFT}>XXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXX</div>
<div css={STYLES_KEY_LEFT}>
XXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXX
</div>
)}
<div css={STYLES_KEY_RIGHT}>
<span
@ -80,7 +83,8 @@ class Key extends React.Component {
onClick={this._handleToggleVisible}
style={{
marginRight: 8,
}}>
}}
>
<SVG.Privacy height="16px" />
</span>
<span
@ -88,7 +92,8 @@ class Key extends React.Component {
onClick={() => this._handleDelete(this.props.data.id)}
style={{
marginRight: 4,
}}>
}}
>
<SVG.Dismiss height="16px" />
</span>
</div>
@ -97,7 +102,10 @@ class Key extends React.Component {
}
}
const EXAMPLE_GET_SLATE = (key, slateId) => `const response = await fetch('https://slate.host/api/v1/get-slate', {
const EXAMPLE_GET_SLATE = (
key,
slateId
) => `const response = await fetch('https://slate.host/api/v1/get-slate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -113,7 +121,9 @@ const EXAMPLE_GET_SLATE = (key, slateId) => `const response = await fetch('https
const json = await response.json();
console.log(json);`;
const EXAMPLE_GET = (key) => `const response = await fetch('https://slate.host/api/v1/get', {
const EXAMPLE_GET = (
key
) => `const response = await fetch('https://slate.host/api/v1/get', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -152,7 +162,10 @@ const EXAMPLE_GET_SLATE_RESPONSE = (key, slateId) => `{
}
}`;
const EXAMPLE_UPLOAD_TO_SLATE = (key, slateId) => `const url = 'https://slate.host/api/v1/upload-data/${slateId}';
const EXAMPLE_UPLOAD_TO_SLATE = (
key,
slateId
) => `const url = 'https://slate.host/api/v1/upload-data/${slateId}';
let file = e.target.files[0];
let data = new FormData();
@ -195,7 +208,11 @@ export default class SceneSettingsDeveloper extends React.Component {
_handleDelete = async (id) => {
this.setState({ loading: true });
if (!window.confirm("Are you sure you want to delete this key? This action is irreversible")) {
if (
!window.confirm(
"Are you sure you want to delete this key? This action is irreversible"
)
) {
this.setState({ loading: false });
return;
}
@ -249,19 +266,22 @@ export default class SceneSettingsDeveloper extends React.Component {
return (
<ScenePage>
<System.H1>Developer API</System.H1>
<System.DescriptionGroup
style={{ marginTop: 48, marginBottom: 48 }}
label="Generate an API key"
description="You can use your API key to get slates and add images to slates. You can have a total of 10 keys at any given time."
/>
<ScenePageHeader title="Developer API">
You can use your API key to get slates and add images to slates. You
can have a total of 10 keys at any given time.
</ScenePageHeader>
<br />
<br />
{this.props.viewer.keys.map((k) => {
return <Key key={k.id} data={k} onDelete={this._handleDelete} />;
})}
<div style={{ marginTop: 24 }}>
<System.ButtonPrimary onClick={this._handleSave} loading={this.state.loading}>
<System.ButtonPrimary
onClick={this._handleSave}
loading={this.state.loading}
>
Generate
</System.ButtonPrimary>
</div>
@ -274,7 +294,10 @@ export default class SceneSettingsDeveloper extends React.Component {
label="Get all slates"
description="This API request will return all of your public slates."
/>
<CodeBlock children={EXAMPLE_GET(key)} style={{ maxWidth: "768px" }} />
<CodeBlock
children={EXAMPLE_GET(key)}
style={{ maxWidth: "768px" }}
/>
<br />
<br />
<System.DescriptionGroup
@ -282,19 +305,28 @@ export default class SceneSettingsDeveloper extends React.Component {
label="Get slate by ID"
description="This API request will return a specific slate. If you don't provide an ID argument the response will contain the most recently modified slate."
/>
<CodeBlock children={EXAMPLE_GET_SLATE(key, slateId)} style={{ maxWidth: "768px" }} />
<CodeBlock
children={EXAMPLE_GET_SLATE(key, slateId)}
style={{ maxWidth: "768px" }}
/>
<System.DescriptionGroup
style={{ marginTop: 48, marginBottom: 16 }}
label="Get slate by ID: Response"
description="This is the shape of the response."
/>
<CodeBlock children={EXAMPLE_GET_SLATE_RESPONSE(key)} style={{ maxWidth: "768px" }} />
<CodeBlock
children={EXAMPLE_GET_SLATE_RESPONSE(key)}
style={{ maxWidth: "768px" }}
/>
<System.DescriptionGroup
style={{ marginTop: 48 }}
label="Upload data to slate by ID"
description="This API request will add a JavaScript file object to your slate."
/>
<CodeBlock children={EXAMPLE_UPLOAD_TO_SLATE(key, slateId)} style={{ maxWidth: "768px" }} />
<CodeBlock
children={EXAMPLE_UPLOAD_TO_SLATE(key, slateId)}
style={{ maxWidth: "768px" }}
/>
</React.Fragment>
) : null}
</ScenePage>

View File

@ -7,6 +7,7 @@ import * as SVG from "~/components/system/svg";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import Slate from "~/components/core/Slate";
import SlateMediaObject from "~/components/core/SlateMediaObject";
import CircleButtonLight from "~/components/core/CircleButtonLight";
@ -24,8 +25,11 @@ export default class SceneSlate extends React.Component {
}
componentDidUpdate(prevProps) {
const isNewSlateScene = prevProps.current.slatename !== this.props.current.slatename;
const isUpdated = this.props.current.data.objects.length !== prevProps.current.data.objects.length;
const isNewSlateScene =
prevProps.current.slatename !== this.props.current.slatename;
const isUpdated =
this.props.current.data.objects.length !==
prevProps.current.data.objects.length;
if (isNewSlateScene || isUpdated) {
this.setState({
@ -105,7 +109,9 @@ export default class SceneSlate extends React.Component {
id: each.id,
cid,
data: each,
component: <SlateMediaObject key={each.id} useImageFallback data={each} />,
component: (
<SlateMediaObject key={each.id} useImageFallback data={each} />
),
};
}),
},
@ -180,16 +186,25 @@ export default class SceneSlate extends React.Component {
return (
<ScenePage style={{ padding: `88px 24px 128px 24px` }}>
<System.H1 style={{ marginBottom: 24, paddingLeft: 24 }}>
{slatename}{" "}
<CircleButtonLight onClick={this._handleAdd} style={{ marginLeft: 16, marginRight: 12 }}>
<SVG.Plus height="16px" />
</CircleButtonLight>
<CircleButtonLight onClick={this._handleShowSettings}>
<SVG.Settings height="16px" />
</CircleButtonLight>
</System.H1>
<ScenePageHeader
style={{ padding: `0 24px 0 24px` }}
title={slatename}
actions={
<React.Fragment>
<CircleButtonLight
onClick={this._handleAdd}
style={{ marginLeft: 12, marginRight: 12 }}
>
<SVG.Plus height="16px" />
</CircleButtonLight>
<CircleButtonLight onClick={this._handleShowSettings}>
<SVG.Settings height="16px" />
</CircleButtonLight>
</React.Fragment>
}
>
https://slate.host/{this.props.viewer.username}/{slatename}
</ScenePageHeader>
<Slate editing items={objects} onSelect={this._handleSelect} />
</ScenePage>
);

View File

@ -5,6 +5,7 @@ import * as System from "~/components/system";
import { css } from "@emotion/react";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import Section from "~/components/core/Section";
const STYLES_NUMBER = css`
@ -40,7 +41,9 @@ export default class SceneSlates extends React.Component {
rows: this.props.viewer.slates.map((each) => {
return {
...each,
url: `https://slate.host/${this.props.viewer.username}/${each.slatename}`,
url: `https://slate.host/${this.props.viewer.username}/${
each.slatename
}`,
public: each.data.public,
objects: <span css={STYLES_NUMBER}>{each.data.objects.length}</span>,
};
@ -48,16 +51,20 @@ export default class SceneSlates extends React.Component {
};
// TODO(jim): Refactor later.
const slateButtons = [{ name: "Create slate", type: "SIDEBAR", value: "SIDEBAR_CREATE_SLATE" }];
const slateButtons = [
{ name: "Create slate", type: "SIDEBAR", value: "SIDEBAR_CREATE_SLATE" },
];
return (
<ScenePage>
<System.DescriptionGroup
label="Will the Slates page look like this in the final product?"
description="No! Consider this page just a functionality test. Slates will be collaborative mood boards and will have a much more intuitive experience than this."
/>
<System.H1 style={{ marginTop: 48 }}>Slates</System.H1>
<Section title="Slates" buttons={slateButtons} onAction={this.props.onAction}>
<ScenePageHeader title="Slates [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
<Section
title="Slates"
buttons={slateButtons}
onAction={this.props.onAction}
>
<System.Table
data={slates}
name="slate"

View File

@ -8,6 +8,7 @@ import { css } from "@emotion/react";
import Section from "~/components/core/Section";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
const STYLES_GROUP = css`
padding: 24px;
@ -129,7 +130,9 @@ export default class SceneWallet extends React.Component {
return (
<ScenePage>
<System.H1>Wallet</System.H1>
<ScenePageHeader title="Wallet [WIP]">
This scene is currently a work in progress.
</ScenePageHeader>
<Section
onAction={this.props.onAction}
@ -142,7 +145,8 @@ export default class SceneWallet extends React.Component {
type: "SIDEBAR",
value: "SIDEBAR_CREATE_WALLET_ADDRESS",
},
]}>
]}
>
<div css={STYLES_GROUP}>
<System.SelectMenu
label="Select your address"
@ -158,7 +162,11 @@ export default class SceneWallet extends React.Component {
<div css={STYLES_TEXT}>
<div>
<div css={STYLES_FOCUS}>
{this.state.visible ? currentAddress.address : <span css={STYLES_FOCUS_EMPAHSIS}>Hidden</span>}
{this.state.visible ? (
currentAddress.address
) : (
<span css={STYLES_FOCUS_EMPAHSIS}>Hidden</span>
)}
</div>
<div css={STYLES_SUBTEXT}>Filecoin address</div>
</div>
@ -166,7 +174,8 @@ export default class SceneWallet extends React.Component {
<div style={{ marginTop: 24 }}>
<div css={STYLES_FOCUS}>
{currentAddress.name}{" "}
{this.props.viewer.settings_cold_default_address === currentAddress.address ? (
{this.props.viewer.settings_cold_default_address ===
currentAddress.address ? (
<strong css={STYLES_FOCUS_EMPAHSIS}>(Primary)</strong>
) : null}
</div>
@ -175,7 +184,9 @@ export default class SceneWallet extends React.Component {
<div css={STYLES_ITEM_GROUP}>
<div css={STYLES_ITEM}>
<div css={STYLES_FOCUS}>{Strings.formatNumber(currentAddress.balance)}</div>
<div css={STYLES_FOCUS}>
{Strings.formatNumber(currentAddress.balance)}
</div>
<div css={STYLES_SUBTEXT}>Filecoin</div>
</div>
@ -193,7 +204,8 @@ export default class SceneWallet extends React.Component {
type: "SIDEBAR",
value: "SIDEBAR_WALLET_SEND_FUNDS",
})
}>
}
>
Send Filecoin
</System.ButtonPrimary>
</div>
@ -204,11 +216,17 @@ export default class SceneWallet extends React.Component {
onClick={this._handleMakeAddressVisible}
style={{
marginRight: 16,
backgroundColor: this.state.visible ? null : Constants.system.brand,
}}>
backgroundColor: this.state.visible
? null
: Constants.system.brand,
}}
>
<SVG.Privacy height="16px" />
</span>
<span css={STYLES_CIRCLE_BUTTON} onClick={() => this._handleCopy(currentAddress.address)}>
<span
css={STYLES_CIRCLE_BUTTON}
onClick={() => this._handleCopy(currentAddress.address)}
>
<SVG.CopyAndPaste height="16px" />
</span>
</div>