Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating group chats #19

Merged
merged 7 commits into from
Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ const config = require('./config')
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');
const logoutRoute = require('./routes/logoutRoutes')
const postsApiRoute = require('./routes/api/posts')
const postRoute = require('./routes/postRoutes')
const profileRoute = require('./routes/profileRoutes')
const userRoute = require('./routes/api/users')
const uploadRoute = require('./routes/uploadRoutes')
const searchRoute = require('./routes/searchRoutes')
const messagesRoute = require('./routes/messagesRoutes')
const usersApiRoute = require('./routes/api/users')
const postsApiRoute = require('./routes/api/posts')
const chatsApiRoute = require('./routes/api/chats')

const app = express();
const PORT = 3003;
Expand All @@ -40,10 +42,12 @@ app.use("/logout", logoutRoute);
app.use("/register", registerRoute);
app.use("/posts", middleware.requireLogin, postRoute);
app.use("/profile", middleware.requireLogin, profileRoute);
app.use("/api/posts", postsApiRoute);
app.use("/api/users", userRoute);
app.use("/uploads", uploadRoute);
app.use("/search", middleware.requireLogin, searchRoute)
app.use("/search", middleware.requireLogin, searchRoute);
app.use("/messages", middleware.requireLogin, messagesRoute);
app.use("/api/posts", postsApiRoute);
app.use("/api/users", usersApiRoute);
app.use("/api/chats", chatsApiRoute);


app.get("/", middleware.requireLogin, (req, res, next) => {
Expand Down
49 changes: 49 additions & 0 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -442,4 +442,53 @@ button span {
background-color: var(--lightGrey);
border: none;
color: var(--greyText);
}

.chatPageContainer {
display: flex;
flex-direction: column;
min-height: 0;
}

.chatTitleBar {
border-bottom: 1px solid var(--lightGrey);
display: flex;
align-items: center;
min-height: 60px;
padding: 10px;
}

.chatTitleBar label {
margin: 0 10px 0 0;
}

#userSearchTextbox {
border: none;
flex: 1;
font-weight: 200;
min-width: 350px;
}

#createChatButton {
border: none;
background-color: var(--blue);
color: #fff;
padding: 7px 20px;
margin: 10px auto;
border-radius: 40px;
}

#createChatButton:disabled {
background-color: var(--lightGrey);
color: var(--greyText);
}

.selectedUser {
font-weight: 300;
background-color: #cbe5fe;
color: #0084ff;
padding: 5px;
border-radius: 3px;
margin: 5px 5px 0 0;
display: inline-block;
}
97 changes: 91 additions & 6 deletions public/js/common.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
let cropper
let cropper;
let timer;
let selectedUsers = [];

