μ€μ μ½λλ githubμ μ¬λ¦Ό(wetube_v2)
νλ‘ν μ΄λ―Έμ§(avatar) / search / profile / edit / shared.scss
π‘ populate μ€μ²© μ¬μ©
// userController.js export const see = async (req, res) => { const { id } = req.params; const user = await User.findById(id).populate({ path: "videos", // populate μ€μ²© μ¬μ© populate: { path: "owner", model: "User", }, // λ΄λ¦Όμ°¨μ μ λ ¬ options: { sort: { createdAt: "desc" }, }, }); if (!user) { return res.status(404).render("404", { pageTitle: "User not found" }); } return res.render("profile", { pageTitle: user.name, user }); };
π‘ formμ font-awesome μμ΄μ½ λ£κΈ°
- input(type="submit") λμ μ button(type="submit")μ λ£μ΄μ€¬λ€.
//- search.pug div.form-container.form-container__search form.search-form(method="GET") input(name="keyword", placeholder="κ²μ", required) button.search-button i.fas.fa-search
- position: absolute λ₯Ό μ΄μ©ν΄ μμΉλ₯Ό μ‘μ쀬λ€.
// search.scss .form-container__search { border-style: none; box-shadow: none; margin-bottom: 4rem; padding: 0; } .search-form { position: relative; .search-button { border-style: none; background-color: transparent; color: $color-white; font-size: $font-regular; padding: 0; position: absolute; top: 50%; right: 0; transform: translateY(-50%); cursor: pointer; } }
π‘ νλ‘ν μ΄λ―Έμ§(avatar) λΉμ¨μ λ§μΆ° μνμΌλ‘ μλ₯΄κΈ°
background-image
μμ±μ μ΄μ©νλ€. loggedInUser.avatarUrl (header.pug) / user.avatarUrl (profile.pug) / video.owner.avatarUrl (video.pug) μ κ°μ κ°μ ΈμμΌ νκΈ° λλ¬Έμ background-image μμ±μ pug νμΌμμμΈλΌμΈ μ€νμΌ(inline style)
νμμΌλ‘ μΆκ°νλ€.
- avatarUrlμ΄ μλ κ²½μ°λ μΌλ¨ μμλ‘ μ΄λͺ¨ν°μ½μ λ£μ΄μ€¬λ€. λ°°ν¬ νμ AWS S3μμ κΈ°λ³Έ μ΄λ―Έμ§λ₯Ό κ°μ Έμ€λλ‘ μμ ν κ²μ΄λ€.
//- header.pug a(href=`/users/${loggedInUser._id}`) if !loggedInUser.avatarUrl span.profile-img π else if loggedInUser.socialOnly div.profile-img(style=`background-image: url("${loggedInUser.avatarUrl}");`) else div.profile-img(style=`background-image: url("/${loggedInUser.avatarUrl}");`)
// shared.scss .profile-img { width: 3rem; height: 3rem; border-radius: 50%; background-size: cover; background-position: center; }
cf. μ΄μ μ μΌλ λ°©λ²
div.profile-outer-box div.profile-inner-box a(href=`/users/${loggedInUser._id}`) if loggedInUser.socialOnly img(src=loggedInUser.avatarUrl, crossorigin).profile-img else img(src=loggedInUser.avatarUrl).profile-img
.profile-outer-box { width: 60px; .profile-inner-box { padding-top: 100%; overflow: hidden; position: relative; border-radius: 50%; .profile-img { width: 100%; height: 100%; object-fit: cover; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } } }
λΉμ₯ κ°λ€λ²λ¦¬μ.padding-top: %
κ΄λ ¨ν΄μ μκ³ μμ΄μΌ νκΈ΄ νμ§λ§κ·Έλλ λΉμ₯ κ°λ€λ²λ¦¬μ.
π‘ μ¬λ¬ μ€ λ¬Έμμ΄ μ€ λ°κΎΈκ³ μ¨κΈ°κΈ°
CSS / CSSλ‘ λ¬Έμμ΄ μλ₯΄κΈ° - ν μ€μΈ κ²½μ°, μ¬λ¬ μ€μΈ κ²½μ°,
word-break μμ±κ³Ό word-wrap μμ± μμ보기,
word-wrap μ€λ°κΏ μμ±(normal, break-word) μ°Έκ³//- video.scss div.video-mixin__info a(href=`/videos/${video.id}`).video-mixin__title=video.title
// video.scss .video-mixin__info { overflow: hidden; // μμΌλ‘ λμΉλ λΆλΆ μ¨κΉ .video-mixin__title { overflow: hidden; // λ°μΌλ‘ λμΉλ λΆλΆ μ¨κΉ line-height: 1.4rem; // 1μ€ λμ΄ μ€μ max-height: 2.8rem; // 2μ€ λ³΄μ¬μ£Όκ³ μΆμΌλκΉ 1.4 * 2 (height μ¬μ© x) word-break: break-all; // μμ λ¨μμμ μ€ λ°κΏ (μμ΄) word-wrap: break-word; // μμ λ¨μμμ μ€ λ°κΏ (νμ€μΌ μΈμ΄) // μ΄ν 3μ€ μ½λλ Chrome λ²κ·Έ(μ€ λ°κΏ μλ¨) λλ¬Έμ μΆκ°ν¨ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: $font-regular; } }
μ²μ ν λ κ΅μ₯ν μ΄λ €μ λ ννΈμΈλ° μλ‘κ² λ€λ₯Έ λ°©λ²λ€λ‘ λ€μ ν΄λ³΄λ©΄μ μ λ¦¬κ° μ‘°κΈ λ κ±° κ°λ€.