diff --git a/public/css/main.css b/public/css/main.css index da188b8..58dd942 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -1,22 +1,20 @@ :root { - --blue: #1fa2f1; - --blueBackhround: rgba(212, 237, 255, 0.6); + --blue: #1FA2F1; + --blueLight: #9BD1F9; + --blueBackground: rgba(212, 237, 255, 0.6); --buttonHoverBg: #d4edff; --lightGrey: rgb(230, 236, 240); --spacing: 15px; - --blueLight: #9bd1f9; --greyText: rgb(101, 119, 134); - --greyButtonText: rgba(0, 0, 0, 0.34); - --red: rgb(226, 34, 94); - --green: rgb(23, 191, 99); - --greenBackground: rgba(23, 191, 99, 0.1); - --redBackground: rgba(226, 34, 94, 0.34); - -} + --greyButtonText: rgba(0,0,0,0.34); + --red: rgb(226,34,94); + --redBackground: rgba(226,34,94,0.1); + --green: rgb(23,191,99); + --greenBackground: rgba(23,191,99,0.1); +} * { outline: none !important; - } a { @@ -49,10 +47,11 @@ nav a { display: flex; align-items: center; justify-content: center; + color: #212529; } nav a.blue { - color: var(--blue) + color: var(--blue); } nav a:hover { @@ -71,14 +70,13 @@ button { color: var(--greyButtonText); } - button i, button span { pointer-events: none; } .mainSectionContainer { - padding: 0; + padding: 0; border-left: 1px solid var(--lightGrey); border-right: 1px solid var(--lightGrey); display: flex; @@ -90,7 +88,7 @@ button span { padding: 0 var(--spacing); display: flex; align-items: center; - border-bottom: 10px solid var(--lightGrey); + border-bottom: 1px solid var(--lightGrey); flex-shrink: 0; } @@ -105,7 +103,6 @@ button span { flex-shrink: 0; } - .modal .postFormContainer { border: none; padding: 0; @@ -114,7 +111,6 @@ button span { .modal .post { padding: 0 0 var(--spacing) 0; - padding-bottom: var(--spacing); } .userImageContainer { @@ -133,7 +129,7 @@ button span { padding-left: var(--spacing); } -.textareaContainer textarea{ +.textareaContainer textarea { width: 100%; border: none; resize: none; @@ -175,7 +171,7 @@ button span { .username, .date { - color: var(--greyText); + color: var(--greyText) } .displayName { @@ -211,28 +207,26 @@ button span { border-radius: 50%; } - .postButtonContainer.red button.active { color: var(--red); -} - +} .postButtonContainer.red button:hover { color: var(--red); - background-color: var(--redBackground); -} + background-color: var(--redBackground) +} .postButtonContainer.green button.active { color: var(--green); -} +} .postButtonContainer.green button:hover { color: var(--green); - background-color: var(--greenBackground); + background-color: var(--greenBackground) } .postActionContainer { - padding-left: 45px; + padding-left: 35px; font-size: 13px; color: var(--greyText); margin-bottom: 5px; @@ -260,21 +254,22 @@ button span { } .errorMessage { - padding: var(--spacing) + padding: var(--spacing); } -.profileHeaderContainer .coverPhotoContainer { +.coverPhotoSection { height: 180px; background-color: var(--blue); position: relative; } .profileHeaderContainer .userImageContainer { - height: 132px; width: 132px; + height: 132px; margin-left: var(--spacing); position: absolute; bottom: -66px; + display: flex; align-items: center; justify-content: center; @@ -323,7 +318,7 @@ button span { } .followersContainer span:not(.value) { - color: var(--greyText) + color: var(--greyText); } .followersContainer a { @@ -334,7 +329,6 @@ button span { border-bottom: 1px solid #000; } - .tabsContainer { display: flex; border-bottom: 1px solid var(--lightGrey); @@ -358,7 +352,7 @@ button span { .tab:hover { color: var(--blue); - background-color: var(--blueBackhround); + background-color: var(--blueBackground); } .noResults { @@ -381,18 +375,34 @@ button span { padding: 0 var(--spacing) } -.profilePictureButton { +.profilePictureButton, +.coverPhotoButton { position: absolute; font-size: 50px; - color: rgba(0,0,00.6); + color: rgba(0,0,0,0.6); display: none; } -.userImageContainer:hover .profilePictureButton { +.userImageContainer:hover .profilePictureButton, +.coverPhotoSection:hover .coverPhotoButton { display: block; } -#imagePreview { +.coverPhotoContainer { + display: flex; + align-items: center; + justify-content: center; + height: 100%; +} + +.coverPhotoContainer img { + width: 100%; + height: 100%; + object-fit: cover; +} + +#imagePreview, +#coverPreview { width: 100%; display: block; max-width: 100%; diff --git a/public/images/profilePic.jpg b/public/images/profilePic.jpg index a8ac7e3..3993a1f 100644 Binary files a/public/images/profilePic.jpg and b/public/images/profilePic.jpg differ diff --git a/public/js/common.js b/public/js/common.js index b110a35..69fb3c0 100644 --- a/public/js/common.js +++ b/public/js/common.js @@ -108,6 +108,27 @@ $("#filePhoto").change(function() { } }) +$("#coverPhoto").change(function() { + if (this.files && this.files[0]) { + const reader = new FileReader(); + reader.onload = (event) => { + const image = document.getElementById("coverPreview") + image.src = event.target.result + + if (cropper !== undefined) { + cropper.destroy() + } + + cropper = new Cropper(image, { + aspectRatio: 16 / 9, + background: false + }) + + } + reader.readAsDataURL(this.files[0]); + } +}) + $("#imageUploadButton").click(() => { const canvas = cropper.getCroppedCanvas(); @@ -131,6 +152,50 @@ $("#imageUploadButton").click(() => { }) }) +$("#coverPhoto").change(function(){ + if(this.files && this.files[0]) { + var reader = new FileReader(); + reader.onload = (e) => { + var image = document.getElementById("coverPreview"); + image.src = e.target.result; + + if(cropper !== undefined) { + cropper.destroy(); + } + + cropper = new Cropper(image, { + aspectRatio: 16 / 9, + background: false + }); + + } + reader.readAsDataURL(this.files[0]); + } +}) + +$("#coverPhotoButton").click(() => { + var canvas = cropper.getCroppedCanvas(); + + if(canvas == null) { + alert("Отсутствует картинка. Загрузите желаемое фото обложки."); + return; + } + + canvas.toBlob((blob) => { + var formData = new FormData(); + formData.append("croppedImage", blob); + + $.ajax({ + url: "/api/users/coverPhoto", + type: "POST", + data: formData, + processData: false, + contentType: false, + success: () => location.reload() + }) + }) +}) + $(document).on("click", ".likeButton", (event) => { const button = $(event.target); const postId = getPostIdFromElement(button); diff --git a/routes/api/users.js b/routes/api/users.js index 0d7267a..a0d1ee0 100644 --- a/routes/api/users.js +++ b/routes/api/users.js @@ -78,5 +78,27 @@ router.post("/profilePicture", upload.single("croppedImage"), async (req, res, n }) }) +router.post("/coverPhoto", upload.single("croppedImage"), async (req, res, next) => { + if(!req.file) { + console.log("Отсутствует файл, который должен прийти в запросе от ajax."); + return res.sendStatus(400); + } + + var filePath = `/uploads/images/${req.file.filename}.png`; + var tempPath = req.file.path; + var targetPath = path.join(__dirname, `../../${filePath}`); + + fs.rename(tempPath, targetPath, async error => { + if(error != null) { + console.log(error); + return res.sendStatus(400); + } + + req.session.user = await User.findByIdAndUpdate(req.session.user._id, { coverPhoto: filePath }, { new: true }); + res.sendStatus(204); + }) + +}); + module.exports = router; \ No newline at end of file diff --git a/schemas/UserSchema.js b/schemas/UserSchema.js index 93042f9..981e05f 100644 --- a/schemas/UserSchema.js +++ b/schemas/UserSchema.js @@ -32,6 +32,9 @@ const UserSchema = new Schema({ type: String, default: "/images/profilePic.jpg" }, + coverPhoto: { + type: String + }, likes: [{ type: Schema.Types.ObjectId, ref: 'Post' diff --git a/uploads/images/51c53395ef8f8cbf1f74ece7739f4a4c.png b/uploads/images/51c53395ef8f8cbf1f74ece7739f4a4c.png deleted file mode 100644 index 7307168..0000000 Binary files a/uploads/images/51c53395ef8f8cbf1f74ece7739f4a4c.png and /dev/null differ diff --git a/uploads/images/a1f3bfc263b38e3b678103102039b186.png b/uploads/images/a1f3bfc263b38e3b678103102039b186.png new file mode 100644 index 0000000..cab7efa Binary files /dev/null and b/uploads/images/a1f3bfc263b38e3b678103102039b186.png differ diff --git a/uploads/images/a42916190f0f7afe2d848578c5cfdb5c.png b/uploads/images/a42916190f0f7afe2d848578c5cfdb5c.png deleted file mode 100644 index 01c42e7..0000000 Binary files a/uploads/images/a42916190f0f7afe2d848578c5cfdb5c.png and /dev/null differ diff --git a/uploads/images/a74ef3d2e8cd84e87aa23b26323eb129.png b/uploads/images/a74ef3d2e8cd84e87aa23b26323eb129.png new file mode 100644 index 0000000..d45da60 Binary files /dev/null and b/uploads/images/a74ef3d2e8cd84e87aa23b26323eb129.png differ diff --git a/uploads/images/aef34c648a009bf7f4e8210a55e9419a.png b/uploads/images/aef34c648a009bf7f4e8210a55e9419a.png deleted file mode 100644 index 3315411..0000000 Binary files a/uploads/images/aef34c648a009bf7f4e8210a55e9419a.png and /dev/null differ diff --git a/uploads/images/fcd0445dbc4ca51a43246b4f78c35031.png b/uploads/images/fcd0445dbc4ca51a43246b4f78c35031.png new file mode 100644 index 0000000..9f1c20c Binary files /dev/null and b/uploads/images/fcd0445dbc4ca51a43246b4f78c35031.png differ diff --git a/views/mixins/mixins.pug b/views/mixins/mixins.pug index 3bb38bb..3c3ffec 100644 --- a/views/mixins/mixins.pug +++ b/views/mixins/mixins.pug @@ -74,4 +74,21 @@ mixin createImageUploadModal() .modal-footer button.btn.btn-secondary(type='button' data-dismiss='modal') Отменить - button#imageUploadButton.btn.btn-primary(type='button') Сохранить \ No newline at end of file + button#imageUploadButton.btn.btn-primary(type='button') Сохранить + +mixin createCoverPhotoUploadModal() + #coverPhotoUploadModal.modal.fade(tabindex='-1', role='dialog', aria-labelledby='coverPhotoModalLabel', aria-hidden='true') + .modal-dialog(role='document') + .modal-content + .modal-header + h5#coverPhotoModalLabel.modal-title Изменить фото обложки + button.close(type='button', data-dismiss='modal', aria-label='Close') + span(aria-hidden='true') × + .modal-body + input#coverPhoto(type="file", name="filePhoto") + + .coverPhotoPreviewContainer + img#coverPreview + .modal-footer + button.btn.btn-secondary(type='button', data-dismiss='modal') Отменить + button#coverPhotoButton.btn.btn-primary(type='button') Сохранить \ No newline at end of file diff --git a/views/profilePage.pug b/views/profilePage.pug index 7580bc2..163ea05 100644 --- a/views/profilePage.pug +++ b/views/profilePage.pug @@ -12,7 +12,14 @@ block content - followingCount = profileUser.following.length .profileHeaderContainer - .coverPhotoContainer + .coverPhotoSection + .coverPhotoContainer + if profileUser.coverPhoto + img(src=profileUser.coverPhoto, alt="Обложка пользователя") + + if profileUser._id == userLoggedIn._id + button.coverPhotoButton(data-toggle="modal", data-target="#coverPhotoUploadModal") + i.fas.fa-camera .userImageContainer img(src=profileUser.profilePic, alt="Фото пользователя") @@ -53,6 +60,7 @@ block content +createPostModals(userLoggedIn) +createImageUploadModal() + +createCoverPhotoUploadModal() block scripts script(src="/js/profile.js") \ No newline at end of file