수업정리 쿠팡#4

최동민·2022년 6월 30일
0

Spring 수업정리

목록 보기
34/47

SessionInterceptor 추가

request.setAttribute("sessionEntity", sessionEntity);

UserService
만료시키는 것

UserController 로그아웃 구현

로그아웃을 누르면 로그아웃이 된다.

index.html 추가

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<!--/*@thymesVar id="userEntity" type="dev.dmchoi.coupang.entities.member.UserEntity"*/-->
<head>
    <meta charset="UTF-8">
    <title>쿠팡</title>
    <link th:href="@{/resources/stylesheets/common.css}" rel="stylesheet">
    <link th:href="@{/resources/stylesheets/index.css}" rel="stylesheet">
    <link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard-dynamic-subset.css" />
    <script src="https://kit.fontawesome.com/0d51ab0f86.js" crossorigin="anonymous"></script>
</head>
<body>
<th:block th:replace="~{fragments/header.html :: content}"></th:block>
<main class="main">
    <aside class="aside">
        카테고리 자리임
    </aside>
    <section class="content">
        <section class="controller">
            <a class="link selected" href="#">이름순</a>
            <a class="link" href="#">낮은가격순</a>
            <a class="link" href="#">높은가격순</a>
            <span class="spring"></span>
            <a class="link" th:href="@{/product/add}" th:if="${userEntity != null && userEntity.isAdmin() == true}">상품 등록</a>
        </section>
        <section class="products">
            <a class="product" href="#">
                <img alt="상품이미지" class="image" th:src="@{/resources/images/test-product-image.jpg}">
                <span class="title">니베아 맨 센서티브 쉐이빙 폼</span>
                <span class="price">
                    <span class="number">8,920</span>
                    <span class="won"></span>
                    <img alt="로켓프레시" class="rocket" th:src="@{resources/images/rocket-fresh.png}">
                </span>
                <span class="due">7/9(토) 새벽 도착 보장</span>
                <span class="stars three">
                    <i class="star one two three four five fa-solid fa-star"></i>
                    <i class="star two three four five fa-solid fa-star"></i>
                    <i class="star three four five fa-solid fa-star"></i>
                    <i class="star four five fa-solid fa-star"></i>
                    <i class="star five fa-solid fa-star"></i>
                </span>
            </a>
            <a class="product" href="#">
                <img alt="상품이미지" class="image" th:src="@{/resources/images/test-product-image.jpg}">
                <span class="title">니베아 맨 센서티브 쉐이빙 폼</span>
                <span class="price">
                    <span class="number">8,920</span>
                    <span class="won"></span>
                    <img alt="로켓프레시" class="rocket" th:src="@{resources/images/rocket-fresh.png}">
                </span>
                <span class="due">7/9(토) 새벽 도착 보장</span>
                <span class="stars three">
                    <i class="star one two three four five fa-solid fa-star"></i>
                    <i class="star two three four five fa-solid fa-star"></i>
                    <i class="star three four five fa-solid fa-star"></i>
                    <i class="star four five fa-solid fa-star"></i>
                    <i class="star five fa-solid fa-star"></i>
                </span>
            </a>
        </section>
    </section>
</main>
</body>
</html>

index.css 추가

index.main.css 추가

@charset "UTF-8";

body > .main {
    width: var(--content-max-width);
    align-items: flex-start;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
}

body > .main > .aside {
    border: 0.0625rem solid rgb(229, 229, 229);
    border-top: none;
    margin-right: 1rem;
}

body > .main > .content {
    flex: 1;
}

body > .main > .content > .controller {
    background-color: rgb(239, 239, 239);
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-top: 1rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
}

body > .main > .content > .controller > .spring {
    flex: 1;
}

body > .main > .content > .controller > .link:hover {
    color: rgb(66, 132, 243);
}

body > .main > .content > .controller > .link.selected {
    color: rgb(66, 132, 243);
    cursor: default;
    font-weight: 500;
    pointer-events: none;
}

body > .main > .content > .controller > .link + .link {
    margin-left: 0.5rem;
}

body > .main > .content > .products {
    display: grid;
    grid-gap: 1.5rem;
    grid-template-columns: repeat(3, 1fr);
}

body > .main > .content > .products > .product {
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}

body > .main > .content > .products > .product > .image {
    width: 100%;
    margin-bottom: 0.75rem;
}

body > .main > .content > .products > .product > .title {
    margin-bottom: 0.5rem;
    text-align: justify;
}

body > .main > .content > .products > .product:hover > .title {
    color: rgb(66, 132, 243);
    text-decoration: underline;
}

body > .main > .content > .products > .product > .price {
    align-items: center;
    color: rgb(174, 0, 0);
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-bottom: 0.2rem;
}

body > .main > .content > .products > .product > .price > .number {
    font-size: 1.125rem;
    font-weight: 600;
}

body > .main > .content > .products > .product > .price > .rocket {
    height: 1.25rem;
    margin-left: 0.5rem;
}

body > .main > .content > .products > .product > .due {
    color: rgb(0, 137, 26);
    margin-bottom: 0.375rem;
}

body > .main > .content > .products > .product > .stars {
    color: rgb(205, 205, 205);
    letter-spacing: -0.125rem;
}

