[TIL] 211216

Lee Syong·2021년 12ė›” 16ėž
0

TIL

ëŠĐ록 ëģīęļ°
120/204
post-thumbnail

📝 ė˜Ī늘 한 ęēƒ

  1. flash messages - express-flash / req.flash() / messages.key / keyframes / animation ė†ė„ą / position: absolute & margin: 0 auto

📚 ë°°ėšī ęēƒ

1. flash messages

ėš”ėē­ė— 대한 ė‘ë‹ĩėœžëĄœ pug 파ėžė„ 렌더링한 ęē―ėš°ė—ëŠ” 템플ëĶŋė— ëģ€ėˆ˜ëĨž ęģĩėœ í•ĻėœžëĄœėĻ ëДė‹œė§€ëĨž 띄ėšļ ėˆ˜ ėžˆë‹Ī.

대ė‹  ėš”ėē­ė— 대한 ė‘ë‹ĩėœžëĄœ redirectëĨž ė‚ŽėšĐ한 ęē―ėš°ė—ëŠ” ė‚ŽėšĐėžė—ęēŒ ę·ļ ėīėœ ëĨž ė•Œë ĪėĢžęģ  ė‹ķë‹ĪëĐī flash messgeëĨž ė‚ŽėšĐ할 ėˆ˜ ėžˆë‹Ī.

1) express-flash

express-flashëĨž ė„Īėđ˜í•œë‹Ī.

$ npm i express-flash

flash ëŊļë“Īė›Ļė–ī import 한 후 ė‚ŽėšĐ할 ėˆ˜ ėžˆë„록 한ë‹Ī.
ėīëĨž í†ĩí•ī flash ëŊļë“Īė›Ļė–ī는 sessionė— ė—°ęē°í•˜ė—Ž í•īë‹đ userė—ęēŒë§Œ ëДė‹œė§€ëĨž ëģīė—ŽėĪ„ ėˆ˜ ėžˆë‹Ī.
ėī는 ėžíšŒė„ą ëДė‹œė§€ëĄœ 한ëēˆ ëģīė—ŽėĢžęģ  나ëĐī express가 cacheė—ė„œ ė§€ė›Œëē„ëĶ°ë‹Ī.

// server.js
import session from "express-session";
import flash from "express-flash"; // express-session ëģīë‹Ī ë’Īė—ė„œ import í•īė•ž 한ë‹Ī ❗

app.use(flash());

2) req.flash()

req.flash("ëДė‹œė§€ 타ėž…", "ëДė‹œė§€ ë‚īėšĐ");

flash ëŊļë“Īė›Ļė–īëĨž ė„Īėđ˜í•˜ëĐī req.flash() í•Ļėˆ˜ëĨž ė‚ŽėšĐí•ī falsh messageëĨž 만ë“Ī ėˆ˜ ėžˆë‹Ī.
ėƒí™Đė— ė•Œë§žė€ ëДė‹œė§€ë“Īė„ 만ë“Īė–ī ëŊļë“Īė›Ļė–īė™€ ėŧĻíŠļëĄĪ럮ė— ėķ”ę°€í•˜ë„ëĄ 한ë‹Ī.

middleware.js

const protectorMiddleware = () => {
  if (req.session.loggedIn) {
    next();
  } else {
    req.flash("info", "Not Authorized");
    return res.redirect("/login");
  }
};

const publicOnlyMiddleware = () => {
  if (!req.session.loggedIn) {
    next();
  } else {
    req.flash("info", "Not Authorized");
    return res.redirect("/");
  }
};

userController.js

export const finishGithubLogin = async (req, res) => {
  
  // ėĪ‘ëžĩ
  
  if ("access_token" in tokenRequest) {
    
    // ėĪ‘ëžĩ
    
    // github APIė˜ userė˜ ėœ íšĻ한 ėīëДėžėī ė—†ė„ ė‹œ
    if (!emailObj) {
      req.flash("error", "No valid email.");
      return res.redirect("/login");
    }
    
    // ėĪ‘ëžĩ
    
  } else {
    // ė•Ąė„ļėŠĪ 토큰ėī ė—†ė„ ė‹œ
    req.flash("error", "No access token");
    return res.redirect("/login");
  }
};

