Add communities, read-only for now

This commit is contained in:
Rogerio Chaves 2020-04-18 09:55:55 +02:00
parent c376a4f065
commit e33b8b9166
No known key found for this signature in database
GPG Key ID: E6AF5440509B1D94
8 changed files with 190 additions and 20 deletions

View File

@ -294,7 +294,7 @@ router.get("/profile/:id(*)", async (req, res) => {
res.render("profile", { profile, posts, friends, friendshipStatus });
});
router.post("/profile/:id/add_friend", async (req, res) => {
router.post("/profile/:id(*)/add_friend", async (req, res) => {
const id = req.params.id;
if (id == req.context.profile.id) {
throw "cannot befriend yourself";
@ -313,7 +313,7 @@ router.post("/profile/:id/add_friend", async (req, res) => {
res.redirect(profileUrl(id));
});
router.post("/profile/:id/reject_friend", async (req, res) => {
router.post("/profile/:id(*)/reject_friend", async (req, res) => {
const id = req.params.id;
if (id == req.context.profile.id) {
throw "cannot reject yourself";
@ -362,7 +362,7 @@ router.post("/vanish", async (req, res) => {
res.send("ok");
});
router.post("/profile/:id/publish", async (req, res) => {
router.post("/profile/:id(*)/publish", async (req, res) => {
const id = req.params.id;
const visibility = req.body.visibility;
@ -407,7 +407,7 @@ router.post("/pubs/add", async (req, res) => {
res.redirect("/");
});
router.get("/about", (_req, res) => {
router.get("/about", (req, res) => {
if (!req.context.profile) {
return res.render("index");
}
@ -448,19 +448,26 @@ router.post("/about", async (req, res) => {
res.redirect("/");
});
router.get("/debug", async (req, res) => {
const query = req.query || {};
router.get("/communities", async (req, res) => {
if (!req.context.profile) {
return res.render("index");
}
const communities = await queries.getCommunities(ssbServer);
const entries = await queries.getAllEntries(ssbServer, query);
res.render("debug", { entries, query });
res.render("communities", { communities });
});
router.get("/debug-error", (_req, res) => {
const object = {};
object.isUndefinedAFunction();
router.get("/communities/:name", async (req, res) => {
const name = req.params.name;
if (!req.context.profile) {
return res.render("index");
}
const [members, posts] = await Promise.all([
queries.getCommunityMembers(ssbServer, name),
queries.getCommunityPosts(ssbServer, name),
]);
res.send("should never reach here");
res.render("community", { community: { name, members, posts } });
});
router.get("/search", async (req, res) => {
@ -484,6 +491,21 @@ router.get("/syncing", (req, res) => {
res.json({ syncing });
});
router.get("/debug", async (req, res) => {
const query = req.query || {};
const entries = await queries.getAllEntries(ssbServer, query);
res.render("debug", { entries, query });
});
router.get("/debug-error", (_req, res) => {
const object = {};
object.isUndefinedAFunction();
res.send("should never reach here");
});
router.get("/metrics", (_req, res) => {
res.set("Content-Type", metrics.register.contentType);
res.end(metrics.register.metrics());

View File

@ -5,7 +5,10 @@ const debugPosts = require("debug")("queries:posts"),
debugFriends = require("debug")("queries:friends"),
debugFriendshipStatus = require("debug")("queries:friendship_status"),
debugPeople = require("debug")("queries:people"),
debugProfile = require("debug")("queries:profile");
debugProfile = require("debug")("queries:profile"),
debugCommunities = require("debug")("queries:communities"),
debugCommunityMembers = require("debug")("queries:communityMembers"),
debugCommunityPosts = require("debug")("queries:communityPosts");
const paramap = require("pull-paramap");
const { promisePull, mapValues } = require("./utils");
@ -276,7 +279,7 @@ const getAllEntries = (ssbServer, query) => {
return promisePull(
ssbServer.query.read({
reverse: true,
limit: 500,
limit: 1000,
...queryOpts,
})
);
@ -327,6 +330,96 @@ const autofollow = async (ssbServer, id) => {
}
};
const getCommunities = async (ssbServer) => {
debugCommunities("Fetching");
const communitiesPosts = await promisePull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
private: { $not: true },
content: {
type: "post",
channel: { $truthy: true },
},
},
},
},
],
limit: 1000,
})
);
const communities = Array.from(
new Set(communitiesPosts.map((p) => p.value.content.channel))
);
debugCommunities("Done");
return communities;
};
const getCommunityMembers = async (ssbServer, name) => {
debugCommunityMembers("Fetching");
const communityMembers = await promisePull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
content: {
type: "channel",
channel: name,
},
},
},
},
],
limit: 100,
}),
paramap(mapProfiles(ssbServer))
);
debugCommunityMembers("Done");
return communityMembers.map((x) => x.value.authorProfile);
};
const getCommunityPosts = async (ssbServer, name) => {
debugCommunityPosts("Fetching");
const communityPosts = await promisePull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
content: {
type: "post",
channel: name,
reply: { $not: true },
root: { $not: true },
},
},
},
},
],
limit: 100,
}),
paramap(mapProfiles(ssbServer))
);
debugCommunityPosts("Done");
return mapValues(communityPosts);
};
setInterval(() => {
debugProfile("Clearing profile cache");
profileCache = {};
@ -342,6 +435,9 @@ module.exports = {
getVanishingMessages,
profileCache,
getFriendshipStatus,
getCommunities,
getCommunityMembers,
getCommunityPosts,
progress,
autofollow,
};

View File

@ -102,6 +102,11 @@ header .logo a:hover {
margin-left: 7px;
}
.no-link-style {
text-decoration: none;
color: #000;
}
main {
max-width: 1200px;
margin: 0 auto;
@ -277,7 +282,7 @@ button.notification-box:hover {
display: block;
}
.friend-item {
.link-block {
border: 1px solid #ddd;
border-radius: 3px;
padding: 5px;
@ -289,7 +294,7 @@ button.notification-box:hover {
background: #fff;
}
.friend-item:hover {
.link-block:hover {
background: #f0f0f0;
}

View File

@ -1,5 +1,5 @@
<% friends.map(friend => { %>
<a class="friend-item" href="<%= profileUrl(friend.id) %>">
<a class="link-block" href="<%= profileUrl(friend.id) %>">
<img style="width: 32px; max-height: 100px; margin-right: 5px;" src="<%= profileImageUrl(friend) %>" />
<div><%= friend.name %></div>
</a>

View File

@ -15,6 +15,7 @@
<nav>
<a href="/">Profile</a>
<a href="/about">About me</a>
<a href="/communities">Communities</a>
<% if (context.profile.admin) { %>
<a href="/pubs">Pubs</a>
<% } %>

View File

@ -1,12 +1,17 @@
<div style="padding-top: 15px;">
<% posts.map(post => { %>
<% if (!post.content.text) return %>
<div class="post">
<div>
<img src="<%= profileImageUrl(post.authorProfile) %>" class="post-profile-pic" />
<a href="<%= profileUrl(post.author) %>">
<img src="<%= profileImageUrl(post.authorProfile) %>" class="post-profile-pic" />
</a>
</div>
<div class="post-content">
<div class="content-header">
<%= post.authorProfile.name %>
<a href="<%= profileUrl(post.author) %>" class="no-link-style">
<%= post.authorProfile.name %>
</a>
</div>
<div class="content-body">
<% let text = post.content.text.slice(0, 140) %>

13
app/views/communities.ejs Normal file
View File

@ -0,0 +1,13 @@
<%- include('_header') %>
<h1>Communities</h1>
<div style="padding-top: 20px">
<% communities.map(community => { %>
<a href="/communities/<%= community %>" class="link-block" style="display: inline-block">
#<%= community %>
</a>
<% }) %>
</div>
<%- include('_footer') %>

28
app/views/community.ejs Normal file
View File

@ -0,0 +1,28 @@
<%- include('_header') %>
<style>
main {
max-width: none;
margin: 0 auto;
}
</style>
<div style="background: #666; color: #FFF; padding: 50px 0">
<div style="max-width: 1200px; margin: 0 auto">
<h1 style="font-size: 60px">#<%= community.name %></h1>
</div>
</div>
<div style="max-width: 1200px; margin: 0 auto">
<div class="columns">
<div class="about">
<h2>Members</h2>
<%- include('_friends', { friends: community.members }) %>
</div>
<div class="wall">
<h2>Posts</h2>
<%- include('_posts', { posts: community.posts }) %>
</div>
</div>
</div>
<%- include('_footer') %>