body > .main > .content > .products > .product > .stars.one > .star.one {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.two > .star.two {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.three > .star.three {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.four > .star.four {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.five > .star.five {
    color: rgb(255,151,0);
}

ProductController
RequestAttribute을 사용하게 되면 아래 내용을 하지 않아도 된다.

if (request.getAttribute("sessionEntity") instanceof SessionEntity) {
SessionEntity sessionEntity = (SessionEntity) request.getAttribute("sessionEntity");
this.userService.expireSession(sessionEntity);     

required = true 이면
비회원 시 들어가면 오류가 터지고, false 해놓으면 null이 들어감 false로 변경

로그인을 안했거나 관리자가 아닐 경우 404페이지로.

product/add.html 추가

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<!--/*@thymesVar id="userEntity" type="dev.dmchoi.coupang.entities.member.UserEntity"*/-->
<head>
    <meta charset="UTF-8">
    <title>쿠팡</title>
    <link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard-dynamic-subset.css" />
    <link th:href="@{/resources/stylesheets/common.css}" rel="stylesheet">
    <link th:href="@{/product/resources/stylesheets/add.css}" rel="stylesheet">
    <script src="https://kit.fontawesome.com/0d51ab0f86.js" crossorigin="anonymous"></script>
    <script defer th:src="@{/resources/libraries/ckeditor/ckeditor.js}"></script>
    <script defer th:src="@{/product/resources/scripts/add.js}"></script>
</head>
<body>
<th:block th:replace="~{fragments/header.html :: content}"></th:block>
<form class="main" method="post">
    <label class="label">
        <span class="hint">제목</span>
        <input autofocus class="input" min="100" name="title" placeholder="상품 제목을 입력해주세요" type="text">
    </label>
    <label class="label">
        <span class="hint">가격</span>
        <input class="input" min="100" max="99999990" name="price" placeholder="판매 가격을 입력해주세요" step="10" type="number">
    </label>
    <label class="label">
        <span class="hint">배송</span>
        <label class="label">
            <input checked class="input" name="delivery" type="radio" value="normal">
            <span class="checker"></span>
            <span class="text">일반</span>
        </label>
        <label class="label">
            <input class="input" name="delivery" type="radio" value="rocket">
            <span class="checker"></span>
            <span class="text">로켓</span>
        </label>
        <label class="label">
            <input class="input" name="delivery" type="radio" value="rocketFresh">
            <span class="checker"></span>
            <span class="text">로켓프레시</span>
        </label>
    </label>
    <textarea class="editor" name="content" id="editor"></textarea>
    <div class="buttons">
        <input class="button white" type="button" value="돌아가기" onclick="if (confirm('정말로 돌아갈까요? 작성하신 정보가 모두 유실됩니다.')) {window.history.back();}">
        <input class="button blue" type="submit" value="상품 등록하기">
    </div>

</form>
</body>
</html>

add.css 추가

@charset "UTF-8";

body > .main {
    width: var(--content-max-width);
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    margin-top: 1rem;
    padding-bottom: 2rem;
}

body > .main > .label {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-bottom: 0.5rem;
}
body > .main > .label > .hint {
    flex: 0 0 3rem;
    white-space: nowrap;
    margin-left: 1rem;
}

body > .main > .label > .input {
    width: auto;
    flex: 1;
    border: 0.0625rem solid rgb(229, 229, 229);
    padding: 0.625rem 1rem;
    border-radius: 0.25rem;
}

body > .main > .label > .label {
    align-items: center;
    cursor: pointer;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
}

body > .main > .label > .label + .label {
    margin-left: 0.75rem;
}

body > .main > .label > .label > .checker {
    border: 0.0625rem solid rgb(229, 229, 229);
    border-radius: 50%;
    margin-right: 0.375rem;
    padding:0.5rem;
}

body > .main > .label > .label > .input:checked + .checker {
    border: 0.0625rem solid rgb(229, 229, 229);
    background-color: rgb(66,132,243);
}

body > .main > .label > .label > .text {
    white-space: nowrap;
}

body > .main > .buttons {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin-top: 1.5rem;
}

body > .main > .buttons > .button {
    width: auto;
    border-radius: 0.25rem;
    cursor: pointer;
    padding: 0.75rem 1.25rem;
}

body > .main > .buttons > .button +.button {
    margin-left: 0.5rem;
}

body > .main > .buttons > .button:hover {
    filter: brightness(105%);
}

body > .main > .buttons > .button:active {
    filter: brightness(95%);
}

body > .main > .buttons > .button.white {
    border: 0.0625rem solid rgb(229, 229, 229);
}

body > .main > .buttons > .button.blue {
    background-color: rgb(66,132,243);
    color: white;
}

https://ckeditor.com/ckeditor-5/demo/

메인에서 상단 메뉴바에 CKEditor5 클릭

Online builder 클릭

Classic 클릭

Cloud Services 및 ck 관련된거 삭제하고 simple 검색

Simple upload adapter ADD

Next step 후 Korean으로 지정

다운로드

build에 있는 내용 ckeditor 디렉토리에 추가

add.html 에 script 추가

product -> resources -> scripts 디렉토리에 add.js 추가

적용완료

테스트해보자

add 클릭해보면


여러 이미지 업로드를 위해 배열로 만들어준다.

이미지를 업로드 해보면

binary이미지를 의미

이미지파일 이름이 뜨면 된다

profile
코드를 두드리면 문이 열린다

0개의 댓글

관련 채용 정보