Fix tag links on org page to correctly navigate to explore page
[gitter.git] / server / handlers / renderers / org.js
blobfd1a5b8a13d2200de10e820b70d335541a8dc1ed
1 'use strict';
3 var assert = require('assert');
4 var clientEnv = require('gitter-client-env');
5 var Promise = require('bluebird');
6 var StatusError = require('statuserror');
7 const asyncHandler = require('express-async-handler');
8 var avatars = require('gitter-web-avatars');
9 var fonts = require('../../web/fonts');
10 var restSerializer = require('../../serializers/rest-serializer');
12 var contextGenerator = require('../../web/context-generator');
13 var generateRoomCardContext = require('gitter-web-shared/templates/partials/room-card-context-generator');
14 var userService = require('gitter-web-users');
15 var groupBrowserService = require('gitter-web-groups/lib/group-browser-service');
16 var roomMembershipService = require('gitter-web-rooms/lib/room-membership-service');
17 var generateUserThemeSnapshot = require('../snapshots/user-theme-snapshot');
18 const mixinHbsDataForVueLeftMenu = require('./vue/mixin-vue-left-menu-data');
20 var ROOMS_PER_PAGE = 15;
22 function findRooms(groupId, user, currentPage) {
23   assert(ROOMS_PER_PAGE <= 15, 'Querying for more than 15 rooms can slow things down too much');
24   var userId = user && user._id;
26   var skip = (currentPage - 1) * ROOMS_PER_PAGE;
27   if (skip > 2000) throw new StatusError(400);
29   return groupBrowserService
30     .findRoomsWithPagination(groupId, userId, {
31       skip: skip,
32       limit: ROOMS_PER_PAGE
33     })
34     .then(function(roomBrowseResult) {
35       var strategy = restSerializer.TroupeStrategy.createSuggestionStrategy();
37       return restSerializer
38         .serialize(roomBrowseResult.results, strategy)
39         .then(function(serializedRooms) {
40           roomBrowseResult.results = serializedRooms;
41           return roomBrowseResult;
42         });
43     });
46 function getRoomMembersForRooms(rooms) {
47   var roomMembershipIdMap = {};
48   var userIdMap = {};
50   return Promise.all(
51     rooms.map(function(room) {
52       return roomMembershipService
53         .findMembersForRoom(room.id, { limit: 5 })
54         .then(function(userIds) {
55           roomMembershipIdMap[room.id] = userIds;
56           userIds.forEach(function(userId) {
57             userIdMap[userId] = true;
58           });
59         });
60     })
61   )
62     .then(function() {
63       var userIds = Object.keys(userIdMap);
64       return userService.findByIds(userIds).then(function(users) {
65         return users.reduce(function(map, user) {
66           map[user.id] = user;
67           return map;
68         }, {});
69       });
70     })
71     .then(function(userMap) {
72       return rooms.reduce(function(roomMembershipMap, room) {
73         roomMembershipMap[room.id] = (roomMembershipIdMap[room.id] || []).reduce(function(
74           membershipList,
75           userId
76         ) {
77           const user = userMap[userId];
78           if (user) {
79             membershipList.push(user);
80           }
82           return membershipList;
83         },
84         []);
85         return roomMembershipMap;
86       }, {});
87     });
90 function getRoomsWithMembership(groupId, user, currentPage) {
91   return findRooms(groupId, user, currentPage).then(function(roomBrowseResult) {
92     var rooms = roomBrowseResult.results;
94     return getRoomMembersForRooms(rooms)
95       .then(function(roomMembershipMap) {
96         return rooms.map(function(room) {
97           room.users = (roomMembershipMap[room.id] || []).map(function(user) {
98             user.avatarUrl = avatars.getForUser(user);
99             return user;
100           });
102           return room;
103         });
104       })
105       .then(function(rooms) {
106         roomBrowseResult.results = rooms;
107         return roomBrowseResult;
108       });
109   });
112 function renderOrgPage(req, res, next) {
113   return Promise.try(function() {
114     var group = req.uriContext.group;
115     if (!group) throw new StatusError(404);
116     var groupId = group._id;
117     var user = req.user;
118     var policy = req.uriContext.policy;
120     var currentPage = Math.max(parseInt(req.query.page, 10) || 1, 1);
122     return Promise.join(
123       getRoomsWithMembership(groupId, user, currentPage),
124       contextGenerator.generateOrgContext(req),
125       policy.canAdmin(),
126       generateUserThemeSnapshot(req),
127       async function(roomBrowseResult, troupeContext, isGroupAdmin, userThemeSnapshot) {
128         var isStaff = req.user && req.user.staff;
129         var editAccess = isGroupAdmin || isStaff;
130         var orgUserCount = roomBrowseResult.totalUsers;
131         var roomCount = roomBrowseResult.total;
133         // Calculate total pages
134         var pageCount = Math.ceil(roomCount / ROOMS_PER_PAGE);
135         var rooms = roomBrowseResult.results.map(function(room) {
136           var result = generateRoomCardContext(room, {
137             isStaff: editAccess,
138             stripGroupName: true
139           });
141           // No idea why this is called `isStaff`
142           result.isStaff = editAccess;
144           return result;
145         });
147         var fullUrl = clientEnv.basePath + '/' + troupeContext.group.homeUri;
148         var text = encodeURIComponent('Explore our chat community on Gitter:');
149         var url =
150           'https://twitter.com/share?' +
151           'text=' +
152           text +
153           '&url=' +
154           fullUrl +
155           '&related=gitchat' +
156           '&via=gitchat';
158         res.render(
159           'org-page',
160           await mixinHbsDataForVueLeftMenu(req, {
161             bootScriptName: 'router-org-page',
162             cssFileName: 'styles/org-page.css',
163             hasDarkTheme: userThemeSnapshot.theme === 'gitter-dark',
164             hasCachedFonts: fonts.hasCachedFonts(req.cookies),
165             fonts: fonts.getFonts(),
166             socialUrl: url,
167             isLoggedIn: !!req.user,
168             exploreBaseUrl: req.user ? '/home/explore' : '/explore',
169             orgDirectoryUrl: fullUrl,
170             roomCount: roomCount,
171             orgUserCount: orgUserCount,
172             isGroupAdmin,
173             group: troupeContext.group,
174             rooms: rooms,
175             troupeContext: troupeContext,
176             pagination: {
177               page: currentPage,
178               pageCount: pageCount
179             }
180           })
181         );
182       }
183     );
184   }).catch(next);
187 module.exports = exports = {
188   renderOrgPage: asyncHandler(renderOrgPage),
189   testOnly: {
190     getRoomMembersForRooms
191   }