(
-
-
Settings
-
Settings will go here!
-
-);
-
-export default ContentViewLoop;
diff --git a/src/components/ContentView/index.js b/src/components/ContentView/index.js
index ab30147..cb03eae 100644
--- a/src/components/ContentView/index.js
+++ b/src/components/ContentView/index.js
@@ -1,7 +1,6 @@
import React from 'react';
import ContentViewLoop from './ContentViewLoop';
-import Settings from './Settings';
const ContentView = ({
posts,
@@ -27,7 +26,6 @@ const ContentView = ({
isOwner={isOwner}
/>
)}
- {postDisplay === 'settings' &&
}
);
diff --git a/src/components/Following/FollowSuggestions.js b/src/components/Following/FollowSuggestions.js
new file mode 100644
index 0000000..3d842e3
--- /dev/null
+++ b/src/components/Following/FollowSuggestions.js
@@ -0,0 +1,5 @@
+import React from 'react';
+
+const FollowSuggestions = () =>
Who to follow
;
+
+export default FollowSuggestions;
diff --git a/src/components/Following/Follows.js b/src/components/Following/Follows.js
new file mode 100644
index 0000000..bf90935
--- /dev/null
+++ b/src/components/Following/Follows.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+const Follows = ({ follows }) => (
+
+ {follows &&
+ follows.map((follow, i) => (
+
+ ))}
+
+);
+export default Follows;
diff --git a/src/components/Following/NewFollow.js b/src/components/Following/NewFollow.js
new file mode 100644
index 0000000..091ba65
--- /dev/null
+++ b/src/components/Following/NewFollow.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+const NewFollow = ({ addFollower }) => (
+
+
Add User
+
+
+);
+
+export default NewFollow;
diff --git a/src/components/Header/index.js b/src/components/Header/index.js
index b97de4c..fe9798a 100644
--- a/src/components/Header/index.js
+++ b/src/components/Header/index.js
@@ -49,14 +49,14 @@ const Header = ({
togglePostDisplay('settings')}
+ ${'ContentDisplayToggle__Item'}
+ ${
+ postDisplay === 'settings'
+ ? 'ContentDisplayToggle__Item_Selected'
+ : ''
+ }
+ `}
+ href="/settings"
>
diff --git a/src/components/SharedComponents/Profile/ProfileEdit.js b/src/components/SharedComponents/Profile/ProfileEdit.js
new file mode 100644
index 0000000..9e55799
--- /dev/null
+++ b/src/components/SharedComponents/Profile/ProfileEdit.js
@@ -0,0 +1,58 @@
+import React from 'react';
+
+const ProfileEdit = ({
+ userAvatar,
+ userName,
+ userBio,
+ changeFn,
+ updateUserData
+}) => (
+
+);
+
+export default ProfileEdit;
diff --git a/src/components/SharedComponents/Profile/index.js b/src/components/SharedComponents/Profile/index.js
new file mode 100644
index 0000000..c09bf39
--- /dev/null
+++ b/src/components/SharedComponents/Profile/index.js
@@ -0,0 +1,41 @@
+import React from 'react';
+
+import ProfileEdit from './ProfileEdit';
+
+const Profile = ({
+ userAvatar,
+ userName,
+ userBio,
+ editProfile,
+ changeFn,
+ updateUserData
+}) => (
+
+ {editProfile ? (
+
+ ) : (
+
+
+
Avatar
+ {userAvatar}
+
+
+
+
+ )}
+
+);
+
+export default Profile;
diff --git a/src/config.js b/src/config.js
index ff9f3e4..dd2f617 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,2 +1,7 @@
+//--- Nick
+// export const DAT_URL =
+// 'aeac0a57a7f65ea03693909d817e93d8340c243137ed483076d7b68b18d09c61';
+
+//--- James
export const DAT_URL =
- 'aeac0a57a7f65ea03693909d817e93d8340c243137ed483076d7b68b18d09c61';
+ '7fcca9b6889e23b39a59de3780a74445e49ab722b1cd23358381760d6202a606';
diff --git a/src/containers/App/App.js b/src/containers/App/App.js
index 8742b82..ebdb9a1 100644
--- a/src/containers/App/App.js
+++ b/src/containers/App/App.js
@@ -1,9 +1,12 @@
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import sortBy from 'lodash.sortby';
+import urlEnv from '../../utils/urlEnv';
+import profileContents from '../../utils/profileContents';
+import { queryFollowers, followURLCheck } from '../../utils/following';
import ContentViewContainer from '../ContentViewContainer';
-import urlEnv from '../../utils/urlEnv';
+import Settings from '../Settings';
import PostContainer from '../PostContainer/index';
class App extends Component {
@@ -15,7 +18,10 @@ class App extends Component {
correctBrowser: true,
isOwner: false,
posts: [],
- postDisplay: 'theirs'
+ theirPosts: [],
+ postDisplay: 'mine',
+ editProfile: false,
+ userData: {}
};
}
@@ -23,12 +29,14 @@ class App extends Component {
try {
const archive = await new global.DatArchive(urlEnv());
const archiveInfo = await archive.getInfo();
- const allPosts = await this.getAllPosts(archive);
+ const results = await this.refreshPosts(archive);
+ const theirresults = await this.refreshTheirPosts(archive);
const userData = await this.getUserInfo(archive);
this.setState({
correctBrowser: true,
- posts: allPosts,
+ posts: results,
+ theirPosts: theirresults,
loading: false,
...(archiveInfo.isOwner && { isOwner: true }),
deadTitle: archiveInfo.title,
@@ -36,7 +44,7 @@ class App extends Component {
userData
});
} catch (error) {
- console.log(error);
+ console.log('try error', error);
this.setState({
loading: false,
correctBrowser: false
@@ -57,20 +65,16 @@ class App extends Component {
});
};
- /*
- * This method takes an archive and
- * returns all of their posts.
- * It does not setState.
- */
- getAllPosts = async archive => {
- const posts = await archive.readdir('/posts');
+ refreshTheirPosts = async archive => {
+ await queryFollowers();
+ const posts = await archive.readdir('/theirposts');
if (posts.length === 0) {
this.setState({
- posts: []
+ theirPosts: []
});
} else {
const promises = posts.map(async post => {
- const postResponse = await archive.readFile(`/posts/${post}`);
+ const postResponse = await archive.readFile(`/theirposts/${post}`);
return JSON.parse(postResponse);
});
const results = await Promise.all(promises);
@@ -78,11 +82,7 @@ class App extends Component {
}
};
- /*
- * Exact same as the above function, but
- * also sets state.
- */
- getAllPostsSaved = async archive => {
+ refreshPosts = async archive => {
const posts = await archive.readdir('/posts');
if (posts.length === 0) {
this.setState({
@@ -94,9 +94,7 @@ class App extends Component {
return JSON.parse(postResponse);
});
const results = await Promise.all(promises);
- this.setState({
- posts: results
- });
+ return results;
}
};
@@ -130,9 +128,67 @@ class App extends Component {
window.location.href = '/';
};
+ addFollower = e => {
+ e.preventDefault();
+ // 1. input dat URL into input field
+ const followerFieldVal = document.querySelector('#add-follower-input')
+ .value;
+ // 2. regex in dat://
+
+ /*---
+ 3. query for dat URL
+ 3a. return true or false message if valid dat URL
+ ---*/
+ const followerData = {
+ name: '',
+ url: followURLCheck(followerFieldVal)
+ };
+ if (followerData.url === '') {
+ return null;
+ }
+ // 4. write to following array in profile.json
+ this.setState(
+ {
+ userData: {
+ avatar: this.state.userData.avatar,
+ bio: this.state.userData.bio,
+ name: this.state.userData.name,
+ follows: [...this.state.userData.follows, followerData]
+ }
+ },
+ () => this.changeUserData(this.state.userData)
+ );
+ document.querySelector('#add-follower-input').value = '';
+ };
+
+ updateUserData = e => {
+ e.preventDefault();
+ this.changeUserData(this.state.userData);
+ };
+
+ userDataChange = (e, str) => {
+ this.setState({
+ userData: {
+ ...this.state.userData,
+ [str]: e.target.value
+ }
+ });
+ };
+
+ changeUserData = async userData => {
+ const archive = await new global.DatArchive(urlEnv());
+ await archive.writeFile(`profile.json`, profileContents(userData));
+ this.state.editProfile === true && this.toggleEdit();
+ };
+
+ toggleEdit = () =>
+ this.setState({
+ editProfile: !this.state.editProfile
+ });
+
+ sortedPosts = posts => sortBy(posts, ['createdAt']).reverse();
+
render() {
- const sortedPosts = sortBy(this.state.posts, ['createdAt']).reverse();
- console.log('state', this.state);
return (
@@ -145,7 +201,11 @@ class App extends Component {
contentSelectionOpen={this.state.contentSelectionOpen}
toggleContentSelection={this.toggleContentSelection}
postDisplay={this.state.postDisplay}
- posts={sortedPosts}
+ posts={this.sortedPosts(
+ this.state.postDisplay === 'theirs'
+ ? this.state.theirPosts
+ : this.state.posts
+ )}
isOwner={this.state.isOwner}
getPosts={this.getAllPostsSaved}
togglePostDisplayFn={this.togglePostDisplay}
@@ -175,6 +235,28 @@ class App extends Component {
/>
)}
/>
+ (
+
+ )}
+ />
);
diff --git a/src/containers/ContentViewContainer/index.js b/src/containers/ContentViewContainer/index.js
index 40d8fc8..3184d87 100644
--- a/src/containers/ContentViewContainer/index.js
+++ b/src/containers/ContentViewContainer/index.js
@@ -4,6 +4,7 @@ import Header from '../../components/Header';
import ContentView from '../../components/ContentView';
import BrowserDetection from '../../components/SharedComponents/BrowserDetection';
import UserInfo from '../../components/SharedComponents/UserInfo';
+
const ContentViewContainer = ({
loading,
getPosts,
diff --git a/src/containers/Settings/index.js b/src/containers/Settings/index.js
new file mode 100644
index 0000000..f6c8542
--- /dev/null
+++ b/src/containers/Settings/index.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import urlEnv from '../../utils/urlEnv';
+
+import Header from '../../components/Header';
+import Follows from '../../components/Following/Follows';
+// import FollowSuggestions from '../../components/Following/FollowSuggestions';
+import NewFollow from '../../components/Following/NewFollow';
+import Profile from '../../components/SharedComponents/Profile';
+
+const Settings = props => (
+
+
+
+
+
+
Profile Settings
+
props.toggleEdit()}>
+

+
+
+
+
+
+
Following
+
+
+
+
+
+);
+
+export default Settings;
diff --git a/src/index.css b/src/index.css
index 1201578..51c08f7 100644
--- a/src/index.css
+++ b/src/index.css
@@ -16,8 +16,10 @@ body {
max-width: 1040px;
padding-top: 100px;
}
-.Post__Title {
- padding-bottom: 30px;
+
+.Post .ContentItem__Title a {
+ font-size: 36px;
+ line-height: 40px;
}
.Header {
background-color: rgba(255, 255, 255, 0.8);
@@ -444,12 +446,10 @@ h5 {
position: relative;
width: 120px;
}
-
.ImagePreview img {
height: auto;
width: 100%;
}
-
.ImagePreview__Delete svg {
cursor: pointer;
position: absolute;
@@ -458,3 +458,60 @@ h5 {
transform: rotate(45deg);
width: 25px;
}
+.UserInfo {
+ margin: 0 auto;
+ max-width: 1440px;
+ padding: 18px 20px;
+}
+.Settings {
+ padding-bottom: 100px;
+}
+.Settings__Container {
+ display: flex;
+ flex-direction: row;
+ margin: 0 auto;
+ max-width: 900px;
+ padding-top: 100px;
+}
+.Settings__Item {
+ flex-basis: 50%;
+ padding-right: 40px;
+}
+.Profile .label {
+ font-size: 12px;
+ font-weight: bold;
+ margin-bottom: 0;
+ margin-top: 30px;
+ text-transform: uppercase;
+}
+.Settings__Title {
+ max-width: 250px;
+ position: relative;
+}
+.Settings .Edit__Toggle {
+ cursor: pointer;
+ opacity: 0.7;
+ position: absolute;
+ right: 0;
+ top: -3px;
+ transform: rotate(0deg);
+ transition: opacity 200ms ease, transform 200ms ease;
+}
+.Settings .Edit__Toggle:hover {
+ opacity: 1;
+ transform: rotate(10deg);
+}
+.Settings .Edit__Toggle img {
+ height: auto;
+ width: 40px;
+}
+.Following {
+ margin-top: 20px;
+}
+.Following__Item a {
+ color: #000;
+ display: block;
+ font-size: 14px;
+ font-weight: bold;
+ padding: 10px 0;
+}
diff --git a/src/utils/fileContents.js b/src/utils/fileContents.js
index c538f2e..81bddeb 100644
--- a/src/utils/fileContents.js
+++ b/src/utils/fileContents.js
@@ -17,6 +17,3 @@ const fileContents = (
});
export default fileContents;
-
-//--- Future additions/modifications
-// "imageContent": "${postImage}",
diff --git a/src/utils/following.js b/src/utils/following.js
new file mode 100644
index 0000000..849fa60
--- /dev/null
+++ b/src/utils/following.js
@@ -0,0 +1,52 @@
+import urlEnv from './urlEnv';
+
+const archive = new global.DatArchive(urlEnv());
+
+export const queryFollowers = async () => {
+ // 1. get following list
+ const userData = await archive.readFile(`profile.json`);
+ const followingArray = JSON.parse(userData).follows;
+ // 2. map following users
+ if (followingArray.length > 0) {
+ followingArray.map(async follow => {
+ await queryFollowerPosts(follow);
+ });
+ }
+};
+
+const queryFollowerPosts = async follow => {
+ let newArchive = new global.DatArchive(follow.url);
+ // 3. query posts from following users
+ let userArchive = await newArchive.readdir('/posts');
+ if (userArchive.length > 0) {
+ userArchive.map(async post => {
+ let postResponse = await newArchive.readFile(`/posts/${post}`);
+ let postId = await JSON.parse(postResponse).postId;
+ // 4. check if post downloaded
+ // TODO - File will overwrite at this point... won't want double query though
+
+ // 5. put posts into theirposts folder
+ await writePost(postResponse, postId);
+ });
+ }
+};
+
+const writePost = async (post, postId) => {
+ await archive.writeFile(`/theirposts/${postId}.json`, post);
+};
+
+export const followURLCheck = async value => {
+ if (
+ value.startsWith('dat://') &&
+ (value.length === 70 || value.length === 71)
+ ) {
+ return value;
+ } else if (
+ !value.startsWith('dat://') &&
+ (value.length === 65 || value.length === 66)
+ ) {
+ return 'dat://' + value;
+ } else {
+ return '';
+ }
+};
diff --git a/src/utils/profileContents.js b/src/utils/profileContents.js
new file mode 100644
index 0000000..7757e77
--- /dev/null
+++ b/src/utils/profileContents.js
@@ -0,0 +1,8 @@
+const profileContents = userData => `{
+ "avatar": "${userData.avatar}",
+ "bio": "${userData.bio}",
+ "name": "${userData.name}",
+ "follows": ${JSON.stringify(userData.follows)}
+}`;
+
+export default profileContents;