Gantt: Configurable format for dates on x-axis

Flowchart: Default styles for links as discussed in issue #31
This commit is contained in:
knsv 2015-02-28 23:50:23 +01:00
parent 8598a7d712
commit 3c5a19e5a7
15 changed files with 674 additions and 429 deletions

311
dist/mermaid.full.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

311
dist/mermaid.slim.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -108,6 +108,15 @@ exports.addVertices = function (vert, g) {
exports.addEdges = function (edges, g) {
var cnt=0;
var aHead;
var defaultStyle;
if(typeof edges.defaultStyle !== 'undefined'){
defaultStyle = edges.defaultStyle.toString().replace(/,/g , ';');
console.log('edges def: '+defaultStyle);
//console.log('edges def:'+defaultStyle.replace(',' , ';','g'));
}
edges.forEach(function (edge) {
cnt++;
@ -122,7 +131,6 @@ exports.addEdges = function (edges, g) {
var style = '';
if(typeof edge.style !== 'undefined'){
edge.style.forEach(function(s){
style = style + s +';';
@ -132,6 +140,9 @@ exports.addEdges = function (edges, g) {
switch(edge.stroke){
case 'normal':
style = 'stroke: #333; stroke-width: 1.5px;fill:none';
if(typeof defaultStyle !== 'undefined'){
style = defaultStyle;
}
break;
case 'dotted':
style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;';
@ -140,8 +151,6 @@ exports.addEdges = function (edges, g) {
style = 'stroke: #333; stroke-width: 3.5px;fill:none';
break;
}
}
// Add the edge to the graph

View File

@ -75,7 +75,12 @@ exports.addLink = function (start, end, type, linktext) {
*/
exports.updateLink = function (pos, style) {
var position = pos.substr(1);
edges[pos].style = style;
if(pos === 'default'){
edges.defaultStyle = style;
}else{
edges[pos].style = style;
}
};
exports.addClass = function (id, style) {

View File

@ -9,6 +9,7 @@
%%
"style" return 'STYLE';
"default" return 'DEFAULT';
"linkStyle" return 'LINKSTYLE';
"classDef" return 'CLASSDEF';
"class" return 'CLASS';
@ -384,8 +385,10 @@ textNoTags: textNoTagsToken
;
classDefStatement:CLASSDEF SPACE alphaNum SPACE stylesOpt
classDefStatement:CLASSDEF SPACE DEFAULT SPACE stylesOpt
{$$ = $1;yy.addClass($3,$5);}
| CLASSDEF SPACE alphaNum SPACE stylesOpt
{$$ = $1;yy.addClass($3,$5);}
;
classStatement:CLASS SPACE alphaNum SPACE alphaNum
@ -402,8 +405,10 @@ styleStatement:STYLE SPACE alphaNum SPACE stylesOpt
{$$ = $1;yy.updateLink($3,$5);}
;
linkStyleStatement:
LINKSTYLE SPACE NUM SPACE stylesOpt
linkStyleStatement
: LINKSTYLE SPACE DEFAULT SPACE stylesOpt
{$$ = $1;yy.updateLink($3,$5);}
| LINKSTYLE SPACE NUM SPACE stylesOpt
{$$ = $1;yy.updateLink($3,$5);}
;
@ -426,7 +431,7 @@ styleComponent: ALPHA | COLON | MINUS | NUM | UNIT | SPACE | HEX | BRKT | DOT |
commentToken : textToken | graphCodeTokens ;
textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT ;
textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFAULT;
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;

File diff suppressed because one or more lines are too long

View File

@ -18,25 +18,25 @@ describe('when parsing a gantt diagram it',function() {
gantt.parse(str);
});
it('should handle an dateFormat definition', function () {
var str = 'gantt\ntitle Adding gantt diagram functionality to mermaid';
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
gantt.parse(str);
});
it('should handle an dateFormat definition', function () {
var str = 'gantt\ntitle Adding gantt diagram functionality to mermaid';
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
gantt.parse(str);
});
it('should handle an dateFormat definition', function () {
var str = 'gantt\nsection Documentation';
it('should handle an section definition', function () {
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
gantt.parse(str);
});
it('should handle an dateFormat definition', function () {
it('should handle a task definition', function () {
var str = 'gantt\n' +
'dateFormat yyyy-mm-dd\n' +
'title Adding gantt diagram functionality to mermaid\n' +
'section Documentation\n' +
//'section Documentation2\n';
//'Design jison grammar :';
'Design jison grammar:des1, 2014-01-01, 2014-01-04';
gantt.parse(str);

View File

@ -50,8 +50,8 @@ exports.findTaskById = function(id) {
exports.getTasks=function(){
var i;
for(i=10000;i<tasks.length;i++){
tasks[i].startTime = moment(tasks[i].startTime).format('YYYY-MM-DD');
tasks[i].endTime = moment(tasks[i].endTime).format('YYYY-MM-DD');
tasks[i].startTime = moment(tasks[i].startTime).format(dateFormat);
tasks[i].endTime = moment(tasks[i].endTime).format(dateFormat);
}
return tasks;
@ -78,11 +78,12 @@ var getStartDate = function(prevTime, dateFormat, str){
}
// Check for actual date set
if(moment(str,dateFormat,true).isValid()){
return moment(str,dateFormat).toDate();
if(moment(str,dateFormat.trim(),true).isValid()){
return moment(str,dateFormat.trim(),true).toDate();
}else{
console.log('Invalid date:'+str);
console.log('With date format:'+dateFormat);
console.log('With date format:'+dateFormat.trim());
console.log('----');
}
// Default date - now
@ -96,12 +97,12 @@ var getEndDate = function(prevTime, dateFormat, str){
if(moment(str,dateFormat,true).isValid()){
return moment(str,dateFormat).toDate();
}
var d = moment(prevTime);
// Check for length
var re = /^([\d]+)([wdh])/;
var durationStatement = re.exec(str.trim());
if(durationStatement!== null){
switch(durationStatement[2]){
case 'h':
@ -155,6 +156,8 @@ var compileData = function(prevTask, dataStr){
var task = {};
var df = exports.getDateFormat();
// Get tags like active, done cand crit
var matchFound = true;
while(matchFound){
matchFound = false;
@ -180,6 +183,7 @@ var compileData = function(prevTask, dataStr){
data[i] = data[i].trim();
}
switch(data.length){
case 1:
task.id = parseId();

View File

@ -1,7 +1,9 @@
var gantt = require('./parser/gantt').parser;
gantt.yy = require('./ganttDb');
var d3 = require('./d3');
var moment = require('moment');
var daysInChart;
var conf = {
titleTopMargin: 25,
barHeight: 20,
@ -42,7 +44,14 @@ module.exports.draw = function (text, id) {
var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = d3.min(taskArray, function (d) {
return d.startTime;
});
var endDate = d3.max(taskArray, function (d) {
return d.endTime;
});
// Set timescale
var timeScale = d3.time.scale()
.domain([d3.min(taskArray, function (d) {
@ -51,10 +60,15 @@ module.exports.draw = function (text, id) {
d3.max(taskArray, function (d) {
return d.endTime;
})])
.rangeRound([0, w - 150])
.nice(d3.time.monday);
.rangeRound([0, w - 150]);
//.nice(d3.time.monday);
var categories = [];
daysInChart = moment.duration(endDate-startDate).asDays();
console.log('startDate',startDate);
console.log('endDate',endDate);
console.log('daysInChart',daysInChart);
for (var i = 0; i < taskArray.length; i++) {
categories.push(taskArray[i].type);
@ -230,39 +244,64 @@ module.exports.draw = function (text, id) {
function makeGrid(theSidePad, theTopPad, w, h) {
var pre = [
[".%L", function (d) {
return d.getMilliseconds();
}],
[":%S", function (d) {
return d.getSeconds();
}],
// Within a hour
["h1 %I:%M", function (d) {
return d.getMinutes();
}]];
var post = [
["%Y", function () {
return true;
}]];
var mid = [
// Within a day
["%I:%M", function (d) {
return d.getHours();
}],
// Day within a week (not monday)
["%a %d", function (d) {
//return d.getDay() ==1;
return d.getDay() && d.getDate() != 1;
}],
// within a month
["%b %d", function (d) {
return d.getDate() != 1;
}],
// Month
["%B", function (d) {
return d.getMonth();
}]
];
var formatter;
if(typeof conf.axisFormatter !== 'undefined'){
mid = [];
conf.axisFormatter.forEach(function(item){
var n = [];
n[0] = item[0];
n[1] = item[1];
mid.push(n);
});
}
formatter = pre.concat(mid).concat(post);
var xAxis = d3.svg.axis()
.scale(timeScale)
.orient('bottom')
.ticks(d3.time.weeks, 1)
.tickSize(-h + theTopPad + conf.gridLineStartPadding, 0, 0)
.tickFormat(d3.time.format.multi([
[".%L", function (d) {
return d.getMilliseconds();
}],
[":%S", function (d) {
return d.getSeconds();
}],
["%I:%M", function (d) {
return d.getMinutes();
}],
["%I %p", function (d) {
return d.getHours();
}],
["%a %d", function (d) {
return d.getDay() && d.getDate() != 2;
}],
["%b %d", function (d) {
return d.getDate() != 2;
}],
["%B", function (d) {
return d.getMonth();
}],
["%Y", function () {
return true;
}]
]))
.tickFormat(d3.time.format.multi(formatter))
;
if(daysInChart >7 && daysInChart<60){
xAxis = xAxis.ticks(d3.time.monday.range);
}
var grid = svg.append('g')
.attr('class', 'grid')
.attr('transform', 'translate(' + theSidePad + ', ' + (h - 50) + ')')

View File

@ -18,8 +18,7 @@
\#[^\n]* /* skip comments */
\%%[^\n]* /* skip comments */
"gantt" return 'gantt';
"dateFormat" return 'dateFormat';
"yyyy"\-"mm"\-"dd" return 'dateFormatInst';
"dateFormat"\s[^#\n;]+ return 'dateFormat';
\d\d\d\d"-"\d\d"-"\d\d return 'date';
"title"\s[^#\n;]+ return 'title';
"section"\s[^#:\n;]+ return 'section';
@ -54,7 +53,7 @@ line
;
statement
: 'dateFormat' dateFormatInst {yy.setDateFormat($2);$$=$2;}
: 'dateFormat' {yy.setDateFormat($1.substr(11));$$=$1.substr(11);}
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}
| taskTxt taskData {yy.addTask($1,$2);$$='task';}

View File

@ -72,12 +72,12 @@
}
*/
var parser = (function(){
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,8,10,11,13,14,15],$V1=[1,9],$V2=[1,10],$V3=[1,11],$V4=[1,12];
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,8,10,11,12,13,14],$V1=[1,9],$V2=[1,10],$V3=[1,11],$V4=[1,12];
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"start":3,"gantt":4,"document":5,"EOF":6,"line":7,"SPACE":8,"statement":9,"NL":10,"dateFormat":11,"dateFormatInst":12,"title":13,"section":14,"taskTxt":15,"taskData":16,"$accept":0,"$end":1},
terminals_: {2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",11:"dateFormat",12:"dateFormatInst",13:"title",14:"section",15:"taskTxt",16:"taskData"},
productions_: [0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,2],[9,1],[9,1],[9,2]],
symbols_: {"error":2,"start":3,"gantt":4,"document":5,"EOF":6,"line":7,"SPACE":8,"statement":9,"NL":10,"dateFormat":11,"title":12,"section":13,"taskTxt":14,"taskData":15,"$accept":0,"$end":1},
terminals_: {2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",11:"dateFormat",12:"title",13:"section",14:"taskTxt",15:"taskData"},
productions_: [0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,1],[9,1],[9,2]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
/* this == yyval */
@ -99,7 +99,7 @@ case 6: case 7:
this.$=[];
break;
case 8:
yy.setDateFormat($$[$0]);this.$=$$[$0];
yy.setDateFormat($$[$0].substr(11));this.$=$$[$0].substr(11);
break;
case 9:
yy.setTitle($$[$0].substr(6));this.$=$$[$0].substr(6);
@ -112,7 +112,7 @@ yy.addTask($$[$0-1],$$[$0]);this.$='task';
break;
}
},
table: [{3:1,4:[1,2]},{1:[3]},o($V0,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:$V1,13:$V2,14:$V3,15:$V4},o($V0,[2,7],{1:[2,1]}),o($V0,[2,3]),{9:13,11:$V1,13:$V2,14:$V3,15:$V4},o($V0,[2,5]),o($V0,[2,6]),{12:[1,14]},o($V0,[2,9]),o($V0,[2,10]),{16:[1,15]},o($V0,[2,4]),o($V0,[2,8]),o($V0,[2,11])],
table: [{3:1,4:[1,2]},{1:[3]},o($V0,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:$V1,12:$V2,13:$V3,14:$V4},o($V0,[2,7],{1:[2,1]}),o($V0,[2,3]),{9:13,11:$V1,12:$V2,13:$V3,14:$V4},o($V0,[2,5]),o($V0,[2,6]),o($V0,[2,8]),o($V0,[2,9]),o($V0,[2,10]),{15:[1,14]},o($V0,[2,4]),o($V0,[2,11])],
defaultActions: {},
parseError: function parseError(str, hash) {
if (hash.recoverable) {
@ -600,9 +600,9 @@ case 4:return 4;
break;
case 5:return 11;
break;
case 6:return 12;
case 6:return 'date';
break;
case 7:return 'date';
case 7:return 12;
break;
case 8:return 13;
break;
@ -610,18 +610,16 @@ case 9:return 14;
break;
case 10:return 15;
break;
case 11:return 16;
case 11:return ':';
break;
case 12:return ':';
case 12:return 6;
break;
case 13:return 6;
break;
case 14:return 'INVALID';
case 13:return 'INVALID';
break;
}
},
rules: [/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\b)/i,/^(?:yyyy-mm-dd\b)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14],"inclusive":true}}
rules: [/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}
});
return lexer;
})();

View File

@ -18,7 +18,29 @@
sidePadding:75,
gridLineStartPadding:35,
fontSize:11,
numberSectionStyles:3
numberSectionStyles:3,
axisFormatter: [
// Within a day
["%I:%M", function (d) {
return d.getHours();
}],
// Monday a week
["w. %U", function (d) {
return d.getDay() == 1;
}],
// Day within a week (not monday)
["%a %d", function (d) {
return d.getDay() && d.getDate() != 1;
}],
// within a month
["%b %d", function (d) {
return d.getDate() != 1;
}],
// Month
["%m-%y", function (d) {
return d.getMonth();
}]
]
};
</script>
<script>
@ -160,10 +182,47 @@
</style>
</head>
<body>
<filter id="blur-effect-1">
<feGaussianBlur stdDeviation="2" />
</filter>
<h1>Gantt tests</h1>
<h1>scale tests</h1>
<h2>less then a day</h2>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD H:mm
title Adding GANTT diagram functionality to mermaid
section Design
Design jison grammar :done, crit, des1, 2014-01-06 1:30,4h
Create example text :done, after des1,6h
</div>
<h2>less then a week</h2>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid2
section Design
Design jison grammar :done, crit, des1, 2014-01-06,2d
Create example text :done, after des1,3d
</div>
<h2>less then a month</h2>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section Design
Design jison grammar :done, crit, des1, 2015-01-05,2d
Create example text :done, after des1, 2w
</div>
<h2>less then a year</h2>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section Design
Design jison grammar :done, crit, des1, 2014-01-06,8w
Create example text :done, after des1, 16w
</div>
<h1>Other tests</h1>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD

View File

@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8">
<script src="mermaid.full.js"></script>
<script src="../dist/mermaid.full.js"></script>
<script>
var mermaid_config = {
startOnLoad:true,
htmlLabels:false
htmlLabels:true
}
mermaid.startOnLoad=true;
</script>
@ -26,6 +26,17 @@
<link rel="stylesheet" href="seq.css"/>
</head>
<body>
<div class="mermaid">
graph LR;
A[Now with default style on links]-->B{a = '1,2'}
B-->|True|C[test = 1]
B-- ... default style on links -->Z[My default thing this]
C-->D{condition};
linkStyle 0 stroke-width:2px,fill:none,stroke:blue;
linkStyle default stroke-width:2px,fill:none,stroke:red;
</div>
<h1>Issue 2</h1>
<div class="mermaid">
graph LR
@ -45,12 +56,12 @@
<h1>Shapes</h1>
<div class="mermaid">
graph TD;
A-->B;
A[Default style on nodes]-->B;
A-->C;
A-->D;
B-->D;
A-->|Link text|B
classDef default fill:#696,stroke:#333,stroke-width:2px;
classDef default fill:#f96,stroke:#333,stroke-width:2px;
classDef green fill:#9f6,stroke:#333,stroke-width:2px;
class B green;
</div>