수업정리 쿠팡#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개의 댓글