Skip to content
This repository was archived by the owner on Jun 14, 2020. It is now read-only.

Commit 98030be

Browse files
committed
render to HTML (instead of DOM) // #161
1 parent 78b2ad2 commit 98030be

File tree

7 files changed

+120
-49
lines changed

7 files changed

+120
-49
lines changed

reframe/pages/ProfilePage.config.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,39 @@
11
import React from 'react';
2+
import assert_internal from 'reassert/internal';
23

34
import Profile from '../views/profile/Profile';
45

6+
import {getAllData} from '../views/profile/rightpanel/contrib/getContribInfo';
7+
8+
/*
9+
const doNotRenderInBrowser = false;
10+
const doNotRenderOnServer = true;
11+
/*/
12+
const doNotRenderInBrowser = true;
13+
const doNotRenderOnServer = false;
14+
//*/
15+
516
const ProfilePage = {
617
route: '/:username',
7-
view: ({route: {args: {username}}}) => <Profile username={username} />
18+
view: ({route: {args: {username}}, ...props}) => <Profile username={username} {...props} />,
19+
getInitialProps: async ({route: {args: {username}}}) => {
20+
const isServerRendering = typeof window === "undefined";
21+
const doNotRender = isServerRendering && doNotRenderOnServer;
22+
assert_internal(isServerRendering || !doNotRenderInBrowser);
23+
24+
const allData = (
25+
doNotRender ? (
26+
{doNotRender}
27+
) : (
28+
await getAllData({username})
29+
)
30+
);
31+
return {
32+
isServerRendering,
33+
...allData
34+
};
35+
},
36+
doNotRenderInBrowser,
837
};
938

1039
export default ProfilePage;

reframe/views/profile/Profile.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import RightPanel from './rightpanel/RightPanel';
1010
import './Profile.css';
1111
import * as db from '../../db';
1212
import {urls} from '../../ghuser';
13+
import assert_internal from 'reassert/internal';
1314

