diff --git a/.pnp.cjs b/.pnp.cjs index 523189a8..efcc20fd 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -34,14 +34,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./",\ "packageDependencies": [\ ["@babel/core", "npm:7.16.12"],\ - ["@editorjs/checklist", "npm:1.5.0"],\ ["@editorjs/editorjs", "npm:2.26.5"],\ ["@editorjs/header", "npm:2.7.0"],\ ["@editorjs/list", "npm:1.8.0"],\ - ["@editorjs/marker", "npm:1.3.0"],\ ["@editorjs/paragraph", "npm:2.9.0"],\ - ["@editorjs/table", "npm:2.2.1"],\ - ["@editorjs/text-variant-tune", "npm:1.0.1"],\ ["@editorjs/underline", "npm:1.1.0"],\ ["@emotion/css", "virtual:749e5bbf5a36f23b3cf0fe3d04bee14b6518c1a723e8b01df428ddb8189c2ccc0edc216f830d01f6c6953a0ff06606bd469c60fb4212fe27940b27d64078f32d#npm:11.7.1"],\ ["@emotion/react", "virtual:749e5bbf5a36f23b3cf0fe3d04bee14b6518c1a723e8b01df428ddb8189c2ccc0edc216f830d01f6c6953a0ff06606bd469c60fb4212fe27940b27d64078f32d#npm:11.7.1"],\ @@ -3076,13 +3072,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@codexteam/icons", "npm:0.1.0"]\ ],\ "linkType": "HARD"\ - }],\ - ["npm:0.3.0", {\ - "packageLocation": "./.yarn/cache/@codexteam-icons-npm-0.3.0-40c6171ad6-4949e753a9.zip/node_modules/@codexteam/icons/",\ - "packageDependencies": [\ - ["@codexteam/icons", "npm:0.3.0"]\ - ],\ - "linkType": "HARD"\ }]\ ]],\ ["@discoveryjs/json-ext", [\ @@ -3094,16 +3083,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["@editorjs/checklist", [\ - ["npm:1.5.0", {\ - "packageLocation": "./.yarn/cache/@editorjs-checklist-npm-1.5.0-5b071f8456-cf71993ba6.zip/node_modules/@editorjs/checklist/",\ - "packageDependencies": [\ - ["@editorjs/checklist", "npm:1.5.0"],\ - ["@codexteam/icons", "npm:0.3.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@editorjs/editorjs", [\ ["npm:2.26.5", {\ "packageLocation": "./.yarn/cache/@editorjs-editorjs-npm-2.26.5-3affcf4351-899741482b.zip/node_modules/@editorjs/editorjs/",\ @@ -3138,16 +3117,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["@editorjs/marker", [\ - ["npm:1.3.0", {\ - "packageLocation": "./.yarn/cache/@editorjs-marker-npm-1.3.0-1ca2af4b28-b93bc22b92.zip/node_modules/@editorjs/marker/",\ - "packageDependencies": [\ - ["@editorjs/marker", "npm:1.3.0"],\ - ["@codexteam/icons", "npm:0.0.5"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@editorjs/paragraph", [\ ["npm:2.9.0", {\ "packageLocation": "./.yarn/cache/@editorjs-paragraph-npm-2.9.0-1df54d17fb-f91acaee6d.zip/node_modules/@editorjs/paragraph/",\ @@ -3158,25 +3127,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["@editorjs/table", [\ - ["npm:2.2.1", {\ - "packageLocation": "./.yarn/cache/@editorjs-table-npm-2.2.1-232aba2d28-7f03086928.zip/node_modules/@editorjs/table/",\ - "packageDependencies": [\ - ["@editorjs/table", "npm:2.2.1"],\ - ["@codexteam/icons", "npm:0.0.6"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@editorjs/text-variant-tune", [\ - ["npm:1.0.1", {\ - "packageLocation": "./.yarn/cache/@editorjs-text-variant-tune-npm-1.0.1-2fd3c439da-723359d536.zip/node_modules/@editorjs/text-variant-tune/",\ - "packageDependencies": [\ - ["@editorjs/text-variant-tune", "npm:1.0.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@editorjs/underline", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/@editorjs-underline-npm-1.1.0-5184f0c31d-5611b76bea.zip/node_modules/@editorjs/underline/",\ @@ -17519,14 +17469,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["mashup-admin-fe", "workspace:."],\ ["@babel/core", "npm:7.16.12"],\ - ["@editorjs/checklist", "npm:1.5.0"],\ ["@editorjs/editorjs", "npm:2.26.5"],\ ["@editorjs/header", "npm:2.7.0"],\ ["@editorjs/list", "npm:1.8.0"],\ - ["@editorjs/marker", "npm:1.3.0"],\ ["@editorjs/paragraph", "npm:2.9.0"],\ - ["@editorjs/table", "npm:2.2.1"],\ - ["@editorjs/text-variant-tune", "npm:1.0.1"],\ ["@editorjs/underline", "npm:1.1.0"],\ ["@emotion/css", "virtual:749e5bbf5a36f23b3cf0fe3d04bee14b6518c1a723e8b01df428ddb8189c2ccc0edc216f830d01f6c6953a0ff06606bd469c60fb4212fe27940b27d64078f32d#npm:11.7.1"],\ ["@emotion/react", "virtual:749e5bbf5a36f23b3cf0fe3d04bee14b6518c1a723e8b01df428ddb8189c2ccc0edc216f830d01f6c6953a0ff06606bd469c60fb4212fe27940b27d64078f32d#npm:11.7.1"],\ diff --git a/.yarn/cache/@codexteam-icons-npm-0.3.0-40c6171ad6-4949e753a9.zip b/.yarn/cache/@codexteam-icons-npm-0.3.0-40c6171ad6-4949e753a9.zip deleted file mode 100644 index be62e8e3..00000000 Binary files a/.yarn/cache/@codexteam-icons-npm-0.3.0-40c6171ad6-4949e753a9.zip and /dev/null differ diff --git a/.yarn/cache/@editorjs-checklist-npm-1.5.0-5b071f8456-cf71993ba6.zip b/.yarn/cache/@editorjs-checklist-npm-1.5.0-5b071f8456-cf71993ba6.zip deleted file mode 100644 index 12d5aec4..00000000 Binary files a/.yarn/cache/@editorjs-checklist-npm-1.5.0-5b071f8456-cf71993ba6.zip and /dev/null differ diff --git a/.yarn/cache/@editorjs-marker-npm-1.3.0-1ca2af4b28-b93bc22b92.zip b/.yarn/cache/@editorjs-marker-npm-1.3.0-1ca2af4b28-b93bc22b92.zip deleted file mode 100644 index d342ef2e..00000000 Binary files a/.yarn/cache/@editorjs-marker-npm-1.3.0-1ca2af4b28-b93bc22b92.zip and /dev/null differ diff --git a/.yarn/cache/@editorjs-table-npm-2.2.1-232aba2d28-7f03086928.zip b/.yarn/cache/@editorjs-table-npm-2.2.1-232aba2d28-7f03086928.zip deleted file mode 100644 index 31c17c81..00000000 Binary files a/.yarn/cache/@editorjs-table-npm-2.2.1-232aba2d28-7f03086928.zip and /dev/null differ diff --git a/.yarn/cache/@editorjs-text-variant-tune-npm-1.0.1-2fd3c439da-723359d536.zip b/.yarn/cache/@editorjs-text-variant-tune-npm-1.0.1-2fd3c439da-723359d536.zip deleted file mode 100644 index c5863b02..00000000 Binary files a/.yarn/cache/@editorjs-text-variant-tune-npm-1.0.1-2fd3c439da-723359d536.zip and /dev/null differ diff --git a/package.json b/package.json index 4cfaa4fc..53b35a70 100644 --- a/package.json +++ b/package.json @@ -100,14 +100,10 @@ "webpack-merge": "^5.8.0" }, "dependencies": { - "@editorjs/checklist": "^1.5.0", "@editorjs/editorjs": "^2.26.5", "@editorjs/header": "^2.7.0", "@editorjs/list": "^1.8.0", - "@editorjs/marker": "^1.3.0", "@editorjs/paragraph": "^2.9.0", - "@editorjs/table": "^2.2.1", - "@editorjs/text-variant-tune": "^1.0.1", "@editorjs/underline": "^1.1.0", "@emotion/css": "^11.7.1", "@emotion/react": "^11.7.1", diff --git a/src/api/index.ts b/src/api/index.ts index 2fd4fbc3..a5f202d2 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -7,3 +7,4 @@ export * from './generation'; export * from './member'; export * from './scoreHistory'; export * from './schedule'; +export * from './storage'; diff --git a/src/components/common/Editor/Editor.component.tsx b/src/components/common/Editor/Editor.component.tsx index 47fe7017..44abe8de 100644 --- a/src/components/common/Editor/Editor.component.tsx +++ b/src/components/common/Editor/Editor.component.tsx @@ -1,110 +1,79 @@ import React, { useState, useEffect, useRef } from 'react'; import EditorJS, { OutputData } from '@editorjs/editorjs'; -import Header from '@editorjs/header'; -import List from '@editorjs/list'; -import Checklist from '@editorjs/checklist'; -import Table from '@editorjs/table'; -import Marker from '@editorjs/marker'; -import Underline from '@editorjs/underline'; -import TextVariantTune from '@editorjs/text-variant-tune'; import DragDrop from 'editorjs-drag-drop'; -import Paragraph from '@editorjs/paragraph'; import { Blocker } from '@/components'; import i18n from './i18n'; - -const DEFAULT_INITIAL_DATA = { - time: new Date().getTime(), - blocks: [], -}; +import { getDefaultEditorData } from '@/utils'; +import tools from './tools'; interface EditorProps { id: string; + savedData: OutputData; } -const Editor = ({ id }: EditorProps) => { - const savedData = localStorage.getItem(id) - ? JSON.parse(localStorage.getItem(id) ?? '{}') - : DEFAULT_INITIAL_DATA; - - const ejInstance = useRef(); +const Editor = ({ id, savedData }: EditorProps) => { + const editorRef = useRef(); const [editorData, setEditorData] = useState(savedData); + const [editorReady, setEditorReady] = useState(false); const initEditor = () => { const editor = new EditorJS({ holder: id, data: editorData, onReady: () => { - ejInstance.current = editor; + editorRef.current = editor; // eslint-disable-next-line no-new new DragDrop(editor); + setEditorReady(true); }, onChange: async () => { - const content = (await ejInstance.current?.saver.save()) as OutputData; + const content = (await editorRef.current?.saver.save()) as OutputData; localStorage.setItem(id, JSON.stringify(content)); setEditorData(content); }, autofocus: true, - tools: { - header: { - // @ts-ignore - class: Header, - config: { - placeholder: `Tab 으로 크기를 변경하세요.`, - levels: [1, 2, 3, 4], - defaultLevel: 3, - }, - }, - paragraph: { - class: Paragraph, - inlineToolbar: true, - config: { - placeholder: `Tab 으로 새로운 블록을 추가하세요.`, - }, - }, - list: { - class: List, - inlineToolbar: true, - config: { - defaultStyle: 'unordered', - }, - }, - checklist: { - class: Checklist, - inlineToolbar: true, - }, - table: { - class: Table, - inlineToolbar: true, - config: { - rows: 2, - cols: 3, - }, - }, - - Marker: { - class: Marker, - shortcut: 'CMD+SHIFT+M', - }, - underline: Underline, - textVariant: TextVariantTune, - }, - tunes: ['textVariant'], + // @ts-expect-error: third party plugin + tools, i18n, }); }; useEffect(() => { - if (!ejInstance.current) initEditor(); + if (!editorRef.current) initEditor(); + + return () => { + editorRef.current?.destroy(); + }; + }, []); + + useEffect(() => { + if (!editorRef.current) return; + const newEditorData = savedData?.blocks ? savedData : getDefaultEditorData(); + setEditorData(newEditorData); + editorRef.current.render(newEditorData); + }, [editorReady, savedData]); + + /** Tab을 입력했을 때 에디터 밖으로 TabIndex가 변경되는 것을 방지 */ + useEffect(() => { + const isEditorFocused = editorRef.current?.blocks?.getCurrentBlockIndex() !== -1; + + const handleKeyDown = (event: KeyboardEvent) => { + if (isEditorFocused && event.key === 'Tab') { + event.preventDefault(); + } + }; + + window.addEventListener('keydown', handleKeyDown); return () => { - ejInstance.current?.destroy(); + window.removeEventListener('keydown', handleKeyDown); }; }, []); return ( <>
; - + ); }; diff --git a/src/components/common/Editor/i18n.ts b/src/components/common/Editor/i18n.ts index 8df9e0bc..5d83c70e 100644 --- a/src/components/common/Editor/i18n.ts +++ b/src/components/common/Editor/i18n.ts @@ -37,11 +37,34 @@ export default { Underline: '밑줄', }, - tools: {}, + tools: { + table: { + 'With headings': '제목 추가', + 'Without headings': '제목 제거', + 'Add column to left': '왼쪽에 열 삽입', + 'Add column to right': '오른쪽에 열 삽입', + 'Delete column': '열 삭제', + 'Add row above': '위에 행 삽입', + 'Add row below': '아래에 행 삽입', + 'Delete row': '행 삭제', + Heading: '제목', + }, + header: { + 'Heading 1': '제목 1', + 'Heading 2': '제목 2', + 'Heading 3': '제목 3', + 'Heading 4': '제목 4', + }, + list: { + Unordered: '글머리 목록', + Ordered: '번호 목록', + }, + }, blockTunes: { delete: { Delete: '삭제', + 'Click to delete': '확인', }, moveUp: { 'Move up': '위로 이동', diff --git a/src/components/common/Editor/tools.ts b/src/components/common/Editor/tools.ts new file mode 100644 index 00000000..645a4942 --- /dev/null +++ b/src/components/common/Editor/tools.ts @@ -0,0 +1,34 @@ +import Header from '@editorjs/header'; +import List from '@editorjs/list'; +import Underline from '@editorjs/underline'; +import Paragraph from '@editorjs/paragraph'; + +export default { + /** + * @type {EditorConfig.tools} + */ + header: { + class: Header, + config: { + placeholder: `Tab 으로 크기를 변경하세요.`, + levels: [1, 2, 3, 4], + defaultLevel: 3, + }, + }, + paragraph: { + class: Paragraph, + inlineToolbar: true, + config: { + placeholder: `Tab 으로 새로운 블록을 추가하세요.`, + preserveBlank: true, + }, + }, + list: { + class: List, + inlineToolbar: true, + config: { + defaultStyle: 'unordered', + }, + }, + underline: Underline, +}; diff --git a/src/components/common/LNB/LNB.component.tsx b/src/components/common/LNB/LNB.component.tsx index a07be907..4838fe24 100644 --- a/src/components/common/LNB/LNB.component.tsx +++ b/src/components/common/LNB/LNB.component.tsx @@ -13,8 +13,8 @@ import ApplicationFormIcon from '@/assets/svg/application-form.svg'; import EmailIcon from '@/assets/svg/email.svg'; import ActivityScoreIcon from '@/assets/svg/activity-score.svg'; import ScheduleIcon from '@/assets/svg/schedule.svg'; +import RecruitIcon from '@/assets/svg/recruit.svg'; // import SignupCodeIcon from "@/assets/svg/signup-code.svg" -// import RecruitIcon from "@/assets/svg/recruit.svg" // import AdminMembersIcon from '@/assets/svg/admin-members.svg'; // import MyPageIcon from "@/assets/svg/my-page.svg" @@ -60,15 +60,16 @@ const navigationItems: NavigationItem[] = [ ], }, // TODO: 추가 예정 메뉴 - // { - // title: '콘텐츠 관리', - // menus: [ - // { - // label: '모집 공고', - // to: PATH.RECRUIT, - // }, - // ], - // }, + { + title: '콘텐츠 관리', + menus: [ + { + label: '모집 공고', + to: PATH.RECRUIT, + icon: , + }, + ], + }, // { // title: '계정 관리', // menus: [ @@ -77,10 +78,10 @@ const navigationItems: NavigationItem[] = [ // to: PATH.ADMIN_MEMBERS, // icon: , // }, - // { - // label: '내 정보', - // to: PATH.MY_PAGE, - // }, + // { + // label: '내 정보', + // to: PATH.MY_PAGE, + // }, // ], // }, ]; diff --git a/src/constants/paths.ts b/src/constants/paths.ts index 22721948..4f53eec6 100644 --- a/src/constants/paths.ts +++ b/src/constants/paths.ts @@ -15,7 +15,7 @@ export const PATH = { SCHEDULE_DETAIL: '/schedule/:scheduleId', SCHEDULE_CREATE: '/schedule/create', SCHEDULE_UPDATE: '/schedule/update/:scheduleId', - UPDATE_PLATFORM_RECRUIT: '/recruit/update', + UPDATE_PLATFORM_RECRUIT: '/recruit', ADMIN_MEMBERS: '/admin-members', SIGNUP_CODE: '/signup-code', RECRUIT: '/recruit', diff --git a/src/pages/UpdatePlatformRecruit/UpdatePlatformRecruit.page.tsx b/src/pages/UpdatePlatformRecruit/UpdatePlatformRecruit.page.tsx index be4e830a..a221f1da 100644 --- a/src/pages/UpdatePlatformRecruit/UpdatePlatformRecruit.page.tsx +++ b/src/pages/UpdatePlatformRecruit/UpdatePlatformRecruit.page.tsx @@ -1,30 +1,95 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; +import { OutputData } from '@editorjs/editorjs'; import { Editor, EditorAside } from '@/components'; import * as Styled from './UpdatePlatformRecruit.styled'; import { $teams } from '@/store'; import { SelectSize } from '@/components/common/Select/Select.component'; -import { postStorage } from '@/api/storage'; +import { decodeHTMLEntities, getDefaultEditorData, removeWrongAmpString, request } from '@/utils'; +import { useToast } from '@/hooks'; +import { ToastType } from '@/components/common/Toast/Toast.component'; +import * as api from '@/api'; + +const EDITOR_ID = 'platform-recruit-editor'; const UpdatePlatformRecruit = () => { - const [selectedPlatform, setSelectedPlatform] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [savedEditorData, setSavedEditorData] = useState(getDefaultEditorData()); + const [selectedPlatform, setSelectedPlatform] = useState('design'); + const storageKey = `recruit-${selectedPlatform}`; + + const { handleAddToast } = useToast(); const teams = useRecoilValue($teams); const teamOptions = teams.map(({ teamId, name }) => ({ value: teamId.toString(), label: name, })); - const editorId = 'platform-recruit-editor'; + const handleUpdateButtonClick = async () => { + const originalOutputData = JSON.parse(localStorage.getItem(EDITOR_ID) ?? '{}'); + const storageValue = { editorData: originalOutputData }; + + request({ + requestFunc: () => { + setIsLoading(true); + return api.postStorage({ keyString: storageKey, valueMap: storageValue }); + }, + errorHandler: () => { + handleAddToast({ + type: ToastType.error, + message: '모집공고를 저장하지 못했습니다. 다시 시도해주세요.', + }); + }, + onSuccess: () => { + handleAddToast({ + type: ToastType.success, + message: '성공적으로 모집공고를 저장했습니다.', + }); + }, + onCompleted: () => { + setIsLoading(false); + }, + }); + }; + + const getPlatformRecruit = async () => { + const { data } = await api.getStorage(storageKey); + const editorOutputData = data.valueMap.editorData; + + const modifiedData = JSON.parse( + decodeHTMLEntities(removeWrongAmpString(JSON.stringify(editorOutputData))), + ); + + return modifiedData; + }; + + useEffect(() => { + const setPlatformRecruit = async () => { + try { + const newPlatformRecruit = await getPlatformRecruit(); + setSavedEditorData(newPlatformRecruit); + } catch (error) { + handleAddToast({ + type: ToastType.error, + message: '모집공고를 불러오지 못했습니다. 다시 시도해주세요.', + }); + return getDefaultEditorData(); + } + }; + + setPlatformRecruit(); + }, [storageKey]); return ( - 리쿠르트 모집공고 수정 + 모집공고 - + setSelectedPlatform(option.label.toLowerCase())} @@ -32,18 +97,8 @@ const UpdatePlatformRecruit = () => { } rightActionButton={{ text: '수정', - onClick: async () => { - await postStorage({ - keyString: `recruit-${selectedPlatform}`, - valueMap: { - editorData: localStorage.getItem(editorId) ?? '', - }, - }); - - // 리크루트 사용 형태 - // const { data } = await getStorage(`recruit-${selectedPlatform}`); - // JSON.parse(data.valueMap.editorData.replace(/"/g, '"').replace(/^"|"\s*$/g, '')) - }, + onClick: handleUpdateButtonClick, + isLoading, }} /> diff --git a/src/styles/editorCss.ts b/src/styles/editorCss.ts new file mode 100644 index 00000000..51c2be21 --- /dev/null +++ b/src/styles/editorCss.ts @@ -0,0 +1,123 @@ +import { css } from '@emotion/react'; + +export default css` + #platform-recruit-editor { + min-height: 20rem; + margin: 0 auto; + padding: 4rem 2rem 4rem 6rem; + background-color: #ffffff; + border: 0.1rem solid #dee2e6; + border-radius: 2rem; + } + + .codex-editor { + width: 78.4rem; + } + + .codex-editor--narrow .codex-editor__redactor { + margin-right: 0px; + } + + .ce-toolbar { + left: -12rem; + } + + .ce-toolbar__actions { + top: -2px; + left: -6rem; + width: 50px; + } + + h1.ce-header { + font-weight: 800; + font-size: 4.6rem; + } + + h2.ce-header { + font-weight: 800; + font-size: 3.201rem; + } + + h3.ce-header { + margin: 1.6rem 0; + padding: 0; + font-weight: 700; + font-size: 1.8rem; + } + + .ce-block { + width: 100%; + font-weight: 500; + font-size: 1.6rem; + line-height: 1.5; + letter-spacing: -0.08rem; + } + + div.ce-block__content { + max-width: 1000px; + } + + .ce-toolbar__settings-btn--hidden { + display: unset; + } + + .ce-toolbar__plus, + .ce-toolbar__settings-btn { + display: flex; + align-items: center; + margin-left: 0; + color: #868e96; + } + + .ce-toolbox .cdx-search-field, + .ce-settings .cdx-search-field { + display: none; + } + + .ce-paragraph { + font-weight: 400; + font-size: 1.6rem; + line-height: 1.5; + } + + .cdx-block { + padding: 0; + } + + ul.cdx-block.cdx-list { + padding: 0; + } + + li.cdx-list__item { + margin-left: 2.5rem; + padding: 0 0 0.6rem 0.3rem; + list-style-type: unset; + } + + /** + * 'Header'에 'placeholder'가 있을 때 클릭 불가 이슈 수정 + * @see {@link https://github.com/codex-team/editor.js/issues/1130} + */ + .ce-header[contentEditable='true'][data-placeholder]::before { + pointer-events: none; + } + + /** 불필요한 반응형 제거 */ + @media (min-width: 651px) { + .codex-editor--narrow .ce-toolbox { + left: 0; + + .ce-popover { + left: 0; + } + } + } + + /** 불필요한 반응형 제거 */ + @media (min-width: 651px) { + .codex-editor--narrow .ce-block--focused { + margin-right: 0; + padding-right: 0; + } + } +`; diff --git a/src/styles/globalStyles.ts b/src/styles/globalStyles.ts index b1868d3f..7f5d09f7 100644 --- a/src/styles/globalStyles.ts +++ b/src/styles/globalStyles.ts @@ -1,84 +1,13 @@ import { css } from '@emotion/react'; import spoqaHanSansNeo from '@/styles/fonts/spoqaHanSansNeo'; import resetCss from './resetCss'; +import editorCss from './editorCss'; export const globalStyles = css` ${spoqaHanSansNeo} ${resetCss} + ${editorCss} #root { min-width: 89.6rem; } - - #platform-recruit-editor { - flex: 1; - min-height: 20rem; - margin: 0 auto; - padding: 6rem 8rem; - background-color: #ffffff; - border: 0.1rem solid #dee2e6; - border-radius: 2rem; - } - - .ce-toolbar__actions { - top: -2px; - left: -6rem; - } - - h1.ce-header { - font-weight: 800; - font-size: 4.6rem; - } - - h2.ce-header { - font-weight: 800; - font-size: 3.201rem; - } - - h3.ce-header { - font-weight: 700; - font-size: 1.8rem; - } - - .ce-block { - width: 100%; - font-weight: 500; - font-size: 1.6rem; - line-height: 1.5; - letter-spacing: -0.08rem; - } - - li.cdx-list__item { - list-style-type: unset; - } - - div.ce-block__content { - max-width: 1000px; - } - - .ce-toolbar__settings-btn--hidden { - display: unset; - } - - .ce-toolbar__plus, - .ce-toolbar__settings-btn { - display: flex; - align-items: center; - margin-left: 0; - color: #868e96; - } - - div.codex-editor__redactor { - padding-bottom: 0 !important; - } - - .ce-toolbox .cdx-search-field, - .ce-settings .cdx-search-field { - display: none; - } - - .ce-paragraph { - font-weight: 400; - font-size: 1.5rem; - line-height: 1.5; - } `; diff --git a/src/utils/editor.ts b/src/utils/editor.ts new file mode 100644 index 00000000..b5b8ad75 --- /dev/null +++ b/src/utils/editor.ts @@ -0,0 +1,6 @@ +export const getDefaultEditorData = () => { + return { + time: new Date().getTime(), + blocks: [{ type: 'paragraph', data: {} }], + }; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index 8354e0d2..25e5f3b1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,3 +8,4 @@ export * from './string'; export * from './number'; export * from './format'; export * from './schedule'; +export * from './editor'; diff --git a/src/utils/string.ts b/src/utils/string.ts index 702516c3..4d4aa1fa 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -36,3 +36,8 @@ export const decodeHTMLEntities = (value: string) => { element.remove(); return element.textContent ?? ''; }; + +/** 백엔드 이스케이프 과정에서 `&`를 `&`로 응답하기 때문에 프론트에서 임시로 처리 */ +export const removeWrongAmpString = (value: string) => { + return value.replace(/&/g, '&'); +}; diff --git a/yarn.lock b/yarn.lock index 95894142..88219e5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1622,13 +1622,6 @@ __metadata: languageName: node linkType: hard -"@codexteam/icons@npm:^0.3.0": - version: 0.3.0 - resolution: "@codexteam/icons@npm:0.3.0" - checksum: 4949e753a9f8d0442c581512566167dddf7853fce0aa388ec9ddd9acc2aa3f081192d266c0eb1a2f78154492f376f7ce042f69ca45cad9a1f02583ab70e0000b - languageName: node - linkType: hard - "@discoveryjs/json-ext@npm:^0.5.0, @discoveryjs/json-ext@npm:^0.5.3": version: 0.5.6 resolution: "@discoveryjs/json-ext@npm:0.5.6" @@ -1636,15 +1629,6 @@ __metadata: languageName: node linkType: hard -"@editorjs/checklist@npm:^1.5.0": - version: 1.5.0 - resolution: "@editorjs/checklist@npm:1.5.0" - dependencies: - "@codexteam/icons": ^0.3.0 - checksum: cf71993ba60d1301d4b9fdb8709ee4f37f87430cf74548e710dc8a829c7b624b11f2a7c8b90fe21526e7002664d3e04880309849e9c21ae322a64b5be33dc829 - languageName: node - linkType: hard - "@editorjs/editorjs@npm:^2.26.5": version: 2.26.5 resolution: "@editorjs/editorjs@npm:2.26.5" @@ -1676,15 +1660,6 @@ __metadata: languageName: node linkType: hard -"@editorjs/marker@npm:^1.3.0": - version: 1.3.0 - resolution: "@editorjs/marker@npm:1.3.0" - dependencies: - "@codexteam/icons": ^0.0.5 - checksum: b93bc22b92ba39a568b146adc4d2d3134a331c1b344e4a75d12cc654864fb5f0dad0ec305fb9aa1e0de81c3599da7e9e2f6a1d6ef776275106d8530804a96f9e - languageName: node - linkType: hard - "@editorjs/paragraph@npm:^2.9.0": version: 2.9.0 resolution: "@editorjs/paragraph@npm:2.9.0" @@ -1694,22 +1669,6 @@ __metadata: languageName: node linkType: hard -"@editorjs/table@npm:^2.2.1": - version: 2.2.1 - resolution: "@editorjs/table@npm:2.2.1" - dependencies: - "@codexteam/icons": ^0.0.6 - checksum: 7f03086928e5562e5fd919e80919f7a62b73556b2c01923c7b2f5a417e9027357e295b870d36ebbc8661351fa816108b9f7cd52f3948821032dbc6f021316d2c - languageName: node - linkType: hard - -"@editorjs/text-variant-tune@npm:^1.0.1": - version: 1.0.1 - resolution: "@editorjs/text-variant-tune@npm:1.0.1" - checksum: 723359d5361d7716a0d33c8ee28e4de4f27c19db371afd339e19d70f0c58f16b4ab5b8fe9b180816d26f66513033deea4cc89ca2f4fd9d7e7be8d27893aa8df5 - languageName: node - linkType: hard - "@editorjs/underline@npm:^1.1.0": version: 1.1.0 resolution: "@editorjs/underline@npm:1.1.0" @@ -12954,14 +12913,10 @@ __metadata: resolution: "mashup-admin-fe@workspace:." dependencies: "@babel/core": ^7.16.12 - "@editorjs/checklist": ^1.5.0 "@editorjs/editorjs": ^2.26.5 "@editorjs/header": ^2.7.0 "@editorjs/list": ^1.8.0 - "@editorjs/marker": ^1.3.0 "@editorjs/paragraph": ^2.9.0 - "@editorjs/table": ^2.2.1 - "@editorjs/text-variant-tune": ^1.0.1 "@editorjs/underline": ^1.1.0 "@emotion/css": ^11.7.1 "@emotion/react": ^11.7.1