어드민 - Article 추가 화면 (준비)

손대중·2022년 7월 4일
0

이제 글 추가하는 어드민 화면을 만들어보자.

총 3가지가 필요하다.

  • article 이 들어갈 메뉴 선택하는 select 화면
  • 제목 input
  • 본문 input - 웹 에디터 필요

뭐 유명한 웹 에디터는 summernote 가 있고, 마침 svelte 용으로 wrapping 된 버전이 존재하는 것이 확인된다. (https://github.com/easylogic/svelte-summernote)

근데 사용법을 보니 명시적으로 jQuery 를 넣어야 하는 듯...

import 'jquery'
import SvelteSummernoteLite from '@easylogic/svelte-summernote'
import '@easylogic/svelte-summernote/index.css'
......

jQuery 는 훌륭한 라이브러리지만 지금은 왠지 명시적으로 쓰기 싫다.

그래서 먼저 Toast UI 의 에디터를 사용해보기로 헸다. (https://github.com/nhn/tui.editor/tree/master/apps/editor)

뭐 이전 회사에서도 써보기도 했고, Toast UI 를 써보고 안되면 summernote 써보지 뭐...

다만 웹 에디터를 적용하기 전에 먼저 소스 정리가 필요하다.

AdminArticle.svelte

Article 추가 화면은 여기다가 만들고, 웹 에디터 부분을 제외한 나머지 부분들을 넣어보자.

근데 생각해보니 메뉴 선택하는 화면은 사실상 AdminMenu.svelte 화면과 동일하다.

코드를 그대로 복사해도 되긴 하지만... 중복이므로 별도의 컴포넌트로 빼고 적용하자.

  • AdminMenuSelectContainer.svelte

    • AdminMenu.svelte 내에 있던 UI & 로직들을 여기로 옮김
    <Content>
        <div class="card-content-container">
            {#each parents as parent, i}
            <div>
                <MenuSelect menus={parent.list} depth={i} on:change={changeParent} initTime={parents.initTime}></MenuSelect>
            </div>
            {/each}
        </div>
        <pre><h2>선택된 부모 메뉴 : { selectedParents() }</h2></pre>
    </Content>
    <Actions>
        <Button on:click={ init } variant="raised"><Label>초기화</Label></Button>
    </Actions>
    
    <script>
        import { Content, Actions } from '@smui/card';
        import Button, { Label } from '@smui/button';
        import { createEventDispatcher } from 'svelte';
    
        import MenuSelect from '../child/MenuSelect.svelte';
    
        import menu from '../../store/menu.js';
    
        const dispatch = createEventDispatcher();
    
        let parents = [];
    
        $: selectedParents = () => {
            let str = '';
            parents.map(parent => {
                if (!parent.select || !parent.select.name) {
                    return;
                }
    
                if (str) {
                    str += ' > ';
                }
    
                str += parent.select.name;
            });
    
            if (!str) {
                str = '없음';
            }
    
            return str;
        };
    
        $: {
            let parent = null;
    
            for (let i = parents.length - 1; i >= 0; i--) {
                if (parents[i].select !== '선택 안함' && !!parents[i].select?._id) {
                    parent = parents[i].select._id;
                    break;
                }
            }
    
            dispatch('change', { parent });
        }
    
        const changeParent = (event) => {
            const { value, depth } = event.detail;
    
            if (!value) {
                return;
            }
    
            const initTime = parents.initTime;
    
            parents = parents.slice(0, depth + 1);
            parents.initTime = initTime;
            parents[depth].select = value;
    
            if (value.children && value.children.length > 0) {
                parents.push({list: [...value.children], select: null});
            }
        };
    
        const init = () => {
            parents = [{list: $menu, select: null}];
            parents.initTime = (new Date()).getTime();
        };
    
        menu.subscribe(value => {
            init();
        });
    </script>
    
    <style>
        .card-content-container {
            display: flex;
            flex-wrap: wrap;
        }
    
        .card-content-container > div {
            flex-basis: 0px;
            min-width: 245px;
            margin-right: 12px;
        }
    
        pre h2 {
            color: orange;
        }
    </style>

추가로createEventDispatcher 로 선택된 메뉴에 대한 정보를 부모 컴포넌트 - AdminMenu.svelte, AdminArticle.svelte 에 전달하는 부분도 구현하고, 하는 김에 style 부분도 정리하고 전반적으로 코드 정리도 같이 했다.

이제 AdminMenu.svelte, AdminArticle.svelte 안에 새로 만든 컴포넌트를 적용하자.

  • AdminMenuSelectContainer.svelte 를 적용한 코드

    <div class="card-container">
        <h3>부모 메뉴 선택</h3>
        <Card variant="outlined">
            <AdminMenuSelectContainer on:change={chageParent}></AdminMenuSelectContainer>
        </Card>
    </div>
    ...
    <script>
        import AdminMenuSelectContainer from '../child/AdminMenuSelectContainer.svelte';
    
        let parent = null;
    
        const chageParent = e => {
            parent = e.detail.parent;
        };
        ....
    </script>
    

구현된 화면은 아래와 같다.

의도대로 잘 동작하는 중 ㅎㅎ 이제 웹 에디터만 추가하면 됨~.

0개의 댓글