1415
class Profile extends React.Component {
1516
constructor(props) {
1617
super(props);
1718
this.state = {
18-
loading: true,
19+
loading: this.props.isServerRendering ? this.props.doNotRender : true,
1920
user: {
2021
login: props.username
2122
},
@@ -25,16 +26,9 @@ class Profile extends React.Component {
2526
}
2627

2728
async componentDidMount() {
28-
const userId = this.props.username.toLowerCase();
29-
try {
30-
const userData = await fetch(`${db.url}/users/${userId}.json`);
31-
const user = await userData.json();
32-
this.setState({ user });
33-
34-
const contribsData = await fetch(`${db.url}/contribs/${userId}.json`);
35-
const contribs = await contribsData.json();
36-
this.setState({ contribs });
37-
} catch (_) {
29+
assert_internal(!this.props.isServerRendering);
30+
assert_internal(!this.props.doNotRender);
31+
if( this.props.profileDoesNotExist ) {
3832
// This profile doesn't exist yet, let's see if it's being created:
3933
const profilesBeingCreatedData = await fetch(urls.profileQueueEndpoint);
4034
const profilesBeingCreated = await profilesBeingCreatedData.json();
@@ -52,19 +46,24 @@ class Profile extends React.Component {
5246
}
5347
}
5448
}
55-
this.setState({ loading: false });
49+
if( this.state.loading ) {
50+
this.setState({ loading: false });
51+
}
5652
}
5753

5854
render() {
55+
assert_internal(!this.props.isServerRendering || !this.props.doNotRender || this.state.loading);
5956
const content = this.state.loading &&
60-
<div><i className="fas fa-spinner fa-pulse"></i> {this.state.user.login}'s profile</div> ||
57+
<div><i className="fas fa-spinner fa-pulse"></i> {this.props.username}'s profile</div> ||
6158
<div className="row">
62-
<LeftPanel user={this.state.user} contribs={this.state.contribs} />
63-
<RightPanel username={this.state.user.login}
64-
fetchedat={this.state.user.contribs && this.state.user.contribs.fetched_at}
65-
contribs={this.state.contribs}
66-
being_created={this.state.user.ghuser_being_created}
67-
deleted_because={this.state.user.ghuser_deleted_because}
59+
<LeftPanel user={this.props.user} contribs={this.props.contribs}
60+
orgsData={this.props.orgsData} />
61+
<RightPanel username={this.props.user.login}
62+
fetchedat={this.props.user.contribs && this.props.user.contribs.fetched_at}
63+
contribs={this.props.contribs}
64+
being_created={this.props.user.ghuser_being_created}
65+
deleted_because={this.props.user.ghuser_deleted_because}
66+
allRepoData={this.props.allRepoData}
6867
profilesBeingCreated={this.state.profilesBeingCreated} />
6968
</div>;
7069

reframe/views/profile/leftpanel/LeftPanel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const LeftPanel = props => {
2828
company={props.user.company} settings={props.user.settings}
2929
blog={!props.user.ghuser_created_at && urls.landing || props.user.blog}
3030
gist_username={props.user.public_gists && props.user.login || null}/>
31-
<Orgs contribOrgs={props.contribs && props.contribs.organizations || []} />
31+
<Orgs orgsData={props.orgsData} />
3232
</div>
3333
);
3434
};

reframe/views/profile/leftpanel/Orgs.js

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,14 @@ import Avatar from '../Avatar';
66
import * as db from '../../../db';
77

88
class Orgs extends React.Component {
9-
constructor(props) {
10-
super(props);
11-
this.state = {
12-
orgs: props.contribOrgs.map(name => ({
13-
name,
14-
avatarUrl: null
15-
})),
16-
};
17-
}
18-
19-
async componentDidMount() {
20-
const orgs = [...this.state.orgs];
21-
for (const org of orgs) {
22-
const orgData = await (await fetch(`${db.url}/orgs/${org.name}.json`)).json();
23-
org.avatarUrl = orgData.avatar_url;
24-
this.setState({
25-
orgs: [...orgs]
26-
});
27-
}
28-
}
29-
309
render() {
3110
const orgAvatar = org => (
3211
<a key={org.name} href={`https://github.com/${org.name}`} target="_blank" title={org.name}>
3312
<Avatar url={org.avatarUrl} classes="avatar-org" />
3413
</a>
3514
);
3615

37-
const contributedTo = this.state.orgs.filter(org => org.avatarUrl).map(org => orgAvatar(org));
16+
const contributedTo = (this.props.orgsData||[]).filter(org => org.avatarUrl).map(org => orgAvatar(org));
3817
if( contributedTo.length===0 ) {
3918
return null;
4019
}

reframe/views/profile/rightpanel/RightPanel.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ const RightPanel = props => {
2626
if (props.contribs) {
2727
const shownContribs = getShownContribs(props.contribs);
2828
shownContribs.forEach((contrib, i) => {
29+
const repo = props.allRepoData[contrib.full_name];
2930
repos.push(
3031
<Contrib key={contrib.full_name} username={props.username} contrib={contrib}
32+
repo={repo}
3133
i={i}
3234
pushToFunctionQueue={pushToFunctionQueue} />
3335
)

reframe/views/profile/rightpanel/contrib/Contrib.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

3-
import * as db from '../../../../db';
3+
//import * as db from '../../../../db';
44
import {urls} from '../../../../ghuser';
55

66
import RichText from '../../../utils/RichText';
@@ -25,12 +25,14 @@ class Contrib extends React.Component {
2525
constructor(props) {
2626
super(props);
2727
this.state = {
28-
loading: true,
28+
// loading: true,
29+
loading: false,
2930
repo: null
3031
};
3132
}
3233

3334
componentDidMount() {
35+
/*
3436
this.props.pushToFunctionQueue(0, async () => {
3537
try {
3638
const repoData = await fetch(`${db.url}/repos/${this.props.contrib.full_name}.json`);
@@ -39,11 +41,14 @@ class Contrib extends React.Component {
3941
} catch (_) {}
4042
this.setState({ loading: false });
4143
});
44+
*/
4245
}
4346

4447
render() {
45-
if( ! this.state.loading && this.state.repo && this.props.i>=10 ) {
46-
return <ContribMini {...{...this.props, ...this.state}}/>;
48+
const repo = this.state.repo || this.props.repo;
49+
50+
if( ! this.state.loading && repo && this.props.i>=10 ) {
51+
return <ContribMini {...{...this.props, ...this.state, repo}}/>;
4752
}
4853

4954
const avatar = () => {
@@ -54,7 +59,7 @@ class Contrib extends React.Component {
5459
</span>
5560
);
5661
}
57-
const repoAvatar = getRepoAvatar(this.state.repo);
62+
const repoAvatar = getRepoAvatar(repo);
5863
if( repoAvatar ) {
5964
return <Avatar url={repoAvatar} classes="avatar-small" />;
6065
}
@@ -81,7 +86,7 @@ class Contrib extends React.Component {
8186
<div style={{position: 'absolute', top: 0, left: 0, paddingTop: 'inherit'}}>
8287
{avatar()}
8388
</div>
84-
<ContribHeader {...{...this.props, ...this.state}}/>
89+
<ContribHeader {...{...this.props, ...this.state, repo}}/>
8590
{badgesLine}
8691
<AccordionBadgerIcon/>
8792
</AccordionHead>

reframe/views/profile/rightpanel/contrib/getContribInfo.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import fetch from '@brillout/fetch';
2+
import * as db from '../../../../db';
3+
14
export {getCommitCounts};
25
export {getRepoAvatar};
36
export {getShownContribs};
47
export {getContribDisplayOrder};
58
export {getContribScore};
9+
export {getAllData};
610

711
function getCommitCounts(contrib) {
812
const {total_commits_count: commits_count__total} = contrib;
@@ -75,3 +79,56 @@ function getStarBoost(stars) {
7579
const starBoost = 0.2 + (Math.log10(stars) / Math.log10(MAX_STARS) * 5);
7680
return starBoost;
7781
}
82+
83+
async function getAllData({username}) {
84+
const userData = await getUserData({username});
85+
if( userData.profileDoesNotExist ) {
86+
return userData;
87+
}
88+
const allRepoData = await getAllRepoData(userData.contribs);
89+
return {allRepoData, ...userData};
90+
}
91+
async function getUserData({username}) {
92+
const userId = username.toLowerCase();
93+
94+
const dbBaseUrl = db.url;
95+
96+
let user;
97+
let contribs;
98+
try {
99+
const userData = await fetch(`${dbBaseUrl}/users/${userId}.json`);
100+
user = await userData.json();
101+
102+
const contribsData = await fetch(`${dbBaseUrl}/contribs/${userId}.json`);
103+
contribs = await contribsData.json();
104+
} catch (_) {
105+
return {profileDoesNotExist: true};
106+
}
107+
108+
const orgsData = contribs && contribs.organizations || [];
109+
await Promise.all(
110+
orgsData.map(async (orgName, i) => {
111+
const newOrgData = await (await fetch(`${db.url}/orgs/${orgName}.json`)).json();
112+
orgsData[i] = {name: orgName, ...newOrgData};
113+
})
114+
);
115+
116+
return {user, contribs, orgsData};
117+
}
118+
async function getAllRepoData(contribs) {
119+
const shownContribs = getShownContribs(contribs);
120+
121+
const allRepoData = {};
122+
123+
await Promise.all(
124+
shownContribs
125+
.map(async contrib => {
126+
const {full_name} = contrib;
127+
const resp = await fetch(`${db.url}/repos/${full_name}.json`);
128+
const repo = await resp.json();
129+
allRepoData[full_name] = repo;
130+
})
131+
);
132+
133+
return allRepoData;
134+
}

0 commit comments

Comments
 (0)