Add button to join/leave communities

This commit is contained in:
Rogerio Chaves 2020-04-26 18:45:45 +02:00
parent bf7f2e7aeb
commit 5282ba0648
No known key found for this signature in database
GPG Key ID: E6AF5440509B1D94
6 changed files with 108 additions and 14 deletions

View File

@ -501,9 +501,13 @@ router.get(
const communityData = (req) => { const communityData = (req) => {
const name = req.params.name; const name = req.params.name;
return queries.getCommunityMembers(name).then((members) => ({ return Promise.all([
queries.getCommunityMembers(name),
queries.isMember(req.context.profile.id, name),
]).then(([members, isMember]) => ({
name, name,
members, members,
isMember,
})); }));
}; };
@ -558,6 +562,38 @@ router.post("/communities/:name/new", async (req, res) => {
res.redirect(`/communities/${name}/${topic.key.replace("%", "")}`); res.redirect(`/communities/${name}/${topic.key.replace("%", "")}`);
}); });
router.post("/communities/:name/join", async (req, res) => {
const name = req.params.name;
await ssb.client().identities.publishAs({
id: req.context.profile.id,
private: false,
content: {
type: "channel",
channel: name,
subscribed: true,
},
});
res.redirect(`/communities/${name}`);
});
router.post("/communities/:name/leave", async (req, res) => {
const name = req.params.name;
await ssb.client().identities.publishAs({
id: req.context.profile.id,
private: false,
content: {
type: "channel",
channel: name,
subscribed: false,
},
});
res.redirect(`/communities/${name}`);
});
router.post("/communities/:name/:key(*)/publish", async (req, res) => { router.post("/communities/:name/:key(*)/publish", async (req, res) => {
const name = req.params.name; const name = req.params.name;
const key = req.params.key; const key = req.params.key;

View File

@ -94,13 +94,14 @@ module.exports.setupRoutes = (router) => {
async (req, res) => { async (req, res) => {
const name = req.params.name; const name = req.params.name;
const [posts, members] = await Promise.all([ const [posts, members, isMember] = await Promise.all([
queries.getCommunityPosts(name), queries.getCommunityPosts(name),
queries.getCommunityMembers(name), queries.getCommunityMembers(name),
queries.isMember(req.context.profile.id, name),
]); ]);
res.render("mobile/communities/community", { res.render("mobile/communities/community", {
community: { name, members }, community: { name, members, isMember },
posts, posts,
layout: "mobile/_layout", layout: "mobile/_layout",
}); });

View File

@ -8,7 +8,8 @@ const debugPosts = require("debug")("queries:posts"),
debugProfile = require("debug")("queries:profile"), debugProfile = require("debug")("queries:profile"),
debugCommunities = require("debug")("queries:communities"), debugCommunities = require("debug")("queries:communities"),
debugCommunityMembers = require("debug")("queries:communityMembers"), debugCommunityMembers = require("debug")("queries:communityMembers"),
debugCommunityPosts = require("debug")("queries:communityPosts"); debugCommunityPosts = require("debug")("queries:communityPosts"),
debugCommunityIsMember = require("debug")("queries:communityIsMember");
const paramap = require("pull-paramap"); const paramap = require("pull-paramap");
const { promisePull, mapValues } = require("./utils"); const { promisePull, mapValues } = require("./utils");
const ssb = require("./ssb-client"); const ssb = require("./ssb-client");
@ -450,6 +451,32 @@ const getCommunities = async () => {
return communities; return communities;
}; };
const isMember = async (id, channel) => {
debugCommunityIsMember("Fetching");
const [lastSubscription] = await promisePull(
ssb.client().query.read({
reverse: true,
limit: 1,
query: [
{
$filter: {
value: {
author: id,
content: {
type: "channel",
channel: channel,
},
},
},
},
],
})
);
debugCommunityIsMember("Done");
return lastSubscription && lastSubscription.value.content.subscribed;
};
const getCommunityMembers = async (name) => { const getCommunityMembers = async (name) => {
debugCommunityMembers("Fetching"); debugCommunityMembers("Fetching");
@ -472,10 +499,22 @@ const getCommunityMembers = async (name) => {
}), }),
paramap(mapProfiles) paramap(mapProfiles)
); );
const dedupMembers = {};
for (const member of communityMembers) {
const author = member.value.author;
if (dedupMembers[author]) continue;
dedupMembers[author] = member;
}
const onlySubscribedMembers = Object.values(dedupMembers).filter(
(x) => x.value.content.subscribed
);
const memberProfiles = onlySubscribedMembers.map(
(x) => x.value.authorProfile
);
debugCommunityMembers("Done"); debugCommunityMembers("Done");
return communityMembers.map((x) => x.value.authorProfile); return memberProfiles;
}; };
const getPostWithReplies = async (channel, key) => { const getPostWithReplies = async (channel, key) => {
@ -611,4 +650,5 @@ module.exports = {
getPostWithReplies, getPostWithReplies,
progress, progress,
autofollow, autofollow,
isMember,
}; };

View File

@ -6,8 +6,8 @@
} }
</style> </style>
<div style="background: #9b5f5f; padding: 50px; border-radius: 5px 5px 0 0"> <div style="background: #9b5f5f; padding: 14px; border-radius: 5px 5px 0 0">
<div style="max-width: 1200px; margin: 0 auto"> <div style="max-width: 1200px; margin: 0 auto; padding: 36px;">
<h1 style="font-size: 60px"> <h1 style="font-size: 60px">
<a href="/communities/<%= community.name %>" style="color: #FFF; text-decoration: none;"> <a href="/communities/<%= community.name %>" style="color: #FFF; text-decoration: none;">
#<%= community.name %> #<%= community.name %>
@ -19,7 +19,12 @@
<div style="max-width: 1200px; margin: 0 auto; border-radius: 0 0 5px 5px"> <div style="max-width: 1200px; margin: 0 auto; border-radius: 0 0 5px 5px">
<div class="columns"> <div class="columns">
<div class="friends-communities" style="border-radius: 0"> <div class="friends-communities" style="border-radius: 0">
<h2>Members</h2> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h2 style="margin: 0;">Members</h2>
<div>
<%- include('../shared/_join_button') %>
</div>
</div>
<%- include('../_friends', { friends: community.members }) %> <%- include('../_friends', { friends: community.members }) %>
</div> </div>
<div class="wall"> <div class="wall">