// 로ę·ļė•„ė›ƒ ė‹œ
export const logout = (req, res) => {
  req.session.destroy();
  req.flash("info", "Bye bye");
  return res.redirect("/");
};

// github로 ęģ„ė • 만든 user가 íŒĻėŠĪė›Œë“œëĨž ëģ€ęē―하ë Īęģ  할 때
export const getChangePassword = async (req, res) => {
  if (req.session.user.socialOnly === true) {
    req.flash("error", "Can't change password.");
    return res.redirect("/");
  }
  return res.render("change-password", { pageTitle: "Change Password" });
};

// íŒĻėŠĪė›Œë“œ ė—…데ėīíŠļ ė‹œ
export const postChangePassword = async (req, res) => {
  
  // ėĪ‘ëžĩ
  
  req.flash("info", "Password updated");
  return res.redirect("/users/logout");
};

videoController.js

// ėˆ˜ė •í•˜ë Ī는 ëđ„ë””ė˜Īė˜ ė†Œėœ ėžę°€ ė•„닐 때
export const getEdit = async (req, res) => {
  // ėĪ‘ëžĩ
  
  if (String(video.owner) !== _id) {
    req.flash("error", "Not Authorized");
    return res.status(403).redirect("/");
  }

  // ėĪ‘ëžĩ
};

// ėˆ˜ė •í•˜ë Ī는 ëđ„ë””ė˜Īė˜ ė†Œėœ ėžę°€ ė•„닐 때
export const postEdit = async (req, res) => {
  // ėĪ‘ëžĩ
  
  if (String(video.owner) !== _id) {
    req.flash("error", "Not Authorized");
    return res.status(403).redirect("/");
  }
  
  // ėĪ‘ëžĩ
};

// ëđ„ë””ė˜Ī ė‚­ė œ ė‹œ
export const deleteVideo = async (req, res) => {  
  // ėĪ‘ëžĩ
  
  if (String(video.owner) !== _id) {
    req.flash("error", "Not Authorized");
    return res.status(403).redirect("/");
  }

  // ėĪ‘ëžĩ  
};

3) messages.key

req.flash()ëĨž í†ĩí•ī ëДė‹œė§€ëĨž 만ë“ĪëĐī, í•īë‹đ ëДė‹œė§€ę°€ ë‹īęļī messages ëģ€ėˆ˜ę°€ 만ë“Īė–īė§„ë‹Ī.
pug 파ėžė—ė„œ messages.key 값ė„ ė‚ŽėšĐí•ī í•īë‹đ ëДė‹œė§€ëĨž ëģīė—ŽėĪ„ ėˆ˜ ėžˆë‹Ī.

각ęļ° ë‹ĪëĨļ ëДė‹œė§€ë“Īė„ 같ė€ 형태로 ëģīė—ŽėĢžęļ° ėœ„í•ī mixins íī더ė— message.pug 파ėžė„ ėž‘ė„ąí•œ 후 base.pug 파ėžė— include 했ë‹Ī.

message.pug

mixin message(kind, text)
  div.message(class=kind)
    span=text

base.pug

include mixins/message

doctype html
html(lang="ko")
  head
    //- ėĪ‘ëžĩ
  body
    if (messages.error)
      +message("error", messages.error)
    if (messages.info)
      +message("info", messages.info)
    if (messages.success)
      +message("success", messages.success)
    include partials/header
    main
      block content
    include partials/footer

4) CSS ėŠĪ타ėžë§

// styles.scss

@keyframes goAway {
  from {
    transform: none;
    opacity: 1;
  }
  to {
    transform: translateY(-100px);
    opacity: 0;
  }
}

.message {
  position: absolute;
  right: 0;
  left: 0;
  margin: 0 auto;
  max-width: 200px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 1000px;
  animation: goAway 0.5s 3s ease-in-out forwards;
  color: white;
  &.error {
    background-color: $red;
  }
  &.info {
    background-color: $grey;
  }
  &.success {
    background-color: $blue;
  }
}

