Skip to content
This repository was archived by the owner on Oct 30, 2025. It is now read-only.

Commit 239a25c

Browse files
committed
[NEW] Displays online and all members for each channel
1 parent 9799b68 commit 239a25c

3 files changed

Lines changed: 168 additions & 7 deletions

File tree

client/src/components/ChannelInfo/index.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,13 @@
5555
overflow-wrap: break-word;
5656
overflow-y: auto;
5757
}
58+
59+
.channel-info-wrapper {
60+
height: -webkit-fill-available;
61+
}
62+
63+
.user-logged-out-message {
64+
font-size: 0.95em;
65+
color: #9a9ea4;
66+
line-height: 25px;
67+
}

client/src/components/ChannelInfo/index.js

Lines changed: 158 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
import React, { useState, useEffect } from "react";
22
import PropTypes from "prop-types";
3-
import { Tabs, Tab, Typography, Box } from "@material-ui/core";
3+
import {
4+
Tabs,
5+
Tab,
6+
Typography,
7+
Box,
8+
Grid,
9+
Button,
10+
Dialog,
11+
DialogContent,
12+
DialogTitle,
13+
Slide,
14+
} from "@material-ui/core";
415
import Cookies from "js-cookie";
516
import axios from "axios";
6-
import { githubApiDomain } from "../../utils/constants";
17+
import { githubApiDomain, rcApiDomain } from "../../utils/constants";
18+
import online from "../../images/online.png";
719

820
import "./index.css";
921