$("#postTextarea, #replyTextarea").keyup(event => {
const textbox = $(event.target)
Expand Down Expand Up @@ -224,15 +226,15 @@ $("#coverPhoto").change(function(){
})

$("#coverPhotoButton").click(() => {
var canvas = cropper.getCroppedCanvas();
let canvas = cropper.getCroppedCanvas();

if(canvas == null) {
alert("Отсутствует картинка. Загрузите желаемое фото обложки.");
return;
}

canvas.toBlob((blob) => {
var formData = new FormData();
let formData = new FormData();
formData.append("croppedImage", blob);

$.ajax({
Expand All @@ -246,6 +248,34 @@ $("#coverPhotoButton").click(() => {
})
})

$("#userSearchTextbox").keydown((event) => {
clearTimeout(timer);
let textbox = $(event.target);
let value = textbox.val();

if (value == "" && (event.which == 8 || event.keyCode == 8)) {
selectedUsers.pop();
updateSelectedUsersHtml();
$(".resultsContainer").html("");

if (selectedUsers.length == 0) {
$("#createChatButton").prop("disabled", true)
}

return;
}

timer = setTimeout(() => {
value = textbox.val().trim();

if (value == "") {
$(".resultsContainer").html("");
} else {
searchUsers(value);
}
}, 1000)
})

$(document).on("click", ".likeButton", (event) => {
const button = $(event.target);
const postId = getPostIdFromElement(button);
Expand All @@ -267,6 +297,17 @@ $(document).on("click", ".likeButton", (event) => {
})
})

$("#createChatButton").click(() => {
const data = JSON.stringify(selectedUsers);

$.post("/api/chats", { users: data }, chat => {

if (!chat || chat._id) return alert("Отсуствует айди чата")

window.location.href = `/messages/${chat._id}`;
})
})

$(document).on("click", ".retweetButton", (event) => {
const button = $(event.target);
const postId = getPostIdFromElement(button);
Expand Down Expand Up @@ -333,7 +374,6 @@ $(document).on("click", ".followButton", (event) => {
})
})


function getPostIdFromElement(element) {
const isRoot = element.hasClass("post");
const rootElement = isRoot == true ? element : element.closest(".post");
Expand Down Expand Up @@ -488,7 +528,6 @@ function timeDifference(current, previous) {
}
}


function outputPosts(results, container) {
container.html("");

Expand Down Expand Up @@ -523,7 +562,6 @@ function outputPostsWithReplies(results, container) {
});
}


function outputUsers(results, container) {
container.html("");

Expand Down Expand Up @@ -565,4 +603,51 @@ function createUserHtml(userData, showFollowButton) {
</div>
${followButton}
</div>`;
}

function searchUsers(searchTerm) {
$.get("/api/users", { search: searchTerm }, results => {
outputSelectableUsers(results, $(".resultsContainer"));
})
}

function outputSelectableUsers(results, container) {
container.html("");

results.forEach(result => {

if (result._id == userLoggedIn._id || selectedUsers.some(u => u._id == result._id)) {
return;
}

const html = createUserHtml(result, false);
let element = $(html);
element.click(() => userSelected(result))
container.append(element);
});

if(results.length == 0) {
container.append("<span class='noResults'>Ещё нет ниодной записи</span>")
}
}

function userSelected(user) {
selectedUsers.push(user);
updateSelectedUsersHtml();
$("#userSearchTextbox").val("").focus();
$(".resultsContainer").html("");
$("#createChatButton").prop("disabled", false)
}

function updateSelectedUsersHtml() {
let elements = [];

selectedUsers.forEach(user => {
const name = user.firstName + " " + user.lastName
const userElement = $(`<span class='selectedUser'>${name}</span>`);
elements.push(userElement);
})

$(".selectedUser").remove();
$("#selectedUsers").prepend(elements);
}
Empty file added public/js/inboxPage.js
Empty file.
2 changes: 0 additions & 2 deletions public/js/search.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
let timer;

$("#searchBox").keydown((event) => {
clearTimeout(timer);
let textbox = $(event.target);
Expand Down
38 changes: 38 additions & 0 deletions routes/api/chats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const router = express.Router();
const Chat = require('../../schemas/chatSchema')

app.use(bodyParser.urlencoded({ extended: false }));

router.post("/", async (req, res, next) => {
if (!req.body.users) {
console.log("Параметры пользователя не были отправлены в теле запроса");
return res.sendStatus(400);
}

const users = JSON.parse(req.body.users)

if (users.length == 0) {
console.log("Массив пользователей пуст");
return res.sendStatus(400);
}

users.push(req.session.user);
const chatData = {
users: users,
isGroupChat: true
};

Chat.create(chatData)
.then(results => res.status(200).send(results))
.catch(error => {
console.log(error);
res.sendStatus(400);
})
})



module.exports = router;
26 changes: 26 additions & 0 deletions routes/messagesRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const express = require('express');
const User = require('../schemas/UserSchema');

const app = express();
const router = express.Router();

router.get("/", (req, res, next) => {
res.status(200).render("inboxPage.pug", {
pageTitle: "Входящие сообщения",
userLoggedIn: req.session.user,
userLoggedInJs: JSON.stringify(req.session.user)
});
})

router.get("/new", (req, res, next) => {

res.status(200).render("newMessage.pug", {
pageTitle: "Новое сообщение",
userLoggedIn: req.session.user,
userLoggedInJs: JSON.stringify(req.session.user)
});
})



module.exports = router;
23 changes: 23 additions & 0 deletions schemas/chatSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const {Schema, model} = require('mongoose')

const ChatSchema = new Schema({
chatName: {
type: String,
trim: true
},
isGroupChat: {
type: Boolean,
default: false
},
users: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
latestMessage: {
type: Schema.Types.ObjectId,
ref: 'Message'
}
}, {timestamps: true})

const Chat = model('Chat', ChatSchema);
module.exports = Chat;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions views/inboxPage.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
extends layouts/main-layout.pug

block content
.resultsContainer

block headerButton
a(href="/messages/new")
i.far.fa-plus-square

block scripts
script(src="/js/inboxPage.js")
1 change: 1 addition & 0 deletions views/layouts/main-layout.pug
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ html(lang="en")
.mainSectionContainer.col-10.col-md-8.col-lg-6
.titleContainer
h1 #{pageTitle}
block headerButton

block content

Expand Down
10 changes: 10 additions & 0 deletions views/newMessage.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extends layouts/main-layout.pug

block content
.chatPageContainer
.chatTitleBar
label(for="userSearchTextbox") Кто:
#selectedUsers
input#userSearchTextbox(type="text", placeholder="Введите имя необходимого пользователя")
.resultsContainer
button#createChatButton(disabled) Создать переписку