View File

@ -1,9 +1,12 @@
<div class="pink-background" style="flex-grow: 0;"> <div class="pink-background" style="flex-grow: 0;">
<div style="display: flex; justify-content: space-between;">
<h1> <h1>
<a href="/communities/<%= community.name %>" style="color: #600; text-decoration: none;"> <a href="/communities/<%= community.name %>" style="color: #600; text-decoration: none;">
#<%= community.name %> #<%= community.name %>
</a> </a>
</h1> </h1>
<%- include('../../shared/_join_button') %>
</div>
<a href="/mobile/communities/<%= community.name %>/new" class="compose-new-button" style="background: #fbb"> <a href="/mobile/communities/<%= community.name %>/new" class="compose-new-button" style="background: #fbb">
<div style="font-size: 40px; color: #FFF">+</div> <div style="font-size: 40px; color: #FFF">+</div>
</a> </a>
@ -19,7 +22,7 @@
<div class="tab-content"> <div class="tab-content">
<div class="tab-item js-tab-item"> <div class="tab-item js-tab-item">
<% posts.map(post => { %> <% posts.map(post => { %>
<a href="/communities/<%= community.name %>/<%= post.key.replace("%", "") %>" class="columns community-topic-link"> <a href="/mobile/communities/<%= community.name %>/<%= post.key.replace("%", "") %>" class="columns community-topic-link">
<div class="community-topic-name"> <div class="community-topic-name">
<%- topicTitle(post.value) %> <%- topicTitle(post.value) %>
</div> </div>

View File

@ -0,0 +1,9 @@
<% if (community.isMember) { %>
<form action="/communities/<%= community.name %>/leave" method="POST">
<input type="submit" value="Leave" />
</form>
<% } else { %>
<form action="/communities/<%= community.name %>/join" method="POST">
<input type="submit" value="Join" />
</form>
<% } %>