(1) keyframes

@keyframes ė• ë‹ˆëДėīė…˜ ėīëĶ„ {
  from {
  
  // ė• ë‹ˆëДėīė…˜ ė‹Ī행 ė „ ėŠĪ타ėž
  
  }
  to {
  
  // ė• ë‹ˆëДėīė…˜ ė‹Ī행 후 ėŠĪ타ėž
  
  }
}

ėĢžė˜í•  ė ė€ keyframesė€ 반드ė‹œ 'ęĩŽėēīė ėļ ėˆ˜ėđ˜ 값'ė„ ė§€ė •í•īė•žë§Œ ė •ėƒė ėœžëĄœ ėž‘동한ë‹Ī는 ęēƒėīë‹Ī.
ėĶ‰, ėˆ˜ėđ˜ 값ė„ ė ė„ 때 autoëĨž ė‚ŽėšĐ할 ėˆ˜ ė—†ë‹Ī.

(2) animation ė†ė„ą

css animation ėīė •ëĶŽ (transition, transform, translate, animation, @keyframes) ė°ļęģ 

animation: ėīëĶ„ | ė§€ė† ė‹œę°„ | ė§€ė—° ė‹œę°„ | ė§„í–‰ ë°Đė‹ | fill-mode ė†ė„ą

fromė—ė„œ ė§€ė—° ė‹œę°„만큞 ė‹œę°„ėī ė§€ë‚˜ëĐī, to가 ė§€ė •í•œ ė§„í–‰ ë°Đė‹ėœžëĄœ 발ėƒí•˜ęģ , to ėƒíƒœę°€ ė§€ė† ė‹œę°„만큞 ėīė–īė§„ë‹Ī.

fill-mode ė†ė„ąė€ ė• ë‹ˆëДėīė…˜ėī ė‹Ī행 ė „·후ė— 대ėƒė— ėŠĪ타ėžė„ ė ėšĐ하는 ë°Đëē•ė„ ė§€ė •í•œë‹Ī.
forwardsëĨž ė§€ė •í•˜ëĐī, ė§€ė† ė‹œę°„ėī ęē―ęģží•ī ė• ë‹ˆëДėīė…˜ėī 끝나도 to ėƒíƒœę°€ ęģ„ė† ėœ ė§€ëœë‹Ī.

(3) position: absoluteė— margin: 0 auto ė ėšĐ하ęļ°

CSS position property ė •ëĶŽ

ėš”ė†Œę°€ position: absolute ėƒíƒœėž 때 margin: 0 autoëĨž ė§€ė •í•˜ë”띞도 í•īë‹đ ėš”ė†ŒëŠ” ėĪ‘ė•™ ė •ë Žë˜ė§€ ė•ŠëŠ”ë‹Ī.
ėī때 í•īë‹đ ėš”ė†Œę°€ ëļ”록 레ëēĻ ėš”ė†Œėī더띾도 마ėđ˜ ėļ띞ėļ 레ëēĻ ėš”ė†Œėē˜ëŸž ėŧĻ텐ėļ ë§Œížė˜ 너ëđ„만ė„ 가ė§€ęēŒ 된ë‹Ī.

div {
  position: absolute;
  right: 0;
  margin: 0 auto;
}

position: absolute ėš”ė†ŒëĨž ėĪ‘ė•™ ė •ë Ží•˜ęļ° ėœ„í•īė„œëŠ” margin: 0 auto가 ëĻđ도록 left: 0ęģž right: 0ė„ ėķ”ę°€í•ī í•īë‹đ ėš”ė†Œę°€ ëķ€ëŠĻ 너ëđ„ëĨž ëŠĻ두 ė°Ļė§€í•˜ęēŒ 만ë“Īė–īė•ž 한ë‹Ī.

div {
  position: absolute;
  right: 0;
  left: 0;
  margin: 0 auto;
}

âœĻ ë‚īėž 할 ęēƒ

  1. comment section
profile
ëŠĨ동ė ėœžëĄœ ė‚īėž, 행ëģĩ하ęēŒðŸ˜

0개ė˜ 댓ęļ€