22+
const Transition = React.forwardRef(function Transition(props, ref) {
23+
return <Slide direction="up" ref={ref} {...props} />;
24+
});
25+
1026
function TabPanel(props) {
1127
const { children, value, index, ...other } = props;
1228

@@ -42,6 +58,13 @@ export default function ChannelInfo(props) {
4258
const [repoInfo, setRepoInfo] = useState({});
4359
const [isPrivate, setIsPrivate] = useState(false);
4460
const [issuesCount, setIssuesCount] = useState(0);
61+
const [isLoggedOut, setIsLoggedOut] = useState(false);
62+
const [channelMembers, setChannelMembers] = useState([]);
63+
const [openMembersDialog, setOpenMembersDialog] = useState(false);
64+
const [activeTab, setActiveTab] = useState(0);
65+
const repoURL = `https://github.com/${props.location.pathname
66+
.split("/")[2]
67+
.replace("_", "/")}`;
4568

4669
useEffect(() => {
4770
const ghRepoInfo = async () => {
@@ -51,18 +74,18 @@ export default function ChannelInfo(props) {
5174
const repository = props.location.pathname
5275
.split("/")[2]
5376
.replace("_", "/");
54-
const headers = {
77+
const ghHeaders = {
5578
accept: "application/json",
5679
};
5780
if (Cookies.get("gh_private_repo_token")) {
58-
headers["Authorization"] = `token ${Cookies.get(
81+
ghHeaders["Authorization"] = `token ${Cookies.get(
5982
"gh_private_repo_token"
6083
)}`;
6184
}
6285
const ghRepoInfoResponse = await axios({
6386
method: "get",
6487
url: `${githubApiDomain}/repos/${repository}`,
65-
headers: headers,
88+
headers: ghHeaders,
6689
});
6790
const ghIssuesResponse = await axios({
6891
method: "get",
@@ -80,7 +103,29 @@ export default function ChannelInfo(props) {
80103
setIsPrivate(true);
81104
}
82105
};
106+
107+
const channelMembers = async () => {
108+
try {
109+
// Fetches channel members
110+
const channelMembersResponse = await axios({
111+
method: "get",
112+
url: `${rcApiDomain}/api/v1/channels.members`,
113+
headers: {
114+
"X-Auth-Token": Cookies.get("rc_token"),
115+
"X-User-Id": Cookies.get("rc_uid"),
116+
},
117+
params: {
118+
roomName: props.location.pathname.split("/")[2],
119+
},
120+
});
121+
setChannelMembers(channelMembersResponse.data.members);
122+
} catch (error) {
123+
console.log(error);
124+
setIsLoggedOut(true);
125+
}
126+
};
83127
ghRepoInfo();
128+
channelMembers();
84129
}, [props.location.pathname]);
85130

86131
const [activeTab, setActiveTab] = useState(0);
@@ -95,6 +140,10 @@ export default function ChannelInfo(props) {
95140
setActiveTab(newValue);
96141
};
97142

143+
const handleCloseMembersDialog = () => {
144+
setOpenMembersDialog(false);
145+
};
146+
98147
return (
99148
<div className="channel-info-wrapper">
100149
<Tabs
@@ -115,8 +164,62 @@ export default function ChannelInfo(props) {
115164
/>
116165
</Tabs>
117166
<TabPanel value={activeTab} index={0}>
118-
{/* TODO: Users Online */}
119-
Users
167+
<div className="channel-info-wrapper">
168+
{!isLoggedOut ? (
169+
<>
170+
<Grid container spacing={2} style={{ marginBottom: "20px" }}>
171+
{channelMembers
172+
.filter(
173+
(user, index) => user.status === "online" && index <= 25
174+
)
175+
.map((user) => {
176+
return (
177+
<Grid
178+
key={user.username}
179+
item
180+
xs={2}
181+
style={{
182+
display: "flex",
183+
alignItems: "flex-start",
184+
position: "relative",
185+
}}
186+
>
187+
<img
188+
style={{
189+
width: "10px",
190+
height: "10px",
191+
zIndex: "2",
192+
position: "absolute",
193+
}}
194+
src={online}
195+
/>
196+
<img
197+
style={{
198+
width: "30px",
199+
zIndex: "1",
200+
marginLeft: "5px",
201+
}}
202+
src={`${rcApiDomain}/avatar/${user.username}`}
203+
/>
204+
</Grid>
205+
);
206+
})}
207+
</Grid>
208+
<Button
209+
variant="contained"
210+
color="primary"
211+
size="small"
212+
onClick={() => setOpenMembersDialog(true)}
213+
>
214+
See All
215+
</Button>
216+
</>
217+
) : (
218+
<div className="user-logged-out-message">
219+
Please sign in to view this information.
220+
</div>
221+
)}
222+
</div>
120223
</TabPanel>
121224
<TabPanel value={activeTab} index={1}>
122225
<div className="repo-info-wrapper">
@@ -177,6 +280,54 @@ export default function ChannelInfo(props) {
177280
)}
178281
</div>
179282
</TabPanel>
283+
<Dialog
284+
open={openMembersDialog}
285+
keepMounted
286+
onClose={handleCloseMembersDialog}
287+
aria-labelledby="alert-dialog-slide-title"
288+
aria-describedby="alert-dialog-slide-description"
289+
TransitionComponent={Transition}
290+
maxWidth="sm"
291+
fullWidth={true}
292+
scroll="paper"
293+
>
294+
<DialogTitle>Channel Members</DialogTitle>
295+
<DialogContent>
296+
<Grid container spacing={2} style={{ margin: "10px 0px" }}>
297+
{channelMembers.map((user) => {
298+
return (
299+
<Grid
300+
key={user.username}
301+
item
302+
md={4}
303+
style={{
304+
display: "flex",
305+
alignItems: "flex-start",
306+
position: "relative",
307+
}}
308+
>
309+
<img
310+
style={{ width: "30px" }}
311+
src={`${rcApiDomain}/avatar/${user.username}`}
312+
/>
313+
<div
314+
style={{
315+
display: "flex",
316+
flexDirection: "column",
317+
marginLeft: "5px",
318+
}}
319+
>
320+
<span style={{ fontWeight: "bold" }}>{user.name}</span>
321+
<span style={{ fontSize: "x-small" }}>
322+
@{user.username}
323+
</span>
324+
</div>
325+
</Grid>
326+
);
327+
})}
328+
</Grid>
329+
</DialogContent>
330+
</Dialog>
180331
</div>
181332
);
182333
}

client/src/images/online.png

13.4 KB
Loading

0 commit comments

Comments
 (0)