진행률 선
진행률 선은 간트 차트 위에 그려지는 분석용 오버레이입니다. 선택한 기준 날짜를 기준으로 작업 진행 지점을 연결하여 작업의 현재 진행 상황과 프로젝트 계획을 비교할 수 있습니다.
이 샘플은 작업 완료 데이터를 사용하고 사이드 패널에서 진행률 선 API를 제공합니다. 샘플을 열 때 진행률 선이 표시되도록 프로젝트의 현재 날짜와 상태 날짜를 초기화합니다. 프로젝트 날짜를 업데이트하고 진행률 선 표시, 기준 날짜, 경로 형식, 선 스타일, 지점 스타일 및 날짜 레이블 스타일을 구성할 수 있습니다.
프로젝트 날짜
진행률 선은 한 번에 하나의 프로젝트 수준 날짜를 참조합니다.
project.currentDate
project.statusDate
샘플은 기본적으로 두 날짜를 모두 지정합니다. 사이드 패널에서 날짜를 변경하여 진행률 선이 어떻게 달라지는지 확인할 수 있습니다.
날짜 눈금선
이 샘플의 현재 날짜 눈금선과 상태 날짜 눈금선은 고정 스타일을 사용하며 진행률 선과 독립적으로 구성됩니다.
진행률 선 API
ganttSheet.progressLine을 사용하여 진행률 선 구성을 설정하거나 가져올 수 있습니다.
사용 가능한 속성은 다음과 같습니다.
display: 진행률 선 표시 여부를 지정합니다.
referenceDate: 사용할 프로젝트 날짜를 지정합니다. 값은 "statusDate" 또는 "currentDate"입니다.
pathType: 경로가 기준 날짜로 돌아갈지, 진행 지점을 직교선 또는 대각선으로 연결할지를 포함하여 진행률 선 경로가 그려지는 방식을 지정합니다.
lineStyle: 진행률 선의 형식과 색을 지정합니다. GC.Spread.Sheets.GanttSheet.GanttGridlineType을 사용합니다.
pointStyle: 진행 지점의 모양과 색을 지정합니다. 모양에는 GC.Spread.Sheets.GanttSheet.TaskbarEndShape와 동일한 값을 지원하는 GC.Spread.Sheets.GanttSheet.ProgressPointShape를 사용합니다.
dateLabelStyle: 날짜 레이블 표시 여부와 레이블 형식을 지정합니다.
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var ganttSheet;
var GanttGridlineType = GC.Spread.Sheets.GanttSheet.GanttGridlineType;
var lineTypeMap = {};
lineTypeMap.thin = GanttGridlineType.thin;
lineTypeMap.dashed = GanttGridlineType.dashed;
lineTypeMap.dotted = GanttGridlineType.dotted;
lineTypeMap.dashDot = GanttGridlineType.dashDot;
lineTypeMap.empty = GanttGridlineType.empty;
window.onload = function() {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
initSpread(spread);
initSplitView(spread);
};
function initSpread(spread) {
spread.suspendPaint();
initGanttSheet(spread);
spread.resumePaint();
}
function initGanttSheet(spread) {
var tableName = "Gantt_Mode";
var baseApiUrl = getBaseApiUrl();
var apiUrl = baseApiUrl + "/" + tableName;
var dataManager = spread.dataManager();
var myTable = dataManager.addTable("myTable", {
batch: true,
remote: {
read: {
url: apiUrl
},
batch: {
url: apiUrl + "Collection"
}
},
schema: {
hierarchy: {
type: "Parent",
column: "parentId"
},
columns: {
id: { isPrimaryKey: true },
taskNumber: { dataType: "rowOrder" }
}
}
});
ganttSheet = spread.addSheetTab(0, "GanttSheet1", GC.Spread.Sheets.SheetType.ganttSheet);
var view = myTable.addView("myView1", [
{ value: "taskNumber", caption: "NO", width: 60 },
{ value: "name", caption: "Task Name", width: 200 },
{ value: "duration", caption: "Duration", width: 90 },
{ value: "predecessors", caption: "Predecessors", width: 120 },
{ value: "complete", caption: "% Complete", width: 100 }
]);
view.fetch().then(function() {
return ganttSheet.bindGanttView(view);
}).then(function() {
initDefaultProjectDates();
applyFixedGridlines();
applyProgressLine();
});
initSidePanel();
}
function initDefaultProjectDates() {
var projectStart = ganttSheet.project.startDate;
var currentDate = addDays(projectStart, 4);
var statusDate = addDays(projectStart, 7);
ganttSheet.project.currentDate = currentDate;
ganttSheet.project.statusDate = statusDate;
document.getElementById("current-date").value = formatInputDate(currentDate);
document.getElementById("status-date").value = formatInputDate(statusDate);
}
function applyFixedGridlines() {
ganttSheet.gridlines.currentDate = {
lineColor: "#4A8F40",
lineType: GanttGridlineType.thin
};
ganttSheet.gridlines.statusDate = {
lineColor: "#5B9BD5",
lineType: GanttGridlineType.dashDot
};
}
function initSidePanel() {
document.getElementById("apply-progress-line").addEventListener("click", function() {
applyProjectDates();
applyFixedGridlines();
applyProgressLine();
});
}
function applyProjectDates() {
var currentDateValue = document.getElementById("current-date").value;
ganttSheet.project.currentDate = parseInputDate(currentDateValue);
var statusDateValue = document.getElementById("status-date").value;
ganttSheet.project.statusDate = parseInputDate(statusDateValue);
}
function applyProgressLine() {
ganttSheet.suspendPaint();
ganttSheet.progressLine = {
display: document.getElementById("display").checked,
referenceDate: document.getElementById("reference-date").value,
pathType: {
returnToReferenceDate: document.getElementById("return-to-reference-date").checked,
pointConnectionType: document.getElementById("point-connection-type").value
},
lineStyle: {
lineType: lineTypeMap[document.getElementById("line-type").value],
lineColor: document.getElementById("line-color").value
},
pointStyle: {
shape: document.getElementById("point-shape").value,
color: document.getElementById("point-color").value
},
dateLabelStyle: {
display: document.getElementById("label-display").checked,
format: document.getElementById("label-format").value,
font: document.getElementById("label-font").value
}
};
ganttSheet.resumePaint();
}
function addDays(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
function formatInputDate(date) {
if (!date) {
return "";
}
var year = date.getFullYear();
var month = ("0" + (date.getMonth() + 1)).slice(-2);
var day = ("0" + date.getDate()).slice(-2);
return year + "-" + month + "-" + day;
}
function parseInputDate(value) {
if (!value) {
return null;
}
var parts = value.split("-");
return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2]));
}
function getBaseApiUrl() {
return window.location.href.match(/http.+spreadjs\/learn-spreadjs\//)[0] + 'server/api';
}
function initSplitView(spread) {
var host = document.getElementById("split-view");
var content = host.getElementsByClassName("split-content")[0];
var panel = host.getElementsByClassName("split-panel")[0];
new SplitView({
host: host,
content: content,
panel: panel,
refreshContent: function() {
spread.refresh();
}
});
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta name="spreadjs culture" content="ko-kr"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css">
<!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/splitView/splitView.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-resources-ko/dist/gc.spread.sheets.resources.ko.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id="split-view" class="sample-tutorial">
<div id="ss" class="sample-spreadsheets split-content"></div>
<div class="options-container split-panel">
<div class="option-row option-title">
진행률 선을 구성합니다.
</div>
<div class="option-block">
<div class="option-row option-title">
프로젝트 날짜
</div>
<div class="option-row input-box">
<label for="current-date">현재 날짜</label>
<input type="date" id="current-date" />
</div>
<div class="option-row input-box">
<label for="status-date">상태 날짜</label>
<input type="date" id="status-date" />
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
눈금선
</div>
<div class="option-row">
<span class="line-swatch current-date-line"></span>
현재 날짜: 녹색 실선
</div>
<div class="option-row">
<span class="line-swatch status-date-line"></span>
상태 날짜: 파란색 일점쇄선
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
진행률 선
</div>
<div class="option-row">
<label class="option-checkbox-label">
<input type="checkbox" id="display" checked />
표시
</label>
</div>
<div class="option-row selection-box">
<label for="reference-date">기준 날짜</label>
<select id="reference-date">
<option value="statusDate" selected>statusDate</option>
<option value="currentDate">currentDate</option>
</select>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
경로 형식
</div>
<div class="option-row">
<label class="option-checkbox-label">
<input type="checkbox" id="return-to-reference-date" />
기준 날짜로 돌아가기
</label>
</div>
<div class="option-row selection-box">
<label for="point-connection-type">연결</label>
<select id="point-connection-type">
<option value="orthogonal" selected>orthogonal</option>
<option value="diagonal">diagonal</option>
</select>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
선 스타일
</div>
<div class="option-row selection-box">
<label for="line-type">선 형식</label>
<select id="line-type">
<option value="thin" selected>thin</option>
<option value="dashed">dashed</option>
<option value="dotted">dotted</option>
<option value="dashDot">dashDot</option>
<option value="empty">empty</option>
</select>
</div>
<div class="option-row input-box">
<label for="line-color">색</label>
<input type="text" id="line-color" value="#C0504D" />
<div class="option-info valid">* 유효한 값: 색 문자열</div>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
지점 스타일
</div>
<div class="option-row selection-box">
<label for="point-shape">모양</label>
<select id="point-shape">
<option value="arrowDown">arrowDown</option>
<option value="arrowUp">arrowUp</option>
<option value="caretDownTop">caretDownTop</option>
<option value="caretUpBottom">caretUpBottom</option>
<option value="circleDiamond" selected>circleDiamond</option>
<option value="circle">circle</option>
<option value="circleArrowDown">circleArrowDown</option>
<option value="circleArrowUp">circleArrowUp</option>
<option value="circleTriangleDown">circleTriangleDown</option>
<option value="circleTriangleUp">circleTriangleUp</option>
<option value="diamond">diamond</option>
<option value="houseDown">houseDown</option>
<option value="houseUp">houseUp</option>
<option value="leftBracket">leftBracket</option>
<option value="leftFade">leftFade</option>
<option value="lineShape">lineShape</option>
<option value="rightBracket">rightBracket</option>
<option value="rightFade">rightFade</option>
<option value="square">square</option>
<option value="star">star</option>
<option value="triangleDown">triangleDown</option>
<option value="triangleLeft">triangleLeft</option>
<option value="triangleRight">triangleRight</option>
<option value="triangleUp">triangleUp</option>
</select>
</div>
<div class="option-row input-box">
<label for="point-color">색</label>
<input type="text" id="point-color" value="#C0504D" />
<div class="option-info valid">* 유효한 값: 색 문자열</div>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
날짜 레이블 스타일
</div>
<div class="option-row">
<label class="option-checkbox-label">
<input type="checkbox" id="label-display" checked />
표시
</label>
</div>
<div class="option-row input-box">
<label for="label-format">형식</label>
<input type="text" id="label-format" value="yyyy-MM-dd" />
</div>
<div class="option-row input-box">
<label for="label-font">글꼴</label>
<input type="text" id="label-font" value="10pt Calibri" />
</div>
</div>
<div class="option-block">
<div class="option-row">
<input type="button" id="apply-progress-line" class="option-button" value="진행률 선 적용">
</div>
</div>
</div>
</div>
</body>
</html>
.sample-tutorial {
width: 100%;
height: 100%;
}
body, html {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.sample-spreadsheets {
width: 100%;
height: 100%;
}
.options-container {
float: right;
width: 300px;
padding: 12px;
height: 100%;
box-sizing: border-box;
background: #fbfbfb;
overflow: auto;
box-shadow: inset 0px 0 4px 0 rgba(0,0,0,0.4);
}
.option-block {
background: #fff;
padding: 8px;
margin: 12px 0;
border-radius: 4px;
border: 1px dashed #82bc00;
box-shadow: 0px 0 6px 0 rgba(0,0,0,0.1);
}
.option-row {
font-size: 14px;
box-sizing: border-box;
padding: 4px 0;
color: #656565;
}
.option-title {
font-weight: bold;
color: #656565;
}
.option-info {
font-size: 12px;
color: #919191;
margin-top: 6px;
font-weight: normal;
}
.option-info.valid {
color: #82bc00;
}
.option-button {
width: 100%;
padding: 0;
line-height: 22px;
background: #82bc00;
color: #fff;
transition: 0.3s;
cursor: pointer;
outline: none;
border-radius: 4px;
box-sizing: border-box;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3);
border: none;
}
.option-button:hover {
background: #82bc00;
color: #fff;
box-shadow: 0 3px 8px 0 rgba(0,0,0,0.4);
}
.option-checkbox-label {
cursor: pointer;
}
.selection-box {
position: relative;
}
.selection-box > select {
text-align: left;
width: 100%;
height: 20px;
padding: 0;
line-height: 20px;
background: transparent;
border: none;
border-bottom: 2px solid #656565;
color: #656565;
transition: 0.3s;
cursor: pointer;
outline: none;
box-sizing: border-box;
}
.selection-box > select > option {
background: white;
}
.selection-box > select:focus {
border-bottom: 2px solid #82bc00;
color: #82bc00;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.3);
}
.selection-box > label {
position: absolute;
cursor: pointer;
font-size: 12px;
color: #fff;
background: #656565;
padding: 0 4px;
right: 0;
top: 6px;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3);
}
.input-box {
position: relative;
}
.input-box > input[type=text],
.input-box > input[type=date] {
width: 100%;
height: 22px;
background: transparent;
border: none;
color: #656565;
border-bottom: 2px solid #656565;
outline: none;
box-sizing: border-box;
transition: 0.3s;
}
.input-box > input[type=text]:focus,
.input-box > input[type=date]:focus {
color: #82bc00;
border-bottom: 2px solid #82bc00;
}
.input-box > input:disabled {
color: #b0b0b0;
border-bottom-color: #c9c9c9;
}
.input-box > label {
cursor: pointer;
position: absolute;
right: 0;
top: 5px;
font-size: 12px;
color: #fff;
background: #656565;
padding: 0 4px;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3);
}
.line-swatch {
display: inline-block;
width: 36px;
height: 0;
margin-right: 6px;
vertical-align: middle;
}
.current-date-line {
border-top: 2px solid #4A8F40;
}
.status-date-line {
border-top: 2px dashed #5B9BD5;
border-top-style: dashed;
}