mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
[WIP] Add SubscriptionDetails, ProfileDetails and UsagesDetails in ProfileDialog
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"aws-sdk": "^2.100.0",
|
||||
"axios": "^0.16.1",
|
||||
"classnames": "2.2.5",
|
||||
"date-fns": "^1.29.0",
|
||||
"element-closest": "2.0.2",
|
||||
"flat": "2.0.1",
|
||||
"fontfaceobserver": "2.0.13",
|
||||
|
28
newIDE/app/src/Profile/CreateProfile.js
Normal file
28
newIDE/app/src/Profile/CreateProfile.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import { Column, Line } from '../UI/Grid';
|
||||
|
||||
const styles = {
|
||||
orDivider: {
|
||||
marginLeft: 15,
|
||||
marginTop: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export default props => (
|
||||
<Column>
|
||||
<Line>
|
||||
<p>
|
||||
You are not connected. Create a profile and connect to access to
|
||||
GDevelop online services, like building your game for Android in one
|
||||
click!
|
||||
</p>
|
||||
</Line>
|
||||
<Line justifyContent="center" alignItems="center">
|
||||
<RaisedButton label="Create my profile" onClick={props.onLogin} primary />
|
||||
<span style={styles.orDivider}>or</span>
|
||||
<FlatButton label="Login" onClick={props.onLogin} />
|
||||
</Line>
|
||||
</Column>
|
||||
);
|
33
newIDE/app/src/Profile/ProfileDetails.js
Normal file
33
newIDE/app/src/Profile/ProfileDetails.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import Avatar from 'material-ui/Avatar';
|
||||
import { Column, Line } from '../UI/Grid';
|
||||
import { type Profile } from '../Utils/GDevelopServices/Authentification';
|
||||
import PlaceholderLoader from '../UI/PlaceholderLoader';
|
||||
|
||||
const styles = {
|
||||
title: {
|
||||
fontSize: 25,
|
||||
lineHeight: '40px',
|
||||
marginLeft: 10,
|
||||
},
|
||||
};
|
||||
|
||||
type Props = {
|
||||
profile: ?Profile,
|
||||
};
|
||||
|
||||
export default ({ profile }: Props) =>
|
||||
profile ? (
|
||||
<Column>
|
||||
<Line>
|
||||
<Avatar src={profile.picture} />
|
||||
<span style={styles.title}>You are connect as {profile.nickname}</span>
|
||||
</Line>
|
||||
<Line>
|
||||
<p>With your account, you can access to GDevelop online services.</p>
|
||||
</Line>
|
||||
</Column>
|
||||
) : (
|
||||
<PlaceholderLoader />
|
||||
);
|
@@ -2,11 +2,23 @@
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import { Tabs, Tab } from 'material-ui/Tabs';
|
||||
import Dialog from '../UI/Dialog';
|
||||
import { Column, Line } from '../UI/Grid';
|
||||
import Window from '../Utils/Window';
|
||||
import Authentification, { type Profile } from './Authentification';
|
||||
import { Column } from '../UI/Grid';
|
||||
import Authentification, {
|
||||
type Profile,
|
||||
} from '../Utils/GDevelopServices/Authentification';
|
||||
import CreateProfile from './CreateProfile';
|
||||
import ProfileDetails from './ProfileDetails';
|
||||
import {
|
||||
getUserUsages,
|
||||
type Usages,
|
||||
type Subscription,
|
||||
getUserSubscription,
|
||||
} from '../Utils/GDevelopServices/Usage';
|
||||
import EmptyMessage from '../UI/EmptyMessage';
|
||||
import UsagesDetails from './UsagesDetails';
|
||||
import SubscriptionDetails from './SubscriptionDetails';
|
||||
|
||||
type Props = {|
|
||||
open: boolean,
|
||||
@@ -15,14 +27,20 @@ type Props = {|
|
||||
|};
|
||||
|
||||
type State = {|
|
||||
currentTab: string,
|
||||
authenticated: boolean,
|
||||
profile: ?Profile,
|
||||
usages: ?Usages,
|
||||
subscription: ?Subscription,
|
||||
|};
|
||||
|
||||
export default class PreferencesDialog extends Component<Props, State> {
|
||||
export default class ProfileDialog extends Component<Props, State> {
|
||||
state = {
|
||||
currentTab: 'profile',
|
||||
authenticated: false,
|
||||
profile: null,
|
||||
usages: null,
|
||||
subscription: null,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
@@ -32,24 +50,36 @@ export default class PreferencesDialog extends Component<Props, State> {
|
||||
? this.props.authentification.isAuthenticated()
|
||||
: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.open) {
|
||||
this.fetchUserProfile();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps: Props) {
|
||||
if (!this.props.open && newProps.open) {
|
||||
this.fetchUserProfile();
|
||||
}
|
||||
}
|
||||
|
||||
_onChangeTab = (newTab: string) =>
|
||||
this.setState({
|
||||
currentTab: newTab,
|
||||
});
|
||||
|
||||
fetchUserProfile() {
|
||||
console.log('Fetching');
|
||||
const { authentification } = this.props;
|
||||
if (!authentification) return;
|
||||
|
||||
authentification.getUserInfo((err, profile) => {
|
||||
console.log('YOP', profile);
|
||||
authentification.getUserInfo((err, profile: ?Profile) => {
|
||||
if (err && err.unauthenticated) {
|
||||
return this.setState({
|
||||
authenticated: false,
|
||||
profile: null,
|
||||
usages: null,
|
||||
});
|
||||
} else if (err) {
|
||||
} else if (err || !profile) {
|
||||
console.log('Unable to fetch user profile', err);
|
||||
return;
|
||||
}
|
||||
@@ -57,13 +87,23 @@ export default class PreferencesDialog extends Component<Props, State> {
|
||||
this.setState({
|
||||
profile,
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
getUserUsages(authentification, profile.sub),
|
||||
getUserSubscription(authentification, profile.sub),
|
||||
]).then(([usages, subscription]) => {
|
||||
this.setState({
|
||||
usages,
|
||||
subscription,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
login = () => {
|
||||
if (this.props.authentification)
|
||||
this.props.authentification.login({
|
||||
onHide: () => console.log('hidden'),
|
||||
onHide: () => {},
|
||||
onAuthenticated: arg => {
|
||||
this.setState({
|
||||
authenticated: true,
|
||||
@@ -71,7 +111,7 @@ export default class PreferencesDialog extends Component<Props, State> {
|
||||
|
||||
this.fetchUserProfile();
|
||||
},
|
||||
onAuthorizationError: err => console.log('Authentification error', err),
|
||||
onAuthorizationError: () => {},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -84,38 +124,51 @@ export default class PreferencesDialog extends Component<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { authenticated, profile } = this.state;
|
||||
const { authenticated, profile, usages, subscription } = this.state;
|
||||
const { open, onClose } = this.props;
|
||||
const actions = [
|
||||
<FlatButton label="Close" primary={false} onClick={onClose} />,
|
||||
<FlatButton
|
||||
label="Close"
|
||||
key="close"
|
||||
primary={false}
|
||||
onClick={onClose}
|
||||
/>,
|
||||
];
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
actions={actions}
|
||||
secondaryActions={
|
||||
authenticated && profile
|
||||
? [<FlatButton label="Logout" key="logout" onClick={this.logout} />]
|
||||
: []
|
||||
}
|
||||
onRequestClose={onClose}
|
||||
open={open}
|
||||
title="My profile"
|
||||
noMargin
|
||||
>
|
||||
<Column>
|
||||
<Line>
|
||||
{authenticated && profile ? (
|
||||
<div>
|
||||
You're logged in as {profile.nickname}. Welcome!
|
||||
<RaisedButton label="Logout" onClick={this.logout} />
|
||||
</div>
|
||||
<Tabs value={this.state.currentTab} onChange={this._onChangeTab}>
|
||||
<Tab label="My Profile" value="profile">
|
||||
{authenticated ? (
|
||||
<Column noMargin>
|
||||
<ProfileDetails profile={profile} />
|
||||
<SubscriptionDetails subscription={subscription} />
|
||||
</Column>
|
||||
) : (
|
||||
<div>
|
||||
<RaisedButton
|
||||
label="Create my profile"
|
||||
onClick={this.login}
|
||||
primary
|
||||
/>
|
||||
<FlatButton label="Login" onClick={this.login} />
|
||||
</div>
|
||||
<CreateProfile onLogin={this.login} />
|
||||
)}
|
||||
</Line>
|
||||
</Column>
|
||||
</Tab>
|
||||
<Tab label="Online services usage" value="usage">
|
||||
{authenticated ? (
|
||||
<UsagesDetails usages={usages} />
|
||||
) : (
|
||||
<EmptyMessage>
|
||||
Register to see the usage that you've made of the online
|
||||
services
|
||||
</EmptyMessage>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
42
newIDE/app/src/Profile/SubscriptionDetails.js
Normal file
42
newIDE/app/src/Profile/SubscriptionDetails.js
Normal file
@@ -0,0 +1,42 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import { Column, Line } from '../UI/Grid';
|
||||
import { type Subscription } from '../Utils/GDevelopServices/Usage';
|
||||
import PlaceholderLoader from '../UI/PlaceholderLoader';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
|
||||
type Props = {
|
||||
subscription: ?Subscription,
|
||||
};
|
||||
|
||||
export default ({ subscription }: Props) =>
|
||||
subscription && subscription.planId ? (
|
||||
<Column>
|
||||
<Line>
|
||||
<p>
|
||||
You are subscribed to {subscription.planId}. Congratulations! You have
|
||||
access to more online services, including building your game for
|
||||
Android in one-click!
|
||||
</p>
|
||||
</Line>
|
||||
<Line>
|
||||
<RaisedButton label="Upgrade/change" disabled />
|
||||
<FlatButton label="Cancel subscription" disabled />
|
||||
</Line>
|
||||
</Column>
|
||||
) : subscription && !subscription.planId ? (
|
||||
<Column>
|
||||
<Line>
|
||||
<p>
|
||||
You don't have any subscription. Get one to access to all online
|
||||
services, including building your game for Android in one-click!
|
||||
</p>
|
||||
</Line>
|
||||
<Line>
|
||||
<RaisedButton label="Choose a subscription" disabled />
|
||||
</Line>
|
||||
</Column>
|
||||
) : (
|
||||
<PlaceholderLoader />
|
||||
);
|
49
newIDE/app/src/Profile/UsagesDetails.js
Normal file
49
newIDE/app/src/Profile/UsagesDetails.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableHeader,
|
||||
TableHeaderColumn,
|
||||
TableRow,
|
||||
TableRowColumn,
|
||||
} from 'material-ui/Table';
|
||||
import { type Usages } from '../Utils/GDevelopServices/Usage';
|
||||
import { Column, Line } from '../UI/Grid';
|
||||
import EmptyMessage from '../UI/EmptyMessage';
|
||||
import format from 'date-fns/format'
|
||||
import PlaceholderLoader from '../UI/PlaceholderLoader';
|
||||
|
||||
type Props = { usages: ?Usages };
|
||||
|
||||
//TODO: Do a CircularProgress component that is centered?
|
||||
export default ({ usages }: Props) => (
|
||||
<Column noMargin>
|
||||
<Line>
|
||||
{!usages ? (
|
||||
<PlaceholderLoader />
|
||||
) : usages.length === 0 ? (
|
||||
<EmptyMessage>
|
||||
You don't have any usage of the online services for now
|
||||
</EmptyMessage>
|
||||
) : (
|
||||
<Table selectable={false}>
|
||||
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
|
||||
<TableRow>
|
||||
<TableHeaderColumn>Date</TableHeaderColumn>
|
||||
<TableHeaderColumn>Type</TableHeaderColumn>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody displayRowCheckbox={false}>
|
||||
{usages.map(usage => (
|
||||
<TableRow key={usage.id}>
|
||||
<TableRowColumn>{format(usage.createdAt, 'YYYY-MM-DD HH:mm:ss')}</TableRowColumn>
|
||||
<TableRowColumn>{usage.type}</TableRowColumn>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</Line>
|
||||
</Column>
|
||||
);
|
18
newIDE/app/src/UI/PlaceholderLoader.js
Normal file
18
newIDE/app/src/UI/PlaceholderLoader.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import CircularProgress from 'material-ui/CircularProgress';
|
||||
|
||||
const styles = {
|
||||
containerStyle: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
padding: 10,
|
||||
},
|
||||
};
|
||||
|
||||
export default props => (
|
||||
<div style={{ ...styles.containerStyle, ...props.style }}>
|
||||
<CircularProgress size={40} />
|
||||
</div>
|
||||
);
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const gdevelopGamesPreviewRegion = 'eu-west-1';
|
||||
const gdevelopGamesPreviewBucket = 'gd-games-preview';
|
||||
@@ -41,5 +42,11 @@ export const Auth0Config = {
|
||||
},
|
||||
redirect: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const GDevelopUsageApi = {
|
||||
baseUrl: isDev
|
||||
? 'https://tc1jkfw4ul.execute-api.us-east-1.amazonaws.com/dev'
|
||||
: 'https://qe7jiozpz9.execute-api.us-east-1.amazonaws.com/live',
|
||||
};
|
||||
|
@@ -1,32 +1,21 @@
|
||||
// @flow
|
||||
import Auth0Lock from 'auth0-lock';
|
||||
|
||||
const AUTH_CONFIG = {
|
||||
domain: '4ian.eu.auth0.com',
|
||||
clientId: 'vpsTe5CLJNp7K4nM1nQHzpkentyIZX5U',
|
||||
};
|
||||
import { Auth0Config } from './ApiConfigs';
|
||||
|
||||
export type Profile = {
|
||||
sub: string, // This represents the userId
|
||||
nickname: string,
|
||||
picture: string,
|
||||
email: string,
|
||||
email_verified: boolean,
|
||||
};
|
||||
|
||||
export default class Auth {
|
||||
lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, {
|
||||
autoclose: true,
|
||||
theme: {
|
||||
logo:
|
||||
'https://raw.githubusercontent.com/4ian/GD/gh-pages/res/icon128linux.png',
|
||||
primaryColor: '#4ab0e4',
|
||||
},
|
||||
auth: {
|
||||
responseType: 'token id_token',
|
||||
audience: `https://${AUTH_CONFIG.domain}/userinfo`,
|
||||
params: {
|
||||
scope: 'openid profile email',
|
||||
},
|
||||
redirect: false,
|
||||
},
|
||||
});
|
||||
export default class Authentification {
|
||||
lock = new Auth0Lock(
|
||||
Auth0Config.clientId,
|
||||
Auth0Config.domain,
|
||||
Auth0Config.lockOptions
|
||||
);
|
||||
|
||||
constructor() {
|
||||
this._handleAuthentication();
|
||||
@@ -41,7 +30,6 @@ export default class Auth {
|
||||
onAuthenticated: Function,
|
||||
onAuthorizationError: Function,
|
||||
}) {
|
||||
// Call the show method to display the widget.
|
||||
const noop = () => {};
|
||||
this.lock.show();
|
||||
this.lock.on('hide', onHide || noop);
|
||||
@@ -66,7 +54,7 @@ export default class Auth {
|
||||
localStorage.setItem('id_token', authResult.idToken);
|
||||
localStorage.setItem('expires_at', expiresAt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getUserInfo = (cb: (any, ?Profile) => void) => {
|
||||
if (!this.isAuthenticated()) cb({ unauthenticated: true });
|
||||
@@ -80,13 +68,21 @@ export default class Auth {
|
||||
console.log('Unable to fetch user info', err);
|
||||
cb({ unknownError: true });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
logout = () => {
|
||||
// Clear access token and ID token from local storage
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('id_token');
|
||||
localStorage.removeItem('expires_at');
|
||||
};
|
||||
|
||||
getAuthorizationHeader = () => {
|
||||
try {
|
||||
return 'Bearer ' + (localStorage.getItem('id_token') || '');
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
isAuthenticated = (): boolean => {
|
||||
@@ -102,5 +98,5 @@ export default class Auth {
|
||||
|
||||
let expiresAt = JSON.parse(storedContent);
|
||||
return new Date().getTime() < expiresAt;
|
||||
}
|
||||
};
|
||||
}
|
84
newIDE/app/src/Utils/GDevelopServices/Usage.js
Normal file
84
newIDE/app/src/Utils/GDevelopServices/Usage.js
Normal file
@@ -0,0 +1,84 @@
|
||||
// @flow
|
||||
import axios from 'axios';
|
||||
import type Authentification from './Authentification';
|
||||
import { GDevelopUsageApi } from './ApiConfigs';
|
||||
|
||||
export type Usage = {
|
||||
id: string,
|
||||
userId: string,
|
||||
type: string,
|
||||
createdAt: number,
|
||||
};
|
||||
export type Usages = Array<Usage>;
|
||||
|
||||
export type Subscription = {
|
||||
userId: string,
|
||||
planId: string,
|
||||
createdAt: number,
|
||||
updatedAt: number,
|
||||
};
|
||||
|
||||
export type Limits = {
|
||||
[string]: {
|
||||
limitReached: boolean,
|
||||
current: number,
|
||||
max: number,
|
||||
},
|
||||
};
|
||||
|
||||
export const getSubscriptionPlans = () => ([
|
||||
{
|
||||
planId: 'gdevelop-indie',
|
||||
},
|
||||
{
|
||||
planId: 'gdevelop-pro',
|
||||
}
|
||||
])
|
||||
|
||||
export const getUserUsages = (
|
||||
authentification: Authentification,
|
||||
userId: string
|
||||
): Promise<Usages> => {
|
||||
return axios
|
||||
.get(`${GDevelopUsageApi.baseUrl}/usage`, {
|
||||
params: {
|
||||
userId,
|
||||
},
|
||||
headers: {
|
||||
Authorization: authentification.getAuthorizationHeader(),
|
||||
},
|
||||
})
|
||||
.then(response => response.data);
|
||||
};
|
||||
|
||||
export const getUserSubscription = (
|
||||
authentification: Authentification,
|
||||
userId: string
|
||||
): Promise<Subscription> => {
|
||||
return axios
|
||||
.get(`${GDevelopUsageApi.baseUrl}/subscription`, {
|
||||
params: {
|
||||
userId,
|
||||
},
|
||||
headers: {
|
||||
Authorization: authentification.getAuthorizationHeader(),
|
||||
},
|
||||
})
|
||||
.then(response => response.data);
|
||||
};
|
||||
|
||||
export const getUserLimits = (
|
||||
authentification: Authentification,
|
||||
userId: string
|
||||
): Promise<Limits> => {
|
||||
return axios
|
||||
.get(`${GDevelopUsageApi.baseUrl}/limits`, {
|
||||
params: {
|
||||
userId,
|
||||
},
|
||||
headers: {
|
||||
Authorization: authentification.getAuthorizationHeader(),
|
||||
},
|
||||
})
|
||||
.then(response => response.data);
|
||||
};
|
@@ -5,7 +5,7 @@ import MainFrame from './MainFrame';
|
||||
import Window from './Utils/Window';
|
||||
import ExportDialog from './Export/ExportDialog';
|
||||
import CreateProjectDialog from './ProjectCreation/CreateProjectDialog';
|
||||
import Authentification from './Profile/Authentification';
|
||||
import Authentification from './Utils/GDevelopServices/Authentification';
|
||||
import { sendProgramOpening } from './Utils/Analytics/EventSender';
|
||||
import { installRaven } from './Utils/Analytics/Raven';
|
||||
import { installFullstory } from './Utils/Analytics/Fullstory';
|
||||
|
@@ -14,6 +14,7 @@ import DragHandle from '../UI/DragHandle';
|
||||
import LocalFolderPicker from '../UI/LocalFolderPicker';
|
||||
import LocalExport from '../Export/LocalExport';
|
||||
import LocalCordovaExport from '../Export/LocalCordovaExport';
|
||||
import LocalOnlineCordovaExport from '../Export/LocalOnlineCordovaExport';
|
||||
import LocalS3Export from '../Export/LocalS3Export';
|
||||
import TextEditor from '../ObjectEditor/Editors/TextEditor';
|
||||
import TiledSpriteEditor from '../ObjectEditor/Editors/TiledSpriteEditor';
|
||||
@@ -49,6 +50,8 @@ import InstructionSelector from '../EventsSheet/InstructionEditor/InstructionOrE
|
||||
import ParameterRenderingService from '../EventsSheet/InstructionEditor/ParameterRenderingService';
|
||||
import {ErrorFallbackComponent} from '../UI/ErrorBoundary';
|
||||
import { makeTestProject } from '../fixtures/TestProject';
|
||||
import CreateProfile from '../Profile/CreateProfile';
|
||||
import ProfileDetails from '../Profile/ProfileDetails';
|
||||
|
||||
const gd = global.gd;
|
||||
const {
|
||||
@@ -167,6 +170,11 @@ storiesOf('LocalCordovaExport', module)
|
||||
.addDecorator(muiDecorator)
|
||||
.add('default', () => <LocalCordovaExport project={project} />);
|
||||
|
||||
storiesOf('LocalOnlineCordovaExport', module)
|
||||
.addDecorator(paperDecorator)
|
||||
.addDecorator(muiDecorator)
|
||||
.add('default', () => <LocalOnlineCordovaExport project={project} />);
|
||||
|
||||
storiesOf('LocalFolderPicker', module)
|
||||
.addDecorator(paperDecorator)
|
||||
.addDecorator(muiDecorator)
|
||||
@@ -462,3 +470,23 @@ storiesOf('ErrorBoundary', module)
|
||||
.add('default', () => (
|
||||
<ErrorFallbackComponent />
|
||||
));
|
||||
|
||||
storiesOf('CreateProfile', module)
|
||||
.addDecorator(paperDecorator)
|
||||
.addDecorator(muiDecorator)
|
||||
.add('default', () => (
|
||||
<CreateProfile onLogin={action('login')} />
|
||||
));
|
||||
|
||||
storiesOf('ProfileDetails', module)
|
||||
.addDecorator(paperDecorator)
|
||||
.addDecorator(muiDecorator)
|
||||
.add('profile', () => (
|
||||
<ProfileDetails profile={{
|
||||
nickname: 'Florian',
|
||||
picture: '"https://s.gravatar.com/avatar/d6fc8df7ddfe938cc379c53bfb5645fc?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Ffl.png',
|
||||
}} />
|
||||
))
|
||||
.add('loading', () => (
|
||||
<ProfileDetails profile={null} />
|
||||
));
|
||||
|
@@ -2524,6 +2524,10 @@ dashdash@^1.12.0:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
date-fns@^1.29.0:
|
||||
version "1.29.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6"
|
||||
|
||||
date-now@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||
|
Reference in New Issue
Block a user