누군가는 써보고 싶은 DHTMLX Gantt 차트당.
가면 많은 Component를 제공 하련당.
안타깝땅. 대부분 Pro 버젼으로 유료에, 무료버젼도 있지만 닭똥 눈물나겡 설명이 구닥다리당.
https://dhtmlx.com/blog/create-react-gantt-chart-component-dhtmlxgantt/
위 사이트에 가면 무료버젼을 이용해 react를 활용하는 예제가 있지만,
역시 구닥따리에 날짜 순서등이 한국식이 아니당. 가슴 아프당.
문서도 방대하고, 제대로 쓰려면 아무래도 시간 투자가 엄칭 많이 필요할꼬시당.
그래도 간단하게 쓴다면, 위 예제 정도로 충분하지 않을깡? 맴이 버럭 든당.
그래서 위 사이트 소스를 요듬 방식으로 고쳐 맹글어 볼꺼이당.(시름 말공...)
먼저 vite를 이용하여 프로젝트를 생성하고 아래 모듈을 추가하련당.
npm install dhtmlx-gantt
파일은 폴더 맹글고 그러면 또 정신 없어지닝, src 폴더에 아래 파일들을 맹글거당.
css 파일은 그냥 가져다 복사/ 붙여넣기 하장.
index.css
.gantt-container {
height: calc(100vh - 50px - 200px);
}
.message-area {
background: #ebebeb;
height: 200px;
overflow: auto;
padding: 10px;
box-sizing:border-box;
}
.message-area ul{
margin: 0;
padding: 0;
list-style: none;
}
.message-area li:before {
content: "\003e";
padding-right: 10px;
}
간트차트를 위한 임시 데이터당. (대략 필요한 속성들 의미만 눈과 머리로 받아들여보장)
dummyData.js
const data = {
data: [
{ id: 1, text: '작업 #1', start_date: '2024-12-25', duration: 3, progress: 0.6},
{ id: 2, text: '작업 #2', start_date: '2024-12-28', duration: 3, progress: 0.4},
{ id: 3, text: '작업 #1-1', start_date: '2024-12-25', duration: 1, progress: 1 ,parent:1},
{ id: 4, text: '작업 #1-2', start_date: '2024-12-26', duration: 2, progress: 0.5,parent:1 },
],
links: [
{ id: 1, source: 1, target: 2, type: '0' },
{ id: 2, source: 3, target: 4, type: '0' },
]
};
export default data;
툴바에서 기간을 시간/일/월 단위로 보여주기 위한 세팅값이다.
낯설지만 DHTMLX Gantt 차트는 이런 식으로 만들란당. (복사/붙여넣기 해서 쓰장)
zoomLevelSetting.js
const initLevels = {
levels: [
{
name: '시간단위',
scale_height: 60,
min_column_width: 30,
scales: [
{ unit: 'day', step: 1, format: '%M %d일' },
{ unit: 'hour', step: 1, format: '%H' }
]
},
{
name: '날짜단위',
scale_height: 60,
min_column_width: 70,
scales: [
{ unit: 'week', step: 1, format: 'Week %W주' },
{ unit: 'day', step: 1, format: '%M %d일' }
]
},
{
name: '월단위',
scale_height: 60,
min_column_width: 70,
scales: [
{ unit: "month", step: 1, format: '%F' },
{ unit: 'week', step: 1, format: '%W주' }
]
}
]
}
export default initLevels
이건 그냥 복사 붙여넣기 하장, log
main.jsx
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
const root = createRoot(document.getElementById('root'))
root.render(
<App />
)
이건 복사 붙여넣기 하고, 한번 눈으로 보장.
logDataupdate 함수는 MyGantt에 넘어가서 불리는 것이 포인트당.
App.jsx
import { useState } from "react";
import MessageArea from "./MessageArea";
import MyGantt from "./MyGantt";
import Toolbar from "./Toolbar";
import data from "./dummyData";
function App() {
const [zoom,setZoom] = useState("날짜단위")
const [msgs,setMsgs] = useState([])
const onZoomChange = (zoom)=>{
setZoom(zoom)
}
const logMessage = (message) =>{
msgs.length >= 5 ? setMsgs([message,...msgs.slice(0,4)]):setMsgs([message,...msgs])
}
const logDataupdate = (entityType, action, itemData, id) => {
console.log("B/E 에 중요",entityType, action, itemData, id);
let text = itemData && itemData.text ? ` (${itemData.text})`: '';
let message = `${entityType} ${action}: ${id} ${text}`;
if (entityType === 'link' && action !== 'delete' ) {
message += ` ( source: ${itemData.source}, target: ${itemData.target} )`;
}
logMessage(message)
}
return (
<>
<Toolbar curzoom={zoom} onZoomChange = {onZoomChange} />
<div className="gantt-container">
<MyGantt tasks={data} curzoom={zoom} msgs={msgs} onDataUpdated={logDataupdate} />
</div>
<MessageArea msgs={msgs} />
</>
)
}
export default App
Gantt 차트에 변화가 생기는 걸 추적할 수 있도록 dataProcessor라는 걸 제공해 준당.
머리 안써도 된당. 매뉴얼대로 그저 세팅했을 뿐이당.(그냥 받아들이장~~)
MyGantt.jsx
import { gantt } from "dhtmlx-gantt";
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
import { useEffect, useRef } from "react";
import initLevels from "./zoomLevelSetting";
function MyGantt({tasks,curzoom,onDataUpdated,msgs}){
const ganttRef = useRef(null)
let dataProcessor = null
const initGanttDataProcessor = () => {
dataProcessor = gantt.createDataProcessor((entityType, action, item, id) => {
return new Promise((resolve, reject) => {
if (onDataUpdated) {
onDataUpdated(entityType, action, item, id);
}
return resolve();
});
});
}
useEffect(()=>{
gantt.i18n.setLocale("kr");
gantt.config.date_format = "%Y-%m-%d %H:%i";
gantt.config.scales = [
{unit:"day",step:1, format:"%j,%D"}
]
console.log("확인 lightbox",gantt.config.lightbox.sections);
console.log("확인 다국어지원",gantt.locale.labels);
gantt.config.lightbox.sections[1].time_format=["%Y","%m","%d"];
gantt.locale.labels.new_task="새 작업";
gantt.config.task_date = " %Y년 %m월 %d일";
gantt.ext.zoom.init(initLevels);
console.log("확인2",gantt.config.lightbox)
//initGanttDataProcessor(); 요기 있으면 message처리가 이상해짐??
gantt.init(ganttRef.current);
gantt.parse(tasks);
},[])
useEffect(()=>{
gantt.ext.zoom.setLevel(curzoom);
initGanttDataProcessor();
return () =>{
if(dataProcessor){
dataProcessor.destructor();
dataProcessor = null;
}
}
// gantt.render();
},[curzoom,msgs])
return (
<div
ref={ganttRef}
style={{width:"100%",height:"100%"}}
></div>
)
}
export default MyGantt
줌(Zoom) 설정을 위한 체크박스들을 담은 컴포넌트당.
Toolbar.jsx
import React, { useContext } from 'react';
function Toolbar({curzoom, onZoomChange}) {
const handleZoomChange = (e) =>{
onZoomChange(e.target.value)
}
const zoomRadios = ['시간단위', '날짜단위', '월단위'].map(val => {
const isActive = curzoom === val;
return (
<label key={val}>
<input type='radio'
checked={isActive}
onChange={handleZoomChange}
value={val}
/>
{val}
</label>
)
})
return (
<div className='tool-bar'>
<b>줌 레벨 선택: </b>
{zoomRadios}
</div>
)
}
export default Toolbar
DataProcessor에서 넘겨 받은 내용을 출력해주는 컴포넌트당.
MessageArea.jsx
function MessageArea({msgs}) {
const messages = msgs.map(msg => <li key={Math.random()}>{msg}</li>)
return (
<div className='message-area'>
<h3>발생로그:</h3>
<ul>
{messages}
</ul>
</div>
)
}
export default MessageArea
실행 결과 화면
흐름만 받아들인다면 기본 베이스로 사용해서, 간트 차트의 핵심 기능은 분명 사용할끼당.
그냥 참고: unit으로 사용 가능 한 값
"minute", "hour", "day" (by default), "week", "quarter", "month", "year"
그때가 좋았어? 왜?
시스템이 허술하고, 급하지 않아서?
잘하는 개발자가 많지 않아서?
아니 그때 난 젊었어!
시간이 알려주는 마지막 답은 젊을 때 !
그때! 마주치는 모든 것에 뒷걸음 말고 다가가라
그리고 그것과 친구가 되어 즐길지어라.
이젠 안당. 젊음 말고 대체 머가 더 필요행~~(^-^)
https://www.youtube.com/watch?v=5RN97CV9I6k
React(리액트) 티키타카 18 ( rc-tree 트리 컴포넌트) (6) | 2024.12.25 |
---|---|
React(리액트) 티키타카 17 (react-quill-new 에디터) (0) | 2024.12.25 |
그냥 E7E만 보는 클릭킁 체킁 (0) | 2024.10.26 |
React(리액트) 티키타카 15 ( restful, tanstack, axios) (5) | 2024.10.15 |
React(리액트) 티키타카 14 (useEffect Hook + fetch ) (0) | 2024.10.13 |