* [wip] added frappe/gantt * frappe/gantt [gantt] added view modes [gantt] added vertical grid, view modes fixed [gantt] fix bar_onclick [gantt] fix view_mode rendering [gantt] drag, resize gantt bar [gantt] fixed month view [gantt] separate styling [gantt] save on datechange, progress field added [gantt] fixed drag to snap on week/monthversion-14
@@ -61,7 +61,7 @@ frappe.Chat = Class.extend({ | |||
var $row = $('<div class="list-row"/>'); | |||
frappe.pages.chat.chat.list.data.unshift(comment); | |||
frappe.pages.chat.chat.list.render_row($row, comment); | |||
frappe.pages.chat.chat.list.$w.prepend($row); | |||
frappe.pages.chat.chat.list.wrapper.prepend($row); | |||
}, | |||
make_sidebar: function() { | |||
@@ -193,8 +193,7 @@ | |||
"css/list.min.css": [ | |||
"public/css/list.css", | |||
"public/css/tag-it.css", | |||
"public/css/calendar.css", | |||
"public/css/gantt.css" | |||
"public/css/calendar.css" | |||
], | |||
"js/list.min.js": [ | |||
"public/js/frappe/ui/listing.html", | |||
@@ -219,13 +218,13 @@ | |||
"public/js/frappe/list/listview.js", | |||
"public/js/frappe/views/calendar_base.js", | |||
"public/js/frappe/views/calendar.js", | |||
"public/js/frappe/views/ganttview.js", | |||
"public/js/frappe/list/blueimp-gallery.html", | |||
"public/js/frappe/list/image_view_item_row.html", | |||
"public/js/frappe/list/image_view_item_main_head.html", | |||
"public/js/frappe/list/header_select_all_like_filter.html", | |||
"public/js/frappe/list/item_assigned_to_comment_count.html", | |||
"public/js/frappe/views/treeview.js" | |||
"public/js/frappe/views/treeview.js", | |||
"public/js/frappe/views/gantt.js" | |||
], | |||
"css/report.min.css": [ | |||
"public/css/report.css", | |||
@@ -1,38 +1,78 @@ | |||
.gantt, | |||
.gantt2 { | |||
border: none !important; | |||
border-radius: none !important; | |||
margin: 0px auto !important; | |||
} | |||
.gantt *, | |||
.gantt2 * { | |||
-webkit-box-sizing: content-box; | |||
-moz-box-sizing: content-box; | |||
box-sizing: content-box; | |||
} | |||
.fn-gantt .leftPanel, | |||
.fn-gantt .leftPanel .row0, | |||
.fn-gantt .leftPanel .name, | |||
.fn-gantt .leftPanel .desc, | |||
.fn-gantt .dataPanel, | |||
.fn-gantt .day, | |||
.fn-gantt .date, | |||
.fn-gantt .rightPanel .month, | |||
.fn-gantt .rightPanel .year { | |||
border-color: #d1d8dd !important; | |||
} | |||
.fn-gantt .navigate { | |||
border: none !important; | |||
} | |||
.fn-gantt .leftPanel .name, | |||
.fn-gantt .leftPanel .desc, | |||
.fn-gantt .spacer, | |||
.fn-gantt .wd, | |||
.fn-gantt .rightPanel .month, | |||
.fn-gantt .rightPanel .year, | |||
.fn-gantt .bottom { | |||
background-color: #F7FAFC !important; | |||
} | |||
.fn-gantt .today { | |||
background-color: #D9F6FF !important; | |||
.gantt #grid .grid-background { | |||
fill: none; | |||
} | |||
.gantt #grid .grid-header { | |||
fill: #fff; | |||
stroke: #e0e0e0; | |||
stroke-width: 1.4; | |||
} | |||
.gantt #grid .row-odd { | |||
fill: #ffffff; | |||
} | |||
.gantt #grid .row-even { | |||
fill: #f5f5f5; | |||
} | |||
.gantt #grid .row-line { | |||
stroke: #EBEFF2; | |||
} | |||
.gantt #grid .tick { | |||
stroke: #aaa; | |||
stroke-width: 0.2; | |||
} | |||
.gantt #grid .tick.thick { | |||
stroke-width: 0.4; | |||
} | |||
.gantt #arrow { | |||
fill: none; | |||
stroke: #333; | |||
stroke-width: 1.4; | |||
} | |||
.gantt .bar { | |||
fill: #b8c2cc; | |||
stroke: #8D99A6; | |||
stroke-width: 0; | |||
transition: stroke-width 0.3s ease; | |||
} | |||
.gantt .bar-label { | |||
fill: #fff; | |||
dominant-baseline: central; | |||
text-anchor: middle; | |||
font-size: 12px; | |||
font-weight: lighter; | |||
letter-spacing: 0.8px; | |||
} | |||
.gantt .bar-label.big { | |||
fill: #555; | |||
text-anchor: start; | |||
} | |||
.gantt .handle { | |||
fill: #ddd; | |||
cursor: ew-resize; | |||
opacity: 0; | |||
visibility: hidden; | |||
transition: opacity .3s ease; | |||
} | |||
.gantt .bar-wrapper { | |||
cursor: pointer; | |||
} | |||
.gantt .bar-wrapper:hover .bar { | |||
stroke-width: 2; | |||
} | |||
.gantt .bar-wrapper:hover .handle { | |||
visibility: visible; | |||
opacity: 1; | |||
} | |||
.gantt .bar-wrapper.active .bar { | |||
stroke-width: 2; | |||
} | |||
.gantt .primary-text, | |||
.gantt .secondary-text { | |||
font-size: 12px; | |||
text-anchor: middle; | |||
} | |||
.gantt .primary-text { | |||
fill: #999; | |||
} | |||
.gantt .secondary-text { | |||
fill: #555; | |||
} |
@@ -130,14 +130,13 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
this.init_listview(); | |||
this.setup_filterable(); | |||
this.init_filters(); | |||
this.init_headers(); | |||
this.init_sort_selector(); | |||
this.init_like(); | |||
this.init_select_all(); | |||
}, | |||
init_headers: function() { | |||
this.header = this.meta.image_view == 0? "list_item_main_head": "image_view_item_main_head"; | |||
this.page.main.find(".list-headers").empty(); | |||
this.header = this.current_view === 'List' ? "list_item_main_head": "image_view_item_main_head"; | |||
var main = frappe.render_template(this.header, { | |||
columns: this.listview.columns, | |||
right_column: this.listview.settings.right_column, | |||
@@ -147,6 +146,9 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
this.list_header = $(frappe.render_template("list_item_row_head", { main:main, list:this.listview })) | |||
.appendTo(this.page.main.find(".list-headers")); | |||
this.init_like(); | |||
this.init_select_all(); | |||
}, | |||
init_listview: function() { | |||
@@ -303,7 +305,14 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
refresh: function(dirty) { | |||
if(dirty!==undefined) this.dirty = dirty; | |||
this.init_stats(); | |||
this.refresh_sidebar(); | |||
// if view has changed, re-render header | |||
if(this.current_view != this.list_sidebar.current_view) { | |||
this.current_view = this.list_sidebar.current_view; | |||
this.init_headers(); | |||
this.dirty = true; | |||
} | |||
if(this.listview.settings.refresh) { | |||
this.listview.settings.refresh(this); | |||
@@ -354,8 +363,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
if(!this.listview.settings.use_route) { | |||
var route = frappe.get_route(); | |||
var me = this; | |||
if(route[2]) { | |||
if(route[2] && !in_list(['Image', 'Gantt'], route[2])) { | |||
$.each(frappe.utils.get_args_dict_from_url(route[2]), function(key, val) { | |||
me.set_filter(key, val, true); | |||
}); | |||
@@ -401,16 +409,131 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
return no_result_message; | |||
}, | |||
render_rows: function(values) { | |||
this['render_rows_' + this.current_view](values); | |||
}, | |||
render_rows_Image: function(values) { | |||
var cols = values.slice(); | |||
while (cols.length) { | |||
row = this.add_row(cols[0]); | |||
$("<div class='row image-view-marker'></div>").appendTo(row); | |||
$(row).addClass('no-hover'); | |||
this.render_image_view_row(row, cols.splice(0, 4)); | |||
} | |||
this.render_image_gallery(); | |||
}, | |||
render_rows_List: function(values) { | |||
var m = Math.min(values.length, this.page_length); | |||
for(var i=0; i < m; i++) { | |||
this.render_row(this.add_row(values[i]), values[i], this, i); | |||
} | |||
}, | |||
render_rows_Gantt: function(values) { | |||
var gantt_area = $('<svg height="400" width="6000"></svg>') | |||
.appendTo(this.wrapper.find('.result-list').css("overflow", "scroll")); | |||
var id = frappe.dom.set_unique_id(gantt_area); | |||
var me = this; | |||
var field_map = frappe.views.calendar[this.doctype].field_map; | |||
var view_modes; | |||
frappe.require(["assets/frappe/js/lib/snap.svg-min.js", "assets/frappe/css/gantt.css"], function() { | |||
me.gantt = new Gantt({ | |||
parent_selector: '#' + id, | |||
bar: { | |||
height: 20, | |||
color: "#b8c2cc", | |||
progress_color: "#a3a3ff", | |||
hover_color: "#8D99A6", | |||
hover_progress_color: "#7575ff" | |||
}, | |||
events: { | |||
bar_on_click: function (task) { | |||
frappe.set_route('Form', task.doctype, task.id); | |||
}, | |||
bar_on_datechange: function(task, start, end) { | |||
update_date(task.id, field_map.start, start.format("YYYY-MM-DD"), function() { | |||
update_date(task.id, field_map.end, end.format("YYYY-MM-DD"), function() { | |||
show_alert("Saved", 1); | |||
}); | |||
}); | |||
}, | |||
on_viewmode_change: function(mode) { | |||
me.list_settings.view_mode = mode; | |||
} | |||
} | |||
}); | |||
view_modes = me.gantt.opts.valid_view_modes || []; | |||
values.forEach(function(item) { | |||
me.gantt.add_task({ | |||
start: item[field_map.start], | |||
end: item[field_map.end], | |||
name: item[field_map.title], | |||
id: item[field_map.id], | |||
doctype: me.doctype, | |||
progress: item.progress | |||
}); | |||
}) | |||
me.gantt.render(); | |||
var dropdown = "<div class='dropdown pull-right'>" + | |||
"<a class='text-muted dropdown-toggle' data-toggle='dropdown'>" + | |||
"<span class='dropdown-text'>Day</span><i class='caret'></i></a>" + | |||
"<ul class='dropdown-menu'></ul>" + | |||
"</div>"; | |||
var dropdown_list = ""; | |||
view_modes.forEach(function(view_mode) { | |||
dropdown_list += "<li>" + | |||
"<a class='option' data-value='"+view_mode+"'>" + | |||
view_mode + "</a></li>"; | |||
}) | |||
var $dropdown = $(dropdown) | |||
$dropdown.find(".dropdown-menu") | |||
.append(dropdown_list); | |||
me.$page.find(".list-row-right").css("margin-top", 0).html($dropdown) | |||
$dropdown.on("click", ".option", function() { | |||
var mode = $(this).data('value'); | |||
me.gantt.set_view_mode(mode) | |||
$dropdown.find(".dropdown-text").text(mode); | |||
}) | |||
}); | |||
function update_date(id, fieldname, value, callback) { | |||
frappe.call({ | |||
method: "frappe.client.set_value", | |||
args: { | |||
doctype: me.doctype, | |||
name: id, | |||
fieldname: fieldname, | |||
value: value | |||
}, | |||
callback: function(r) { | |||
callback(); | |||
} | |||
}); | |||
} | |||
}, | |||
render_row: function(row, data) { | |||
data.doctype = this.doctype; | |||
this.listview.render(row, data, this); | |||
}, | |||
render_image_view_row: function(row, data) { | |||
for (var i = 0; i < data.length; i++) { | |||
data[i].doctype = this.doctype; | |||
this.listview.render(row, data[i], this) | |||
} | |||
}, | |||
get_args: function() { | |||
var args = { | |||
doctype: this.doctype, | |||
@@ -644,7 +767,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
}); | |||
// after delete, hide delete button | |||
this.$w.on("render-complete", function() { | |||
this.wrapper.on("render-complete", function() { | |||
me.toggle_delete(); | |||
}); | |||
} | |||
@@ -675,7 +798,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
get_checked_items: function() { | |||
var me = this; | |||
return $.map(this.$page.find('.list-delete:checked'), function(e) { | |||
if(me.meta.image_view == 0){ | |||
if(me.current_view==='List'){ | |||
return $(e).parents(".list-row:first").data('data'); | |||
} | |||
else{ | |||
@@ -711,9 +834,9 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ | |||
} | |||
); | |||
}, | |||
init_stats: function() { | |||
refresh_sidebar: function() { | |||
var me = this; | |||
this.sidebar_stats = new frappe.views.ListSidebar({ | |||
this.list_sidebar = new frappe.views.ListSidebar({ | |||
doctype: this.doctype, | |||
stats: this.listview.stats, | |||
parent: this.$page.find('.layout-side-section'), | |||
@@ -14,15 +14,17 @@ | |||
</div> | |||
</li> | |||
<li class="divider"></li> | |||
<li class="hide list-link" data-view="List"> | |||
<a href="#List/{%= doctype %}">{%= __("List") %}</a></li> | |||
<li class="hide list-link" data-view="Image"> | |||
<a href="#List/{%= doctype %}/Image">{%= __("Images") %}</a></li> | |||
<li class="hide list-link" data-view="Gantt"> | |||
<a href="#List/{%= doctype %}/Gantt">{%= __("Gantt") %}</a></li> | |||
<li class="hide tree-link"><a href="#Tree/{%= doctype %}">{%= __("Tree") %}</a></li> | |||
<li class="hide calendar-link"><a href="#Calendar/{%= doctype %}">{%= __("Calendar") %}</a></li> | |||
<li class="hide gantt-link"><a href="#Gantt/{%= doctype %}">{%= __("Gantt") %}</a></li> | |||
<li class="assigned-to-me"> | |||
<a>{%= __("Assigned To Me") %}</a> | |||
</li> | |||
<li class="hide switch-list-view"> | |||
<a>{%= __("Show Images") %}</a> | |||
</li> | |||
{% if(frappe.help.has_help(doctype)) { %} | |||
<li><a class="help-link" data-doctype="{{ doctype }}">{{ __("Help") }}</a></li> | |||
{% } %} | |||
@@ -24,15 +24,41 @@ frappe.views.ListSidebar = Class.extend({ | |||
this.setup_reports(); | |||
this.setup_assigned_to_me(); | |||
this.setup_list_view_switching(); | |||
this.setup_views(); | |||
}, | |||
setup_views: function() { | |||
var show_list_link = false; | |||
if(frappe.views.calendar[this.doctype]) { | |||
this.sidebar.find(".calendar-link, .gantt-link").removeClass("hide"); | |||
this.sidebar.find(".calendar-link").removeClass("hide"); | |||
this.sidebar.find('.list-link[data-view="Gantt"]').removeClass('hide'); | |||
show_list_link = true; | |||
} | |||
if(frappe.treeview_settings[this.doctype]) { | |||
this.sidebar.find(".tree-link").removeClass("hide"); | |||
} | |||
this.current_view = 'List'; | |||
var route = frappe.get_route(); | |||
if(route.length > 2 && (route[2]==='Gantt' || route[2]==='Image')) { | |||
this.current_view = route[2]; | |||
} | |||
// disable link for current view | |||
this.sidebar.find('.list-link[data-view="'+ this.current_view +'"] a') | |||
.attr('disabled', 'disabled').addClass('disabled'); | |||
// show image link if image_view | |||
if(this.doclistview.meta.image_field) { | |||
this.sidebar.find('.list-link[data-view="Image"]').removeClass('hide'); | |||
show_list_link = true; | |||
} | |||
if(show_list_link) { | |||
this.sidebar.find('.list-link[data-view="List"]').removeClass('hide'); | |||
} | |||
}, | |||
setup_reports: function() { | |||
// add reports linked to this doctype to the dropdown | |||
@@ -78,35 +104,6 @@ frappe.views.ListSidebar = Class.extend({ | |||
me.doclistview.assigned_to_me(); | |||
}); | |||
}, | |||
setup_list_view_switching: function() { | |||
var me = this; | |||
if(this.doclistview.meta.image_field) { | |||
this.page.sidebar.find(".switch-list-view").removeClass("hide"); | |||
var label = this.doclistview.meta.image_view ? __("Show List"): __("Show Images"); | |||
this.page.sidebar.find(".switch-list-view a").html(label) | |||
var switch_list_view = function(view) { | |||
var image_view = 0 | |||
if(view == __("Show Images")) | |||
image_view = 1 | |||
me.doclistview.meta.image_view = image_view; | |||
// clear and render the headers again while switching | |||
me.doclistview.page.main.find(".list-headers").empty(); | |||
me.doclistview.init_headers(); | |||
me.doclistview.init_like(); | |||
me.doclistview.init_select_all(); | |||
me.doclistview.refresh(true); | |||
}; | |||
this.page.sidebar.find(".switch-list-view a").on("click", function() { | |||
switch_list_view(label) | |||
}); | |||
} | |||
}, | |||
get_stats: function() { | |||
var me = this | |||
return frappe.call({ | |||
@@ -214,12 +214,7 @@ frappe.views.ListView = Class.extend({ | |||
this.id_list.push(data.name); | |||
} | |||
if(this.meta && this.meta.image_view == 0){ | |||
this.render_list_row(row, data); | |||
} | |||
else{ | |||
this.render_list_image(row, data); | |||
} | |||
this['render_row_' + this.doclistview.current_view](row, data); | |||
if(this.settings.post_render_item) { | |||
this.settings.post_render_item(this, row, data); | |||
@@ -228,7 +223,7 @@ frappe.views.ListView = Class.extend({ | |||
this.render_tags(row, data); | |||
}, | |||
render_list_row: function(row, data) { | |||
render_row_List: function(row, data) { | |||
var main = frappe.render_template("list_item_main", { | |||
data: data, | |||
columns: this.columns, | |||
@@ -244,7 +239,7 @@ frappe.views.ListView = Class.extend({ | |||
right_column: this.settings.right_column | |||
})).appendTo(row); | |||
}, | |||
render_list_image: function(row, data) { | |||
render_row_Image: function(row, data) { | |||
this.allowed_type = [ | |||
"Check", "Currency", "Data", "Date", | |||
"Datetime", "Float", "Int", "Link", | |||
@@ -290,7 +285,7 @@ frappe.views.ListView = Class.extend({ | |||
//me.render_timestamp_and_comments(row, data); | |||
} | |||
}); | |||
tag_editor.$w.on("click", ".tagit-label", function() { | |||
tag_editor.wrapper.on("click", ".tagit-label", function() { | |||
me.doclistview.set_filter("_user_tags", | |||
$(this).text()); | |||
}); | |||
@@ -5,22 +5,22 @@ frappe.ui.FilterList = Class.extend({ | |||
init: function(opts) { | |||
$.extend(this, opts); | |||
this.filters = []; | |||
this.$w = this.$parent; | |||
this.wrapper = this.$parent; | |||
this.set_events(); | |||
}, | |||
set_events: function() { | |||
var me = this; | |||
// show filters | |||
this.$w.find('.new-filter').bind('click', function() { | |||
this.wrapper.find('.new-filter').bind('click', function() { | |||
me.add_filter(me.doctype, 'name'); | |||
}); | |||
}, | |||
show_filters: function() { | |||
this.$w.find('.show_filters').toggle(); | |||
this.wrapper.find('.show_filters').toggle(); | |||
if(!this.filters.length) { | |||
this.add_filter(this.doctype, 'name'); | |||
this.filters[0].$w.find(".filter_field input").focus(); | |||
this.filters[0].wrapper.find(".filter_field input").focus(); | |||
} | |||
}, | |||
@@ -42,10 +42,10 @@ frappe.ui.FilterList = Class.extend({ | |||
} | |||
this.$w.find('.show_filters').toggle(true); | |||
this.wrapper.find('.show_filters').toggle(true); | |||
var is_new_filter = arguments.length===0; | |||
if (is_new_filter && this.$w.find(".is-new-filter:visible").length) { | |||
if (is_new_filter && this.wrapper.find(".is-new-filter:visible").length) { | |||
// only allow 1 new filter at a time! | |||
return; | |||
} | |||
@@ -53,7 +53,7 @@ frappe.ui.FilterList = Class.extend({ | |||
var filter = this.push_new_filter(doctype, fieldname, condition, value); | |||
if (filter && is_new_filter) { | |||
filter.$w.addClass("is-new-filter"); | |||
filter.wrapper.addClass("is-new-filter"); | |||
} | |||
if (filter && hidden) { | |||
@@ -131,12 +131,12 @@ frappe.ui.Filter = Class.extend({ | |||
this.set_events(); | |||
}, | |||
make: function() { | |||
this.$w = $(frappe.render_template("edit_filter", {})).appendTo(this.flist.$w.find('.filter_area')); | |||
this.wrapper = $(frappe.render_template("edit_filter", {})).appendTo(this.flist.wrapper.find('.filter_area')); | |||
}, | |||
make_select: function() { | |||
var me = this; | |||
this.fieldselect = new frappe.ui.FieldSelect({ | |||
parent: this.$w.find('.fieldname_select_area'), | |||
parent: this.wrapper.find('.fieldname_select_area'), | |||
doctype: this.doctype, | |||
filter_fields: this.filter_fields, | |||
select: function(doctype, fieldname) { | |||
@@ -150,17 +150,17 @@ frappe.ui.Filter = Class.extend({ | |||
set_events: function() { | |||
var me = this; | |||
this.$w.find("a.remove-filter").on("click", function() { | |||
this.wrapper.find("a.remove-filter").on("click", function() { | |||
me.remove(); | |||
}); | |||
this.$w.find(".set-filter-and-run").on("click", function() { | |||
me.$w.removeClass("is-new-filter"); | |||
this.wrapper.find(".set-filter-and-run").on("click", function() { | |||
me.wrapper.removeClass("is-new-filter"); | |||
me.flist.listobj.run(); | |||
}); | |||
// add help for "in" codition | |||
me.$w.find('.condition').change(function() { | |||
me.wrapper.find('.condition').change(function() { | |||
if(!me.field) return; | |||
var condition = $(this).val(); | |||
if(in_list(["in", "like", "not in", "not like"], condition)) { | |||
@@ -188,7 +188,7 @@ frappe.ui.Filter = Class.extend({ | |||
}, | |||
remove: function(dont_run) { | |||
this.$w.remove(); | |||
this.wrapper.remove(); | |||
this.$btn_group && this.$btn_group.remove(); | |||
this.field = null; | |||
this.flist.update_filters(); | |||
@@ -202,7 +202,7 @@ frappe.ui.Filter = Class.extend({ | |||
set_values: function(doctype, fieldname, condition, value) { | |||
// presents given (could be via tags!) | |||
this.set_field(doctype, fieldname); | |||
if(condition) this.$w.find('.condition').val(condition).change(); | |||
if(condition) this.wrapper.find('.condition').val(condition).change(); | |||
if(value!=null) this.field.set_input(value); | |||
}, | |||
@@ -247,7 +247,7 @@ frappe.ui.Filter = Class.extend({ | |||
old_text = me.field.get_parsed_value(); | |||
} | |||
var field_area = me.$w.find('.filter_field').empty().get(0); | |||
var field_area = me.wrapper.find('.filter_field').empty().get(0); | |||
var f = frappe.ui.form.make_control({ | |||
df: df, | |||
parent: field_area, | |||
@@ -301,7 +301,7 @@ frappe.ui.Filter = Class.extend({ | |||
} else if(['Text','Small Text','Text Editor','Code','Tag','Comments', | |||
'Dynamic Link','Read Only','Assign'].indexOf(df.fieldtype)!=-1) { | |||
df.fieldtype = 'Data'; | |||
} else if(df.fieldtype=='Link' && this.$w.find('.condition').val()!="=") { | |||
} else if(df.fieldtype=='Link' && this.wrapper.find('.condition').val()!="=") { | |||
df.fieldtype = 'Data'; | |||
} | |||
if(df.fieldtype==="Data" && (df.options || "").toLowerCase()==="email") { | |||
@@ -313,9 +313,9 @@ frappe.ui.Filter = Class.extend({ | |||
if(!fieldtype) { | |||
// set as "like" for data fields | |||
if(df.fieldtype=='Data') { | |||
this.$w.find('.condition').val('like'); | |||
this.wrapper.find('.condition').val('like'); | |||
} else { | |||
this.$w.find('.condition').val('='); | |||
this.wrapper.find('.condition').val('='); | |||
} | |||
} | |||
}, | |||
@@ -356,14 +356,14 @@ frappe.ui.Filter = Class.extend({ | |||
}, | |||
get_condition: function() { | |||
return this.$w.find('.condition').val(); | |||
return this.wrapper.find('.condition').val(); | |||
}, | |||
freeze: function() { | |||
if(this.$btn_group) { | |||
// already made, just hide the condition setter | |||
this.set_filter_button_text(); | |||
this.$w.toggle(false); | |||
this.wrapper.toggle(false); | |||
return; | |||
} | |||
@@ -379,7 +379,7 @@ frappe.ui.Filter = Class.extend({ | |||
title="'+__("Remove Filter")+'">\ | |||
<i class="icon-remove text-muted"></i>\ | |||
</button></div>') | |||
.insertAfter(this.flist.$w.find(".set-filters .new-filter")); | |||
.insertAfter(this.flist.wrapper.find(".set-filters .new-filter")); | |||
this.set_filter_button_text(); | |||
@@ -388,9 +388,9 @@ frappe.ui.Filter = Class.extend({ | |||
}); | |||
this.$btn_group.find(".toggle-filter").on("click", function() { | |||
me.$w.toggle(); | |||
me.wrapper.toggle(); | |||
}) | |||
this.$w.toggle(false); | |||
this.wrapper.toggle(false); | |||
}, | |||
set_filter_button_text: function() { | |||
@@ -27,15 +27,15 @@ | |||
<div class="list-paging-area"> | |||
<div class="row"> | |||
<div class="col-xs-6"> | |||
<button class="btn btn-default btn-more btn-sm">{%= _more %}...</button> | |||
</div> | |||
<div class="col-xs-6"> | |||
<div class="btn-group pull-right btn-group-paging"> | |||
<div class="btn-group btn-group-paging"> | |||
<button type="button" class="btn btn-default btn-sm btn-info" data-value="20">20</button> | |||
<button type="button" class="btn btn-default btn-sm" data-value="100">100</button> | |||
<button type="button" class="btn btn-default btn-sm" data-value="500">500</button> | |||
</div> | |||
</div> | |||
<div class="col-xs-6 text-right"> | |||
<button class="btn btn-default btn-more btn-sm">{%= _more %}...</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -64,11 +64,11 @@ frappe.ui.Listing = Class.extend({ | |||
$.extend(this, this.opts); | |||
$(this.parent).html(frappe.render_template("listing", this.opts)); | |||
this.$w = $(this.parent).find('.frappe-list'); | |||
this.wrapper = $(this.parent).find('.frappe-list'); | |||
this.set_events(); | |||
if(this.page) { | |||
this.$w.find('.list-toolbar-wrapper').toggle(false); | |||
this.wrapper.find('.list-toolbar-wrapper').toggle(false); | |||
} | |||
if(this.show_filters) { | |||
@@ -79,9 +79,9 @@ frappe.ui.Listing = Class.extend({ | |||
if(this.page) { | |||
return this.page.add_menu_item(label, click, icon) | |||
} else { | |||
this.$w.find('.list-toolbar-wrapper').removeClass("hide"); | |||
this.wrapper.find('.list-toolbar-wrapper').removeClass("hide"); | |||
$button = $('<button class="btn btn-default"></button>') | |||
.appendTo(this.$w.find('.list-toolbar')) | |||
.appendTo(this.wrapper.find('.list-toolbar')) | |||
.html((icon ? ("<i class='"+icon+"'></i> ") : "") + label) | |||
.click(click); | |||
return $button | |||
@@ -91,13 +91,13 @@ frappe.ui.Listing = Class.extend({ | |||
var me = this; | |||
// next page | |||
this.$w.find('.btn-more').click(function() { | |||
this.wrapper.find('.btn-more').click(function() { | |||
me.run(true); | |||
}); | |||
this.$w.find(".btn-group-paging .btn").click(function() { | |||
this.wrapper.find(".btn-group-paging .btn").click(function() { | |||
me.page_length = cint($(this).attr("data-value")); | |||
me.$w.find(".btn-group-paging .btn-info").removeClass("btn-info"); | |||
me.wrapper.find(".btn-group-paging .btn-info").removeClass("btn-info"); | |||
$(this).addClass("btn-info"); | |||
// always reset when changing list page length | |||
@@ -106,20 +106,20 @@ frappe.ui.Listing = Class.extend({ | |||
// select the correct page length | |||
if(this.opts.page_length != 20) { | |||
this.$w.find(".btn-group-paging .btn-info").removeClass("btn-info"); | |||
this.$w.find(".btn-group-paging .btn[data-value='"+ this.opts.page_length +"']").addClass('btn-info'); | |||
this.wrapper.find(".btn-group-paging .btn-info").removeClass("btn-info"); | |||
this.wrapper.find(".btn-group-paging .btn[data-value='"+ this.opts.page_length +"']").addClass('btn-info'); | |||
} | |||
// title | |||
if(this.title) { | |||
this.$w.find('h3').html(this.title).toggle(true); | |||
this.wrapper.find('h3').html(this.title).toggle(true); | |||
} | |||
// new | |||
this.set_primary_action(); | |||
if(me.no_toolbar || me.hide_toolbar) { | |||
me.$w.find('.list-toolbar-wrapper').toggle(false); | |||
me.wrapper.find('.list-toolbar-wrapper').toggle(false); | |||
} | |||
}, | |||
@@ -159,7 +159,7 @@ frappe.ui.Listing = Class.extend({ | |||
make_filters: function() { | |||
this.filter_list = new frappe.ui.FilterList({ | |||
listobj: this, | |||
$parent: this.$w.find('.list-filters').toggle(true), | |||
$parent: this.wrapper.find('.list-filters').toggle(true), | |||
doctype: this.doctype, | |||
filter_fields: this.filter_fields | |||
}); | |||
@@ -170,9 +170,9 @@ frappe.ui.Listing = Class.extend({ | |||
clear: function() { | |||
this.data = []; | |||
this.$w.find('.result-list').empty(); | |||
this.$w.find('.result').toggle(true); | |||
this.$w.find('.no-result').toggle(false); | |||
this.wrapper.find('.result-list').empty(); | |||
this.wrapper.find('.result').toggle(true); | |||
this.wrapper.find('.no-result').toggle(false); | |||
this.start = 0; | |||
}, | |||
@@ -274,7 +274,7 @@ frappe.ui.Listing = Class.extend({ | |||
} | |||
}, | |||
set_working: function(flag) { | |||
this.$w.find('.img-load').toggle(flag); | |||
this.wrapper.find('.img-load').toggle(flag); | |||
}, | |||
get_call_args: function() { | |||
// load query | |||
@@ -305,7 +305,7 @@ frappe.ui.Listing = Class.extend({ | |||
render_results: function(r) { | |||
if(this.start===0) this.clear(); | |||
this.$w.find('.btn-more, .list-loading').toggle(false); | |||
this.wrapper.find('.btn-more, .list-loading').toggle(false); | |||
if(r.message) { | |||
r.values = this.get_values_from_response(r.message); | |||
@@ -317,7 +317,7 @@ frappe.ui.Listing = Class.extend({ | |||
this.update_paging(r.values); | |||
} else { | |||
if(this.start===0) { | |||
this.$w.find('.result').toggle(false); | |||
this.wrapper.find('.result').toggle(false); | |||
var msg = this.get_no_result_message | |||
? this.get_no_result_message() | |||
@@ -325,7 +325,7 @@ frappe.ui.Listing = Class.extend({ | |||
? this.no_result_message | |||
: __("Nothing to show")); | |||
this.$w.find('.no-result') | |||
this.wrapper.find('.no-result') | |||
.html(msg) | |||
.toggle(true); | |||
} | |||
@@ -334,7 +334,7 @@ frappe.ui.Listing = Class.extend({ | |||
// callbacks | |||
if(this.onrun) this.onrun(); | |||
if(this.callback) this.callback(r); | |||
this.$w.trigger("render-complete"); | |||
this.wrapper.trigger("render-complete"); | |||
}, | |||
get_values_from_response: function(data) { | |||
@@ -356,21 +356,9 @@ frappe.ui.Listing = Class.extend({ | |||
}, | |||
render_rows: function(values) { | |||
// render the rows | |||
if(this.meta && this.meta.image_view){ | |||
var cols = values.slice(); | |||
while (cols.length) { | |||
row = this.add_row(cols[0]); | |||
$("<div class='row image-view-marker'></div>").appendTo(row); | |||
$(row).addClass('no-hover'); | |||
this.render_image_view_row(row, cols.splice(0, 4), this, i); | |||
} | |||
this.render_image_gallery(); | |||
} else { | |||
var m = Math.min(values.length, this.page_length); | |||
for(var i=0; i < m; i++) { | |||
this.render_row(this.add_row(values[i]), values[i], this, i); | |||
} | |||
var m = Math.min(values.length, this.page_length); | |||
for(var i=0; i < m; i++) { | |||
this.render_row(this.add_row(values[i]), values[i], this, i); | |||
} | |||
}, | |||
render_image_gallery: function(){ | |||
@@ -384,17 +372,17 @@ frappe.ui.Listing = Class.extend({ | |||
"assets/frappe/js/lib/gallery/css/blueimp-gallery-indicator.css" | |||
], function(){ | |||
// remove previous gallery container | |||
me.$w.find(".blueimp-gallery").remove(); | |||
me.wrapper.find(".blueimp-gallery").remove(); | |||
// append gallery div | |||
var gallery = frappe.render_template("blueimp-gallery", {}); | |||
$(gallery).appendTo(me.$w); | |||
$(gallery).appendTo(me.wrapper); | |||
me.$w.find(".zoom-view").click(function(event){ | |||
me.wrapper.find(".zoom-view").click(function(event){ | |||
event.preventDefault(); | |||
opts = { | |||
doctype: me.doctype, | |||
docname: $(this).parent().attr('data-name'), | |||
container: me.$w | |||
container: me.wrapper | |||
}; | |||
new frappe.views.ImageView(opts); | |||
}); | |||
@@ -402,14 +390,14 @@ frappe.ui.Listing = Class.extend({ | |||
}, | |||
update_paging: function(values) { | |||
if(values.length >= this.page_length) { | |||
this.$w.find('.btn-more').toggle(true); | |||
this.wrapper.find('.btn-more').toggle(true); | |||
this.start += this.page_length; | |||
} | |||
}, | |||
add_row: function(row) { | |||
return $('<div class="list-row">') | |||
.data("data", (this.meta && this.meta.image_view) == 0 ? row : null) | |||
.appendTo(this.$w.find('.result-list')) | |||
.appendTo(this.wrapper.find('.result-list')) | |||
.get(0); | |||
}, | |||
refresh: function() { | |||
@@ -13,8 +13,8 @@ frappe.ui.TagEditor = Class.extend({ | |||
*/ | |||
$.extend(this, opts); | |||
var me = this; | |||
this.$w = $('<div class="tag-line">').appendTo(this.parent) | |||
this.$tags = $('<ul>').prependTo(this.$w); | |||
this.wrapper = $('<div class="tag-line">').appendTo(this.parent) | |||
this.$tags = $('<ul>').prependTo(this.wrapper); | |||
this.$tags.tagit({ | |||
animate: false, | |||
allowSpaces: true, | |||
@@ -59,7 +59,7 @@ frappe.ui.TagEditor = Class.extend({ | |||
}, | |||
setup_autocomplete: function() { | |||
var me = this; | |||
this.$w.find("input").autocomplete({ | |||
this.wrapper.find("input").autocomplete({ | |||
minLength: 0, | |||
minChars: 0, | |||
source: function(request, response) { | |||
@@ -8,10 +8,10 @@ frappe.ui.Tree = Class.extend({ | |||
init: function(args) { | |||
$.extend(this, args); | |||
this.nodes = {}; | |||
this.$w = $('<div class="tree">').appendTo(this.parent); | |||
this.wrapper = $('<div class="tree">').appendTo(this.parent); | |||
this.rootnode = new frappe.ui.TreeNode({ | |||
tree: this, | |||
parent: this.$w, | |||
parent: this.wrapper, | |||
label: this.label, | |||
parent_label: null, | |||
expandable: true, | |||
@@ -53,7 +53,7 @@ frappe.ui.TreeNode = Class.extend({ | |||
this.$a = $('<span class="tree-link">') | |||
.click(function(event) { | |||
me.tree.selected_node = me; | |||
me.tree.$w.find(".tree-link.active").removeClass("active"); | |||
me.tree.wrapper.find(".tree-link.active").removeClass("active"); | |||
me.$a.addClass("active"); | |||
if(me.tree.toolbar) { | |||
me.show_toolbar(); | |||
@@ -188,7 +188,7 @@ frappe.ui.TreeNode = Class.extend({ | |||
} | |||
// select this link | |||
this.tree.$w.find('.selected') | |||
this.tree.wrapper.find('.selected') | |||
.removeClass('selected'); | |||
this.$a.toggleClass('selected'); | |||
this.expanded = !this.expanded; | |||
@@ -0,0 +1,864 @@ | |||
/* | |||
Opts: | |||
parent_selector: [reqd] | |||
label_width: default 200 | |||
step: 24 // no of hours | |||
column_width: 15 // pixels | |||
date_format: 'YYYY-MM-DD' | |||
bar.height: 26 | |||
bar.gap: 24 | |||
arrow.curve: 15 | |||
*/ | |||
var Gantt = Class.extend({ | |||
init: function(opts) { | |||
this.opts = opts; | |||
this.events = this.opts.events; | |||
this.tasks = []; | |||
this._bars = []; | |||
this.set_defaults(); | |||
this.groups = {}; | |||
this.make(); | |||
}, | |||
set_defaults: function() { | |||
var defaults = { | |||
label_width: 40, | |||
header_height: 50, | |||
column_width: 30, | |||
step: 24, | |||
valid_view_modes: [ | |||
"Quarter Day", | |||
"Half Day", | |||
"Day", | |||
"Week", | |||
"Month" | |||
], | |||
view_mode: 'Day', | |||
padding: 18, | |||
date_format: 'YYYY-MM-DD' | |||
}; | |||
for(var key in defaults) { | |||
if(defaults.hasOwnProperty(key)) { | |||
if(!this.opts[key]) this.opts[key] = defaults[key]; | |||
} | |||
} | |||
}, | |||
make: function() { | |||
this.canvas = Snap(this.opts.parent_selector); | |||
this.canvas.addClass("gantt"); | |||
this.prepare_filters(); | |||
this.set_scale(this.opts.view_mode); | |||
}, | |||
render: function() { | |||
this.clear(); | |||
this.setup_groups(); | |||
this.make_grid(); | |||
this.make_dates(); | |||
this.make_arrows(); | |||
// this.make_label(); | |||
this.make_bars(); | |||
this.setup_events(); | |||
this.set_width(); | |||
this.set_scroll_position(); | |||
this.bind(); | |||
}, | |||
bind: function() { | |||
this.bind_grid_click(); | |||
}, | |||
prepare_filters: function () { | |||
this.filters = {}; | |||
}, | |||
clear: function () { | |||
this.canvas.clear(); | |||
}, | |||
prepare_dates: function() { | |||
var me = this; | |||
this.tasks.forEach(function(task) { | |||
// momentify | |||
task._start = moment(task.start, me.opts.date_format); | |||
task._end = moment(task.end, me.opts.date_format); | |||
// set global start and end date | |||
if(!me.start || task._start < me.start) { | |||
me.start = task._start; | |||
} | |||
if(!me.end || task._end > me.end) { | |||
me.end = task._end; | |||
} | |||
}); | |||
if(me.view_mode === 'Quarter Day' || me.view_mode === 'Half Day') { | |||
me.start = me.start.clone().subtract(1, 'day'); | |||
me.end = me.end.clone().add(1, 'day'); | |||
} else if(me.view_mode === 'Month') { | |||
me.start = me.start.clone().startOf('year'); | |||
me.end = me.end.clone().endOf('month').add(1, 'year'); | |||
} else { | |||
me.start = me.start.clone().startOf('month'); | |||
me.end = me.end.clone().endOf('month'); | |||
} | |||
this.setup_dates(); | |||
}, | |||
setup_dates: function() { | |||
this.dates = []; | |||
var cur_date = null; | |||
while(cur_date === null || cur_date < this.end) { | |||
if(!cur_date) { | |||
cur_date = this.start.clone(); | |||
} else { | |||
cur_date = (this.view_mode === 'Month') ? | |||
cur_date = cur_date.clone().add(1, 'month') : | |||
cur_date.clone().add(this.opts.step, 'hours'); | |||
} | |||
this.dates.push(cur_date); | |||
} | |||
}, | |||
set_view_mode: function(mode) { | |||
this.set_scale(mode); | |||
this.start = this.end = undefined; | |||
this.prepare_dates(); | |||
this.render(); | |||
}, | |||
set_scale: function (scale) { | |||
this.view_mode = scale; | |||
this.events.on_viewmode_change(scale); | |||
if(scale === 'Day') { | |||
this.opts.step = 24; | |||
this.opts.column_width = 38; | |||
} | |||
else if(scale === 'Half Day') { | |||
this.opts.step = 24 / 2; | |||
this.opts.column_width = 38; | |||
} | |||
else if(scale === 'Quarter Day') { | |||
this.opts.step = 24 / 4; | |||
this.opts.column_width = 38; | |||
} | |||
else if(scale === 'Week') { | |||
this.opts.step = 24 * 7; | |||
this.opts.column_width = 140; | |||
} | |||
else if(scale === 'Month') { | |||
this.opts.step = 24 * 30; | |||
this.opts.column_width = 120; | |||
} | |||
}, | |||
add_task: function(task) { | |||
task._index = this.tasks.length; | |||
this.tasks.push(task); | |||
this.prepare_dates(); | |||
}, | |||
setup_groups: function() { | |||
var me = this; | |||
// make groups | |||
["grid", "controls", "label", "date", | |||
"arrow", "progress", "bar", "details"].forEach(function(name) { | |||
me.groups[name] = me.canvas.group().attr({'id': name}); | |||
}); | |||
}, | |||
set_width: function () { | |||
var cur_width = this.canvas.node.getBoundingClientRect().width; | |||
var actual_width = this.canvas.getBBox().width; | |||
if(cur_width < actual_width) | |||
this.canvas.attr("width", actual_width); | |||
}, | |||
set_scroll_position: function() { | |||
document.querySelector(this.opts.parent_selector).parentElement.scrollLeft = | |||
this.get_min_date().diff(this.start, 'hours') | |||
/ this.opts.step * this.opts.column_width; | |||
}, | |||
get_min_date: function() { | |||
return this.tasks.reduce(function(acc, curr) { | |||
return curr._start.isSameOrBefore(acc._start) ? curr : acc; | |||
})._start | |||
}, | |||
make_grid: function () { | |||
this.make_grid_background(); | |||
this.make_grid_rows(); | |||
this.make_grid_header(); | |||
this.make_grid_ticks(); | |||
}, | |||
make_grid_background: function () { | |||
var me = this; | |||
var grid_width = this.opts.label_width + this.dates.length * this.opts.column_width, | |||
grid_height = this.opts.header_height + this.opts.padding | |||
+ (this.opts.bar.height + this.opts.padding) * this.tasks.length; | |||
this.canvas.rect(0,0, grid_width, grid_height) | |||
.addClass('grid-background') | |||
.appendTo(this.groups.grid); | |||
this.canvas.attr({ | |||
// viewBox: "0 0 " + (x+10) + " " + (y+10), | |||
height: grid_height + me.opts.padding, | |||
width: "100%" | |||
}); | |||
}, | |||
make_grid_header: function () { | |||
var me = this; | |||
var header_width = this.opts.label_width + this.dates.length * this.opts.column_width, | |||
header_height = this.opts.header_height + 10; | |||
me.canvas.rect(0,0, header_width, header_height) | |||
.addClass('grid-header') | |||
.appendTo(me.groups.grid); | |||
}, | |||
make_grid_rows: function () { | |||
var | |||
me = this, | |||
rows = me.canvas.group() | |||
.appendTo(me.groups.grid), | |||
lines = me.canvas.group() | |||
.appendTo(me.groups.grid), | |||
row_width = me.opts.label_width + me.dates.length * me.opts.column_width, | |||
row_height = me.opts.bar.height + me.opts.padding, | |||
row_y = me.opts.header_height + me.opts.padding/2; | |||
this.tasks.forEach(function (task, i) { | |||
var row_class = i % 2 ? "row-odd" : "row-even"; | |||
me.canvas.rect(0, row_y, row_width, row_height) | |||
.addClass(row_class) | |||
.appendTo(rows); | |||
me.canvas.line(0, row_y + row_height, row_width, row_y + row_height) | |||
.addClass('row-line') | |||
.appendTo(lines); | |||
row_y += me.opts.bar.height + me.opts.padding; | |||
}); | |||
}, | |||
make_grid_ticks: function () { | |||
var me = this; | |||
var tick_x = me.opts.label_width; | |||
var tick_y = me.opts.header_height + me.opts.padding/2; | |||
var tick_height = (me.opts.bar.height + me.opts.padding) * me.tasks.length; | |||
this.dates.forEach(function(date) { | |||
var tick_class = 'tick'; | |||
//thick tick for monday | |||
if(me.view_mode === 'Day' && date.day() === 1) { | |||
tick_class += ' thick'; | |||
} | |||
//thick tick for first week | |||
if(me.view_mode === 'Week' && date.date() >= 1 && date.date() < 8) { | |||
tick_class += ' thick'; | |||
} | |||
//thick ticks for quarters | |||
if(me.view_mode === 'Month' && date.month() % 3 == 0) { | |||
tick_class += ' thick'; | |||
} | |||
me.canvas.path(Snap.format("M {x} {y} v {height}", { | |||
x: tick_x, | |||
y: tick_y, | |||
height: tick_height | |||
})) | |||
.addClass(tick_class) | |||
.appendTo(me.groups.grid); | |||
if(me.view_mode === 'Month') { | |||
tick_x += date.daysInMonth() * me.opts.column_width/30; | |||
} else { | |||
tick_x += me.opts.column_width; | |||
} | |||
}); | |||
}, | |||
make_dates: function() { | |||
var me = this; | |||
this.dates.forEach(function(date, i) { | |||
var primary_text = ''; | |||
var secondary_text = ''; | |||
if(i===0) { | |||
primary_text = me.get_date_text(date, "primary"); | |||
secondary_text = me.get_date_text(date); | |||
} else { | |||
if(me.view_mode === 'Day') { | |||
primary_text = date.date() !== me.dates[i-1].date() ? | |||
me.get_date_text(date, "primary") : ""; | |||
secondary_text = date.month() !== me.dates[i-1].month() ? | |||
me.get_date_text(date) : ""; | |||
} | |||
else if(me.view_mode === 'Quarter Day') { | |||
primary_text = me.get_date_text(date, "primary"); | |||
secondary_text = date.date() !== me.dates[i-1].date() ? | |||
me.get_date_text(date) : ""; | |||
} | |||
else if(me.view_mode === 'Half Day') { | |||
primary_text = me.get_date_text(date, "primary"); | |||
secondary_text = date.date() !== me.dates[i-1].date() ? | |||
me.get_date_text(date) : ""; | |||
} | |||
else if(me.view_mode === 'Week') { | |||
primary_text = me.get_date_text(date, "primary"); | |||
secondary_text = date.month() !== me.dates[i-1].month() ? | |||
me.get_date_text(date) : ""; | |||
} | |||
else if(me.view_mode === 'Month') { | |||
primary_text = me.get_date_text(date, "primary"); | |||
secondary_text = date.year() !== me.dates[i-1].year() ? | |||
me.get_date_text(date) : ""; | |||
} | |||
} | |||
var primary_text_x = me.opts.label_width + (i * me.opts.column_width), | |||
primary_text_y = me.opts.header_height, | |||
secondary_text_x = me.opts.label_width + (i * me.opts.column_width), | |||
secondary_text_y = me.opts.header_height - 25; | |||
if(me.view_mode === 'Month') { | |||
primary_text_x += me.opts.column_width/2; | |||
secondary_text_x += (me.opts.column_width * 12)/2; | |||
} | |||
if(me.view_mode === 'Week') { | |||
primary_text_x += me.opts.column_width/2; | |||
secondary_text_x += (me.opts.column_width * 4)/2; | |||
} | |||
if(me.view_mode === 'Day') { | |||
secondary_text_x += (me.opts.column_width * 30)/2; | |||
} | |||
if(me.view_mode === 'Quarter Day') { | |||
secondary_text_x += (me.opts.column_width * 4)/2; | |||
} | |||
if(me.view_mode === 'Half Day') { | |||
secondary_text_x += (me.opts.column_width * 2)/2; | |||
} | |||
me.canvas.text(primary_text_x, primary_text_y, primary_text) | |||
.addClass('primary-text') | |||
.appendTo(me.groups.date) | |||
if(secondary_text) { | |||
var $secondary_text = me.canvas.text(secondary_text_x, secondary_text_y, secondary_text) | |||
.addClass('secondary-text') | |||
.appendTo(me.groups.date) | |||
if($secondary_text.getBBox().x2 > me.groups.grid.getBBox().width) { | |||
$secondary_text.remove(); | |||
} | |||
} | |||
}); | |||
}, | |||
get_date_text: function(date, primary) { | |||
var scale = this.view_mode; | |||
var text = ""; | |||
if(scale === 'Day') { | |||
text = (primary) ? date.format('D') : date.format('MMMM'); | |||
} | |||
else if(scale === 'Quarter Day' || scale === 'Half Day') { | |||
text = (primary) ? date.format('HH') : date.format('D MMM'); | |||
} | |||
else if(scale === 'Week') { | |||
text = (primary) ? "Week " + date.format('W') : date.format('MMMM'); | |||
} | |||
else if(scale === 'Month') { | |||
text = (primary) ? date.format('MMMM') : date.format('YYYY'); | |||
} | |||
return text; | |||
}, | |||
make_arrows: function () { | |||
var me = this; | |||
this.tasks.forEach(function (task) { | |||
if(task.dependent) { | |||
var dependents = task.dependent.split(','); | |||
dependents.forEach(function (task_dependent) { | |||
task_dependent = task_dependent.trim(); | |||
var dependent = me.get_task(task_dependent); | |||
var start_x = dependent._start.diff(me.start, 'hours')/me.opts.step | |||
* me.opts.column_width + me.opts.label_width | |||
+ (dependent._end.diff(dependent._start, 'hours')/me.opts.step | |||
* me.opts.column_width) / 2; | |||
var start_y = me.opts.header_height + me.opts.bar.height | |||
+ (me.opts.padding + me.opts.bar.height) * dependent._index; | |||
var end_x = task._start.diff(me.start, 'hours')/me.opts.step | |||
* me.opts.column_width + me.opts.label_width; | |||
var end_y = me.opts.header_height + me.opts.bar.height/2 | |||
+ (me.opts.padding + me.opts.bar.height) * task._index; | |||
var path = Snap.format("M {start_x} {start_y} V {offset} a {curve} {curve} " + | |||
"0 0 0 {curve} {curve}" + | |||
"L {end_x} {end_y} m -5 -5 l 5 5 l -5 5", | |||
{ | |||
start_x: start_x, | |||
start_y: start_y + me.opts.padding, | |||
end_x: end_x - me.opts.padding, | |||
end_y: end_y + me.opts.padding, | |||
offset: end_y - me.opts.arrow.curve + me.opts.padding, | |||
curve: me.opts.arrow.curve | |||
}); | |||
me.groups.arrow.add(me.canvas.path(path)); | |||
}); | |||
} | |||
}); | |||
}, | |||
get_task: function (name) { | |||
var result = null; | |||
this.tasks.forEach(function (task) { | |||
if (task.name === name){ | |||
result = task; | |||
} | |||
}); | |||
return result; | |||
}, | |||
make_label: function () { | |||
var me = this; | |||
var label_x = me.opts.label_width - me.opts.padding, | |||
label_y = me.opts.header_height + me.opts.bar.height/2 + me.opts.padding; | |||
this.tasks.forEach(function (task) { | |||
me.canvas.text(label_x, label_y, task.name).appendTo(me.groups.label); | |||
label_y += me.opts.bar.height + me.opts.padding; | |||
}); | |||
me.groups.label.attr({ | |||
"text-anchor": "end", | |||
"dominant-baseline": "central" | |||
}); | |||
}, | |||
make_bars: function () { | |||
var me = this; | |||
var bar_position_x, | |||
bar_position_y = this.opts.header_height + me.opts.padding; | |||
this.tasks.forEach(function (task, i) { | |||
var bar = new Bar({ | |||
canvas: me.canvas, | |||
task: task, | |||
details: me.groups.details, | |||
gantt: { | |||
offset: me.opts.label_width, | |||
unit_width: me.opts.column_width, | |||
step: me.opts.step, | |||
start: me.start, | |||
header_height: me.opts.header_height, | |||
padding: me.opts.padding, | |||
view_mode: me.view_mode | |||
}, | |||
color: { | |||
bar: me.opts.bar.color, | |||
progress: me.opts.bar.progress_color, | |||
hover_bar: me.opts.bar.hover_color, | |||
hover_progress: me.opts.bar.hover_progress_color | |||
} | |||
}); | |||
me._bars.push(bar); | |||
me.groups.bar.add(bar.group); | |||
}); | |||
}, | |||
setup_events: function() { | |||
var me = this; | |||
this._bars.forEach(function(bar) { | |||
bar.events.on_date_change = me.events.bar_on_datechange; | |||
bar.click(me.events.bar_on_click); | |||
}); | |||
}, | |||
bind_grid_click: function() { | |||
var me = this; | |||
this.groups.grid.click(function() { | |||
me.canvas.selectAll('.bar-wrapper').forEach(function(el) { | |||
el.removeClass('active'); | |||
}); | |||
}) | |||
} | |||
}); | |||
/* | |||
Class: Bar | |||
Opts: | |||
canvas [reqd] | |||
task [reqd] | |||
unit_width [reqd] | |||
x | |||
y | |||
*/ | |||
var Bar = Class.extend({ | |||
init: function (opts) { | |||
for(var key in opts) { | |||
if(opts.hasOwnProperty(key)) | |||
this[key] = opts[key]; | |||
} | |||
this.set_defaults(); | |||
this.prepare(); | |||
this.draw(); | |||
this.bind(); | |||
this.action_completed = false; | |||
}, | |||
set_defaults: function () { | |||
var defaults = { | |||
height: 20, | |||
corner_radius: 3, | |||
color: { | |||
bar: "#a3a3ff", | |||
progress: "#7575ff", | |||
hover_bar: "#7575ff", | |||
hover_progress: "#4d4da8" | |||
}, | |||
events: {} | |||
}; | |||
for(var key in defaults) { | |||
if(defaults.hasOwnProperty(key)) | |||
if(!this[key]) this[key] = defaults[key]; | |||
} | |||
}, | |||
prepare: function () { | |||
this.prepare_values(); | |||
this.prepare_plugins(); | |||
}, | |||
prepare_values: function() { | |||
this.x = this.compute_x(); | |||
this.y = this.compute_y(); | |||
this.duration = this.task._end.diff(this.task._start, 'hours')/this.gantt.step; | |||
this.width = this.gantt.unit_width * this.duration; | |||
if(this.gantt.view_mode === 'Month') | |||
this.width = (this.gantt.unit_width/30) * (this.duration*this.gantt.step/24); | |||
this.progress_width = this.gantt.unit_width * this.duration * (this.task.progress/100) || 0; | |||
this.group = this.canvas.group().addClass('bar-wrapper'); | |||
this.bar_group = this.canvas.group().addClass('bar-group').appendTo(this.group); | |||
this.handle_group = this.canvas.group().addClass('handle-group').appendTo(this.group); | |||
}, | |||
prepare_plugins: function() { | |||
var me = this; | |||
this.filters = {}; | |||
Snap.plugin(function (Snap, Element, Paper, global, Fragment) { | |||
Element.prototype.get = function (attr) { | |||
return +this.attr(attr); | |||
}; | |||
Element.prototype.getX = function () { | |||
return this.get("x"); | |||
}; | |||
Element.prototype.getY = function () { | |||
return this.get("y"); | |||
}; | |||
Element.prototype.getWidth = function () { | |||
return this.get("width"); | |||
}; | |||
Element.prototype.setStartDate = function(date) { | |||
date = moment(date) | |||
var x = me.gantt.offset + (date.diff(me.gantt.start, 'hours')/me.gantt.step)*me.gantt.unit_width; | |||
return this.attr('x', x); | |||
} | |||
Element.prototype.setEndDate = function(date) { | |||
date = moment(date) | |||
var x = me.gantt.offset + (date.diff(me.gantt.start, 'hours')/me.gantt.step)*me.gantt.unit_width; | |||
return this.attr('x', x); | |||
} | |||
}); | |||
}, | |||
draw: function () { | |||
this.draw_bar(); | |||
this.draw_progress_bar(); | |||
this.draw_label(); | |||
this.draw_resize_handles(); | |||
}, | |||
draw_bar: function() { | |||
this.canvas.rect(this.x, this.y, | |||
this.width, this.height, | |||
this.corner_radius, this.corner_radius) | |||
.addClass("bar") | |||
.appendTo(this.bar_group); | |||
}, | |||
draw_progress_bar: function() { | |||
this.canvas.rect(this.x, this.y, | |||
this.progress_width, this.height, | |||
this.corner_radius, this.corner_radius) | |||
.attr("fill", this.color.progress) | |||
.addClass("bar-progress") | |||
.appendTo(this.bar_group) | |||
}, | |||
draw_label: function() { | |||
this.canvas.text(this.x + this.width/2, | |||
this.y + this.height/2, | |||
this.task.name) | |||
.addClass("bar-label") | |||
.appendTo(this.bar_group); | |||
this.update_label_position(this); | |||
}, | |||
draw_resize_handles: function() { | |||
var bar = this.group.select('.bar'); | |||
this.canvas.rect(bar.getX() + bar.getWidth() - 9, bar.getY() + 1, | |||
8, this.height - 2, this.corner_radius, this.corner_radius) | |||
.addClass('handle right') | |||
.appendTo(this.handle_group); | |||
this.canvas.rect(bar.getX() + 1, bar.getY() + 1, | |||
8, this.height - 2, this.corner_radius, this.corner_radius) | |||
.addClass('handle left') | |||
.appendTo(this.handle_group); | |||
}, | |||
bind: function () { | |||
// this.show_details(); | |||
this.bind_resize(); | |||
this.bind_drag(); | |||
}, | |||
show_details: function () { | |||
var me = this; | |||
this.group.mouseover(function (e, x, y) { | |||
var details_box = me.canvas.group(); | |||
me.details.clear(); | |||
var pos = me.get_details_position(me.group); | |||
details_box.attr({ transform: "translate(" + pos.x +"," + pos.y + ")" }) | |||
.appendTo(me.details); | |||
var line1_text = me.task.name + ": " + | |||
me.task._start.format("MMM D") + " - " + | |||
me.task._end.format("MMM D"); | |||
var line1_el = me.canvas.text(0,0, line1_text).attr({ | |||
dx: 10, | |||
dy: 30, | |||
"fill": "#424242", | |||
"font-weight": 500, | |||
"font-size": 14 | |||
}); | |||
me.canvas.rect(0, 0, 0, 110, 2, 2).attr({ | |||
stroke: "#c1c1c1", | |||
"stroke-width": 1.1, | |||
fill: "#fff" | |||
}).appendTo(details_box); | |||
var bbox = line1_el.getBBox(); | |||
details_box.select('rect').attr({ | |||
width: bbox.width + 20 | |||
}); | |||
line1_el.appendTo(details_box); | |||
var line2_text = | |||
"Duration: " + me.task._end.diff(me.task._start, 'days') + " days"; | |||
me.canvas.text(0,0, line2_text).attr({ | |||
dx: 10, | |||
dy: 65, | |||
"fill": "#757575" | |||
}).appendTo(details_box); | |||
var line3_text = me.task.progress ? | |||
"Progress: " + me.task.progress + "%" : ""; | |||
me.canvas.text(0,0, line3_text).attr({ | |||
dx: 10, | |||
dy: 90, | |||
"fill": "#757575" | |||
}).appendTo(details_box); | |||
me.details.attr({ | |||
x: x, | |||
y: y, | |||
"font-size": 14 | |||
}); | |||
}); | |||
this.group.mouseout(function () { | |||
setTimeout(function () { | |||
me.details.clear(); | |||
}, 500); | |||
}); | |||
}, | |||
get_details_position: function (group) { | |||
var bar = group.select('rect'); | |||
return { | |||
x: bar.getX() + bar.getWidth() + 2, | |||
y: bar.getY() - 10 | |||
}; | |||
}, | |||
bind_resize: function() { | |||
var me = this; | |||
var bar = me.group.select('.bar'); | |||
var handle = me.get_handles(me); | |||
handle.right.drag(onmove_right, onstart, onstop_right); | |||
handle.left.drag(onmove_left, onstart, onstop_left); | |||
function onstart() { | |||
bar.ox = bar.getX(); | |||
bar.oy = bar.getY(); | |||
bar.owidth = bar.getWidth(); | |||
this.ox = this.getX(); | |||
this.oy = this.getY(); | |||
bar.finaldx = 0; | |||
} | |||
function onmove_right(dx, dy) { | |||
bar.finaldx = me.get_snap_position(me, bar, dx); | |||
me.update_bar_position(null, bar.owidth + bar.finaldx); | |||
} | |||
function onstop_right() { | |||
if(bar.finaldx) me.date_changed(); | |||
me.set_action_completed(); | |||
} | |||
function onmove_left(dx, dy) { | |||
bar.finaldx = me.get_snap_position(me, bar, dx); | |||
me.update_bar_position(bar.ox + bar.finaldx, bar.owidth - bar.finaldx); | |||
} | |||
function onstop_left() { | |||
if(bar.finaldx) me.date_changed(); | |||
me.set_action_completed(); | |||
} | |||
}, | |||
get_handles: function(me) { | |||
return { | |||
left: me.handle_group.select('.handle.left'), | |||
right: me.handle_group.select('.handle.right') | |||
} | |||
}, | |||
bind_drag: function() { | |||
var me = this; | |||
var bar = me.group.select('.bar'); | |||
me.bar_group.drag(onmove, onstart, onstop); | |||
function onmove(dx, dy) { | |||
bar.finaldx = me.get_snap_position(me, bar, dx); | |||
me.update_bar_position(bar.ox + bar.finaldx); | |||
} | |||
function onstop() { | |||
if(!bar.finaldx) return; | |||
me.date_changed(); | |||
me.set_action_completed(); | |||
} | |||
function onstart() { | |||
bar.ox = bar.getX(); | |||
bar.finaldx = 0; | |||
} | |||
}, | |||
view_is: function(modes) { | |||
var me = this; | |||
if (typeof modes === 'string') { | |||
return me.gantt.view_mode === modes; | |||
} else { | |||
for (var i = 0; i < modes.length; i++) { | |||
if(me.gantt.view_mode === modes[i]) return true; | |||
} | |||
// modes.forEach(function(mode) { | |||
// if(me.gantt.view_mode === mode) return true; | |||
// }) | |||
return false; | |||
} | |||
}, | |||
update_bar_position: function(x, width) { | |||
var bar = this.group.select('.bar'); | |||
if(x) this.update_attr(bar, "x", x); | |||
if(width) this.update_attr(bar, "width", width); | |||
this.update_label_position(this); | |||
this.update_handle_position(this); | |||
this.update_progressbar_position(this); | |||
}, | |||
click: function(callback) { | |||
var me = this; | |||
this.group.click(function() { | |||
if(me.action_completed) { | |||
// just finished a move action, wait for a few seconds | |||
return; | |||
} | |||
if(me.group.hasClass('active')) { | |||
callback(me.task); | |||
} | |||
me.unselect_all(); | |||
me.group.toggleClass('active'); | |||
}); | |||
}, | |||
date_changed: function() { | |||
if(this.events.on_date_change) { | |||
this.events.on_date_change( | |||
this.task, | |||
this.compute_start_date(), | |||
this.compute_end_date() | |||
); | |||
} | |||
}, | |||
set_action_completed: function() { | |||
var me = this; | |||
this.action_completed = true; | |||
setTimeout(function() { me.action_completed = false; }, 2000); | |||
}, | |||
compute_date: function(x) { | |||
var pos = x - this.gantt.offset; | |||
var shift = (x - this.compute_x())/this.gantt.unit_width; | |||
var date = this.task._start.clone().add(this.gantt.step*shift, 'hours'); | |||
return date; | |||
}, | |||
compute_start_date: function() { | |||
var bar = this.group.select(".bar"), | |||
shift = (bar.getX() - this.compute_x()) / this.gantt.unit_width, | |||
new_start_date = this.task._start.clone().add(this.gantt.step*shift, 'hours'); | |||
return new_start_date; | |||
}, | |||
compute_end_date: function() { | |||
var bar = this.group.select(".bar"), | |||
og_x = this.compute_x() + this.duration * this.gantt.unit_width, | |||
final_x = bar.getX() + bar.getWidth(), | |||
shift = (final_x - og_x) / this.gantt.unit_width, | |||
new_end_date = this.task._end.clone().add(this.gantt.step*shift, 'hours'); | |||
return new_end_date; | |||
}, | |||
compute_x: function() { | |||
var x = this.gantt.offset | |||
+ (this.task._start.diff(this.gantt.start, 'hours')/this.gantt.step | |||
* this.gantt.unit_width); | |||
if(this.gantt.view_mode === 'Month') { | |||
x = this.gantt.offset | |||
+ this.task._start.diff(this.gantt.start, 'days') * this.gantt.unit_width/30 | |||
} | |||
return x; | |||
}, | |||
compute_y: function() { | |||
return this.gantt.header_height + this.gantt.padding | |||
+ this.task._index * (this.height + this.gantt.padding) | |||
}, | |||
get_snap_position: function(me, bar, dx) { | |||
var odx = dx, rem, position, scale; | |||
if (me.gantt.view_mode === 'Week') { | |||
rem = dx % (me.gantt.unit_width/7); | |||
position = odx - rem + | |||
((rem < me.gantt.unit_width/7) ? 0 : me.gantt.unit_width/7); | |||
} else if (me.gantt.view_mode === 'Month') { | |||
rem = dx % (me.gantt.unit_width/30); | |||
position = odx - rem + | |||
((rem < me.gantt.unit_width/30) ? 0 : me.gantt.unit_width/30); | |||
} else { | |||
rem = dx % me.gantt.unit_width; | |||
position = odx - rem + | |||
((rem < me.gantt.unit_width) ? 0 : me.gantt.unit_width); | |||
} | |||
return position; | |||
}, | |||
update_attr: function(element, attr, value) { | |||
value = +value; | |||
if(!isNaN(value)) { | |||
element.attr(attr, value); | |||
} | |||
return element; | |||
}, | |||
update_progressbar_position: function(me) { | |||
var bar = me.group.select('.bar'); | |||
var bar_progress = me.group.select('.bar-progress'); | |||
bar_progress.attr('x', bar.getX()); | |||
bar_progress.attr('width', bar.getWidth() * (me.task.progress/100)); | |||
}, | |||
update_label_position: function(me) { | |||
var bar = me.group.select(".bar"); | |||
var label = me.group.select('.bar-label'); | |||
if(label.getBBox().width > bar.getWidth()){ | |||
label.addClass('big').attr('x', bar.getX() + bar.getWidth() + 5); | |||
} else { | |||
label.removeClass('big').attr('x', bar.getX() + bar.getWidth()/2); | |||
} | |||
}, | |||
update_handle_position: function(me) { | |||
var bar = me.group.select(".bar"); | |||
me.handle_group.select(".handle.left").attr({ | |||
"x": bar.getX() + 1, | |||
}); | |||
me.handle_group.select(".handle.right").attr({ | |||
"x": bar.getX() + bar.getWidth() - 9, | |||
}); | |||
}, | |||
unselect_all: function() { | |||
this.canvas.selectAll('.bar-wrapper').forEach(function(el) { | |||
el.removeClass('active'); | |||
}); | |||
} | |||
}); |
@@ -351,7 +351,7 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ | |||
this.dataView = new Slick.Data.DataView(); | |||
this.set_data(this.data); | |||
var grid_wrapper = this.$w.find('.result-list').addClass("slick-wrapper"); | |||
var grid_wrapper = this.wrapper.find('.result-list').addClass("slick-wrapper"); | |||
// set height if not auto | |||
if(!options.autoHeight) | |||
@@ -504,13 +504,13 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ | |||
set_tag_and_status_filter: function() { | |||
var me = this; | |||
this.$w.find('.result-list').on("click", ".label-info", function() { | |||
this.wrapper.find('.result-list').on("click", ".label-info", function() { | |||
if($(this).attr("data-label")) { | |||
me.set_filter("_user_tags", $(this).attr("data-label")); | |||
me.refresh(); | |||
} | |||
}); | |||
this.$w.find('.result-list').on("click", "[data-workflow-state]", function() { | |||
this.wrapper.find('.result-list').on("click", "[data-workflow-state]", function() { | |||
if($(this).attr("data-workflow-state")) { | |||
me.set_filter(me.state_fieldname, | |||
$(this).attr("data-workflow-state")); | |||
@@ -1,23 +0,0 @@ | |||
[Demo and Documentation](http://taitems.github.com/jQuery.Gantt/) | |||
============== | |||
jQuery Gantt Chart is a simple chart that implements gantt functionality as | |||
a jQuery component. | |||
It's able to: | |||
- Read json data | |||
- Paging results | |||
- Display different colours for each task | |||
- Display short description as hints | |||
- Mark holidays | |||
Plugin was tested and should work on: | |||
- Firefox 4+ | |||
- Chrome 13+ | |||
- Safari 5+ | |||
- Opera 9+ | |||
- IE 8+ | |||
Distributed under an MIT license. |
@@ -1,428 +0,0 @@ | |||
.gantt, .gantt2 { | |||
width: 100%; | |||
margin: 20px auto; | |||
border: 14px solid #ddd; | |||
position: relative; | |||
-webkit-border-radius: 6px; | |||
-moz-border-radius: 6px; | |||
border-radius: 6px; | |||
-webkit-box-sizing: border-box; | |||
-moz-box-sizing: border-box; | |||
box-sizing: border-box; | |||
} | |||
.gantt:after { | |||
content: "."; | |||
visibility: hidden; | |||
display: block; | |||
height: 0; | |||
clear: both; | |||
} | |||
.fn-gantt { | |||
width: 100%; | |||
} | |||
.fn-gantt .fn-content { | |||
overflow: hidden; | |||
position: relative; | |||
width: 100%; | |||
} | |||
/* === LEFT PANEL === */ | |||
.fn-gantt .leftPanel { | |||
float: left; | |||
width: 225px; | |||
overflow: hidden; | |||
border-right: 1px solid #DDD; | |||
position: relative; | |||
z-index: 20; | |||
} | |||
.fn-gantt .row { | |||
float: left; | |||
height: 24px; | |||
line-height: 24px; | |||
margin-left: -1px; | |||
} | |||
.fn-gantt .leftPanel .fn-label { | |||
display: inline-block; | |||
margin: 0 0 0 5px; | |||
color: #484A4D; | |||
width: 110px; | |||
white-space: nowrap; | |||
text-overflow: ellipsis; | |||
overflow: hidden; | |||
} | |||
.fn-gantt .leftPanel .row0 { | |||
border-top: 1px solid #DDD; | |||
} | |||
.fn-gantt .leftPanel .name, .fn-gantt .leftPanel .desc { | |||
float: left; | |||
height: 23px; | |||
margin: 0; | |||
border-bottom: 1px solid #DDD; | |||
background-color: #f6f6f6; | |||
} | |||
.fn-gantt .leftPanel .name { | |||
width: 110px; | |||
font-weight: bold; | |||
} | |||
.fn-gantt .leftPanel .desc { | |||
width: 115px; | |||
} | |||
.fn-gantt .leftPanel .fn-wide, .fn-gantt .leftPanel .fn-wide .fn-label { | |||
width: 225px; | |||
} | |||
.fn-gantt .spacer { | |||
margin: -2px 0 1px 0; | |||
border-bottom: none; | |||
background-color: #f6f6f6; | |||
} | |||
/* === RIGHT PANEL === */ | |||
.fn-gantt .rightPanel { | |||
overflow: hidden; | |||
} | |||
.fn-gantt .dataPanel { | |||
margin-left: 0px; | |||
border-right: 1px solid #DDD; | |||
background-image: url(/assets/frappe/js/lib/jQuery.Gantt/img/grid.png); | |||
background-repeat: repeat; | |||
background-position: 24px 24px; | |||
position: relative; | |||
} | |||
.fn-gantt .day, .fn-gantt .date { | |||
overflow: visible; | |||
width: 24px; | |||
line-height: 24px; | |||
text-align: center; | |||
border-left: 1px solid #DDD; | |||
border-bottom: 1px solid #DDD; | |||
margin: -1px 0 0 -1px; | |||
font-size: 11px; | |||
color: #484a4d; | |||
text-shadow: 0 1px 0 rgba(255,255,255,0.75); | |||
text-align: center; | |||
} | |||
.fn-gantt .holiday { | |||
background-color: #ffd263; | |||
height: 23px; | |||
margin: 0 0 -1px -1px; | |||
} | |||
.fn-gantt .today { | |||
background-color: #fff8da; | |||
height: 23px; | |||
margin: 0 0 -1px -1px; | |||
font-weight: bold; | |||
text-align: center; | |||
} | |||
.fn-gantt .sa, .fn-gantt .sn, .fn-gantt .wd { | |||
height: 23px; | |||
margin: 0 0 0 -1px; | |||
text-align: center; | |||
} | |||
.fn-gantt .sa, .fn-gantt .sn { | |||
color: #939496; | |||
background-color: #f5f5f5; | |||
text-align: center; | |||
} | |||
.fn-gantt .wd { | |||
background-color: #f6f6f6; | |||
text-align: center; | |||
} | |||
.fn-gantt .rightPanel .month, .fn-gantt .rightPanel .year { | |||
float: left; | |||
overflow: hidden; | |||
border-left: 1px solid #DDD; | |||
border-bottom: 1px solid #DDD; | |||
height: 23px; | |||
margin: 0 0 0 -1px; | |||
background-color: #f6f6f6; | |||
font-weight: bold; | |||
font-size: 11px; | |||
color: #484a4d; | |||
text-shadow: 0 1px 0 rgba(255,255,255,0.75); | |||
text-align: center; | |||
} | |||
.fn-gantt-hint { | |||
border: 5px solid #edc332; | |||
background-color: #fff5d4; | |||
padding: 10px; | |||
position: absolute; | |||
display: none; | |||
z-index: 11; | |||
-webkit-border-radius: 4px; | |||
-moz-border-radius: 4px; | |||
border-radius: 4px; | |||
} | |||
.fn-gantt .bar { | |||
background-color: #D0E4FD; | |||
height: 18px; | |||
margin: 0px 3px 3px 0px; | |||
position: absolute; | |||
z-index: 10; | |||
text-align: center; | |||
-webkit-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset; | |||
-moz-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset; | |||
box-shadow: 0 0 1px rgba(0,0,0,0.25) inset; | |||
-webkit-border-radius: 3px; | |||
-moz-border-radius: 3px; | |||
border-radius: 3px; | |||
} | |||
.fn-gantt .bar .fn-label { | |||
line-height: 18px; | |||
font-weight: bold; | |||
white-space: nowrap; | |||
width: 100%; | |||
text-overflow: ellipsis; | |||
overflow: hidden; | |||
text-shadow: 0 1px 0 rgba(255,255,255,0.4); | |||
color: #414B57 !important; | |||
text-align: center; | |||
font-size: 11px; | |||
} | |||
.fn-gantt .ganttRed { | |||
background-color: #F9C4E1; | |||
} | |||
.fn-gantt .ganttRed .fn-label { | |||
color: #78436D !important; | |||
} | |||
.fn-gantt .ganttGreen { | |||
background-color: #D8EDA3; | |||
} | |||
.fn-gantt .ganttGreen .fn-label { | |||
color: #778461 !important; | |||
} | |||
.fn-gantt .ganttOrange { | |||
background-color: #FCD29A; | |||
} | |||
.fn-gantt .ganttOrange .fn-label { | |||
color: #714715 !important; | |||
} | |||
/* === BOTTOM NAVIGATION === */ | |||
.fn-gantt .bottom { | |||
clear: both; | |||
background-color: #f6f6f6; | |||
width: 100%; | |||
} | |||
.fn-gantt .navigate { | |||
border-top: 1px solid #DDD; | |||
padding: 10px 0 10px 225px; | |||
} | |||
.fn-gantt .navigate .nav-slider { | |||
height: 20px; | |||
display: inline-block; | |||
} | |||
.fn-gantt .navigate .nav-slider-left, .fn-gantt .navigate .nav-slider-right { | |||
text-align: center; | |||
height: 20px; | |||
display: inline-block; | |||
} | |||
.fn-gantt .navigate .nav-slider-left { | |||
float: left; | |||
} | |||
.fn-gantt .navigate .nav-slider-right { | |||
float: right; | |||
} | |||
.fn-gantt .navigate .nav-slider-content { | |||
text-align: left; | |||
width: 160px; | |||
height: 20px; | |||
display: inline-block; | |||
margin: 0 10px; | |||
} | |||
.fn-gantt .navigate .nav-slider-bar, .fn-gantt .navigate .nav-slider-button { | |||
position: absolute; | |||
display: block; | |||
} | |||
.fn-gantt .navigate .nav-slider-bar { | |||
width: 155px; | |||
height: 6px; | |||
background-color: #838688; | |||
margin: 8px 0 0 0; | |||
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; | |||
-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; | |||
box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; | |||
-webkit-border-radius: 3px; | |||
-moz-border-radius: 3px; | |||
border-radius: 3px; | |||
} | |||
.fn-gantt .navigate .nav-slider-button { | |||
width: 17px; | |||
height: 60px; | |||
background: url(/assets/frappe/js/lib/jQuery.Gantt/img/slider_handle.png) center center no-repeat; | |||
left: 0px; | |||
top: 0px; | |||
margin: -26px 0 0 0; | |||
cursor: pointer; | |||
} | |||
.fn-gantt .navigate .page-number { | |||
display: inline-block; | |||
font-size: 10px; | |||
height: 20px; | |||
} | |||
.fn-gantt .navigate .page-number span { | |||
color: #666666; | |||
margin: 0 6px; | |||
height: 20px; | |||
line-height: 20px; | |||
display: inline-block; | |||
} | |||
.fn-gantt .navigate a:link, .fn-gantt .navigate a:visited, .fn-gantt .navigate a:active { | |||
text-decoration: none; | |||
} | |||
.fn-gantt .nav-link { | |||
margin: 0 3px 0 0; | |||
display: inline-block; | |||
width: 20px; | |||
height: 20px; | |||
font-size: 0px; | |||
background: #595959 url(/assets/frappe/js/lib/jQuery.Gantt/img/icon_sprite.png) !important; | |||
border: 1px solid #454546; | |||
cursor: pointer; | |||
vertical-align: top; | |||
-webkit-border-radius: 2px; | |||
-moz-border-radius: 2px; | |||
border-radius: 2px; | |||
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2); | |||
-moz-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2); | |||
box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2); | |||
-webkit-box-sizing: border-box; | |||
-moz-box-sizing: border-box; | |||
box-sizing: border-box; | |||
} | |||
.fn-gantt .nav-link:active { | |||
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF; | |||
-moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF; | |||
box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF; | |||
} | |||
.fn-gantt .navigate .nav-page-back { | |||
background-position: 1px 0 !important; | |||
margin: 0; | |||
} | |||
.fn-gantt .navigate .nav-page-next { | |||
background-position: 1px -16px !important; | |||
margin-right: 15px; | |||
} | |||
.fn-gantt .navigate .nav-slider .nav-page-next { | |||
margin-right: 5px; | |||
} | |||
.fn-gantt .navigate .nav-begin { | |||
background-position: 1px -112px !important; | |||
} | |||
.fn-gantt .navigate .nav-prev-week { | |||
background-position: 1px -128px !important; | |||
} | |||
.fn-gantt .navigate .nav-prev-day { | |||
background-position: 1px -48px !important; | |||
} | |||
.fn-gantt .navigate .nav-next-day { | |||
background-position: 1px -64px !important; | |||
} | |||
.fn-gantt .navigate .nav-next-week { | |||
background-position: 1px -160px !important; | |||
} | |||
.fn-gantt .navigate .nav-end { | |||
background-position: 1px -144px !important; | |||
} | |||
.fn-gantt .navigate .nav-zoomOut { | |||
background-position: 1px -96px !important; | |||
} | |||
.fn-gantt .navigate .nav-zoomIn { | |||
background-position: 1px -80px !important; | |||
margin-left: 15px; | |||
} | |||
.fn-gantt .navigate .nav-now { | |||
background-position: 1px -32px !important; | |||
} | |||
.fn-gantt .navigate .nav-slider .nav-now { | |||
margin-right: 5px; | |||
} | |||
.fn-gantt-loader { | |||
position: absolute; | |||
width: 100%; | |||
height: 100%; | |||
left: 0; | |||
top: 0; | |||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#bf000000', endColorstr='#bf000000',GradientType=0 ); | |||
background: rgba(0,0,0,0.75); | |||
cursor: wait; | |||
z-index: 30; | |||
} | |||
.fn-gantt-loader-spinner span { | |||
position: absolute; | |||
margin: auto; | |||
top: 0; | |||
right: 0; | |||
bottom: 0; | |||
left: 0; | |||
width: 100%; | |||
text-align: center; | |||
height: 1em; | |||
line-height: 1em; | |||
color: #fff; | |||
font-size: 1em; | |||
font-weight: bold; | |||
} | |||
.row:after { | |||
clear: both; | |||
} | |||
@@ -1,551 +0,0 @@ | |||
<!doctype html> | |||
<html lang="en-au"> | |||
<head> | |||
<title>jQuery.Gantt</title> | |||
<meta charset="utf-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" > | |||
<link rel="stylesheet" href="css/style.css" /> | |||
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css" /> | |||
<link rel="stylesheet" href="http://taitems.github.com/UX-Lab/core/css/prettify.css" /> | |||
<style type="text/css"> | |||
body { | |||
font-family: Helvetica, Arial, sans-serif; | |||
font-size: 13px; | |||
padding: 0 0 50px 0; | |||
} | |||
.contain { | |||
width: 800px; | |||
margin: 0 auto; | |||
} | |||
h1 { | |||
margin: 40px 0 20px 0; | |||
} | |||
h2 { | |||
font-size: 1.5em; | |||
padding-bottom: 3px; | |||
border-bottom: 1px solid #DDD; | |||
margin-top: 50px; | |||
margin-bottom: 25px; | |||
} | |||
table th:first-child { | |||
width: 150px; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="contain"> | |||
<h1> | |||
jQuery.Gantt | |||
<small>— Draw Gantt charts with the famous jQuery ease of development</small> | |||
</h1> | |||
<h2>Contributors</h2> | |||
<ul> | |||
<li> | |||
<strong><a href="http://mbielanczuk.com/" target="_blank">Marek Bielańczuk</a></strong> wrote the original jQuery.Gantt plugin that this version is based off of. | |||
</li> | |||
<li> | |||
<strong><a href="http://taitbrown.com/" target="_blank">Tait Brown</a></strong> enforced stricter code guidelines by validating the code, updating it to support HTML5 and tweaking the design. | |||
</li> | |||
<li> | |||
<strong><a href="mailto:leo.pfeifenberger@googlemail.com" target="_blank">Leo Pfeifenberger</a></strong> made <em>major</em> performance updates as well as adding requested features such as click events, state persisting via cookies and scrollToToday on load functionality. | |||
</li> | |||
</ul> | |||
<h2> | |||
Example | |||
</h2> | |||
<div class="gantt"></div> | |||
<h2> | |||
Gantt Configuration | |||
</h2> | |||
<pre class="prettyprint"> | |||
$(".selector").gantt({ | |||
source: "ajax/data.json", | |||
scale: "weeks", | |||
minScale: "weeks", | |||
maxScale: "months", | |||
onItemClick: function(data) { | |||
alert("Item clicked - show some details"); | |||
}, | |||
onAddClick: function(dt, rowId) { | |||
alert("Empty space clicked - add an item!"); | |||
}, | |||
onRender: function() { | |||
console.log("chart rendered"); | |||
} | |||
}); | |||
</pre> | |||
<table class="table table-striped"> | |||
<thead> | |||
<tr> | |||
<th> | |||
Parameter | |||
</th> | |||
<th> | |||
Default | |||
</th> | |||
<th> | |||
Accepts Type | |||
</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td> | |||
<code>source</code> | |||
</td> | |||
<td> | |||
null | |||
</td> | |||
<td> | |||
Array, String (url) | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>itemsPerPage</code> | |||
</td> | |||
<td> | |||
7 | |||
</td> | |||
<td> | |||
Number | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>months</code> | |||
</td> | |||
<td> | |||
["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] | |||
</td> | |||
<td> | |||
Array | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>dow</code> | |||
</td> | |||
<td> | |||
["S", "M", "T", "W", "T", "F", "S"] | |||
</td> | |||
<td> | |||
Array | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>navigate</code> | |||
</td> | |||
<td> | |||
"buttons" | |||
</td> | |||
<td> | |||
String ("buttons","scroll") | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>scale</code> | |||
</td> | |||
<td> | |||
"days" | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>maxScale</code> | |||
</td> | |||
<td> | |||
"months" | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>minScale</code> | |||
</td> | |||
<td> | |||
"hours" | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>waitText</code> | |||
</td> | |||
<td> | |||
"Please Wait..." | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>onItemClick: </code> | |||
</td> | |||
<td> | |||
<code>function (data) { return; }</code></td> | |||
<td> | |||
a JS Function that gets called when clicking on a Gantt-Item. <br />The parameter passed to the function is the dataObj of the item</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>onAddClick</code></td> | |||
<td> | |||
<code>function (dt, rowId) { return; }</code></td> | |||
<td> | |||
a JS Function that gets called when clicking on a Gantt-Item. <br />The parameter passed to the function is the DateTime in ms for the clicked Cell, and the ID if the source object (row)</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>onRender</code></td> | |||
<td> | |||
<code>function () { return; }</code></td> | |||
<td> | |||
a JS Function called whenever the chart is (re)rendered</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>useCookie</code></td> | |||
<td> | |||
<code>false</code></td> | |||
<td> | |||
indicates if cookies should be used to track the chart's state (scale, scrollposition) between postpacks<br /> | |||
<code>jquery.cookie.js</code> needs to be referenced for this to work</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>scrollToToday</code></td> | |||
<td> | |||
<code>true</code></td> | |||
<td> | |||
Boolean</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<h2> | |||
Source Configuration | |||
</h2> | |||
<pre class="prettyprint"> | |||
source: [{ | |||
name: "Example", | |||
desc: "Lorem ipsum dolor sit amet.", | |||
values: [ ... ] | |||
}] | |||
</pre> | |||
<table class="table table-striped"> | |||
<thead> | |||
<tr> | |||
<th> | |||
Parameter | |||
</th> | |||
<th> | |||
Default | |||
</th> | |||
<th> | |||
Accepts Type | |||
</th> | |||
<th> | |||
Meaning | |||
</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td> | |||
<code>name</code> | |||
</td> | |||
<td> | |||
null | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
<td> | |||
Bold value in the left-most column of the gantt row. | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>desc</code> | |||
</td> | |||
<td> | |||
null | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
<td> | |||
Secondary value in the gantt row. | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>values</code> | |||
</td> | |||
<td> | |||
null | |||
</td> | |||
<td> | |||
Array | |||
</td> | |||
<td> | |||
Collection of date ranges for gantt items. See next table. | |||
</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<h2> | |||
Value Configuration | |||
</h2> | |||
<pre class="prettyprint"> | |||
values: [{ | |||
to: "/Date(1328832000000)/", | |||
from: "/Date(1333411200000)/", | |||
desc: "Something", | |||
label: "Example Value", | |||
customClass: "ganttRed", | |||
dataObj: foo.bar[i] | |||
}] | |||
</pre> | |||
<table class="table table-striped"> | |||
<thead> | |||
<tr> | |||
<th> | |||
Parameter | |||
</th> | |||
<th> | |||
Accepts Type | |||
</th> | |||
<th> | |||
Meaning | |||
</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td> | |||
<code>to</code> | |||
</td> | |||
<td> | |||
String (Date) | |||
</td> | |||
<td> | |||
- | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>from</code> | |||
</td> | |||
<td> | |||
String (Date) | |||
</td> | |||
<td> | |||
- | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>desc</code> | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
<td> | |||
Text that appears on hover, I think? | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>label</code> | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
<td> | |||
Appears on the gantt item. | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>customClass</code> | |||
</td> | |||
<td> | |||
String | |||
</td> | |||
<td> | |||
Custom class to be applied to the gantt item. | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<code>dataObj</code> | |||
</td> | |||
<td> | |||
All | |||
</td> | |||
<td> | |||
A data object that is applied directly to the gantt item. | |||
</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</div> | |||
</body> | |||
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script> | |||
<script src="js/jquery.fn.gantt.js"></script> | |||
<script src="http://twitter.github.com/bootstrap/assets/js/bootstrap-tooltip.js"></script> | |||
<script src="http://twitter.github.com/bootstrap/assets/js/bootstrap-popover.js"></script> | |||
<script src="http://taitems.github.com/UX-Lab/core/js/prettify.js"></script> | |||
<script> | |||
$(function() { | |||
"use strict"; | |||
$(".gantt").gantt({ | |||
source: [{ | |||
name: "Sprint 0", | |||
desc: "Analysis", | |||
values: [{ | |||
from: "/Date(1320192000000)/", | |||
to: "/Date(1322401600000)/", | |||
label: "Requirement Gathering", | |||
customClass: "ganttRed" | |||
}] | |||
},{ | |||
name: " ", | |||
desc: "Scoping", | |||
values: [{ | |||
from: "/Date(1322611200000)/", | |||
to: "/Date(1323302400000)/", | |||
label: "Scoping", | |||
customClass: "ganttRed" | |||
}] | |||
},{ | |||
name: "Sprint 1", | |||
desc: "Development", | |||
values: [{ | |||
from: "/Date(1323802400000)/", | |||
to: "/Date(1325685200000)/", | |||
label: "Development", | |||
customClass: "ganttGreen" | |||
}] | |||
},{ | |||
name: " ", | |||
desc: "Showcasing", | |||
values: [{ | |||
from: "/Date(1325685200000)/", | |||
to: "/Date(1325695200000)/", | |||
label: "Showcasing", | |||
customClass: "ganttBlue" | |||
}] | |||
},{ | |||
name: "Sprint 2", | |||
desc: "Development", | |||
values: [{ | |||
from: "/Date(1326785200000)/", | |||
to: "/Date(1325785200000)/", | |||
label: "Development", | |||
customClass: "ganttGreen" | |||
}] | |||
},{ | |||
name: " ", | |||
desc: "Showcasing", | |||
values: [{ | |||
from: "/Date(1328785200000)/", | |||
to: "/Date(1328905200000)/", | |||
label: "Showcasing", | |||
customClass: "ganttBlue" | |||
}] | |||
},{ | |||
name: "Release Stage", | |||
desc: "Training", | |||
values: [{ | |||
from: "/Date(1330011200000)/", | |||
to: "/Date(1336611200000)/", | |||
label: "Training", | |||
customClass: "ganttOrange" | |||
}] | |||
},{ | |||
name: " ", | |||
desc: "Deployment", | |||
values: [{ | |||
from: "/Date(1336611200000)/", | |||
to: "/Date(1338711200000)/", | |||
label: "Deployment", | |||
customClass: "ganttOrange" | |||
}] | |||
},{ | |||
name: " ", | |||
desc: "Warranty Period", | |||
values: [{ | |||
from: "/Date(1336611200000)/", | |||
to: "/Date(1349711200000)/", | |||
label: "Warranty Period", | |||
customClass: "ganttOrange" | |||
}] | |||
}], | |||
navigate: "scroll", | |||
scale: "weeks", | |||
maxScale: "months", | |||
minScale: "days", | |||
itemsPerPage: 10, | |||
onItemClick: function(data) { | |||
alert("Item clicked - show some details"); | |||
}, | |||
onAddClick: function(dt, rowId) { | |||
alert("Empty space clicked - add an item!"); | |||
}, | |||
onRender: function() { | |||
if (window.console && typeof console.log === "function") { | |||
console.log("chart rendered"); | |||
} | |||
} | |||
}); | |||
$(".gantt").popover({ | |||
selector: ".bar", | |||
title: "I'm a popover", | |||
content: "And I'm the content of said popover." | |||
}); | |||
prettyPrint(); | |||
}); | |||
</script> | |||
</html> |
@@ -1,38 +1,97 @@ | |||
@import "variables.less"; | |||
.gantt, .gantt2 { | |||
border: none !important; | |||
border-radius: none !important; | |||
margin: 0px auto !important; | |||
.gantt { | |||
#grid { | |||
.grid-background { | |||
fill: none; | |||
} | |||
.grid-header { | |||
fill: #fff; | |||
stroke: #e0e0e0; | |||
stroke-width: 1.4; | |||
} | |||
.row-odd { | |||
fill: #ffffff; | |||
} | |||
.row-even { | |||
fill: #f5f5f5; | |||
} | |||
.row-line { | |||
stroke: #EBEFF2; | |||
} | |||
.tick { | |||
stroke: #aaa; | |||
stroke-width: 0.2; | |||
&.thick { | |||
stroke-width: 0.4; | |||
} | |||
} | |||
} | |||
* { | |||
-webkit-box-sizing: content-box; | |||
-moz-box-sizing: content-box; | |||
box-sizing: content-box; | |||
#arrow { | |||
fill: none; | |||
stroke: #333; | |||
stroke-width: 1.4; | |||
} | |||
} | |||
.fn-gantt .leftPanel, | |||
.fn-gantt .leftPanel .row0, | |||
.fn-gantt .leftPanel .name, .fn-gantt .leftPanel .desc, | |||
.fn-gantt .dataPanel, | |||
.fn-gantt .day, .fn-gantt .date, | |||
.fn-gantt .rightPanel .month, .fn-gantt .rightPanel .year { | |||
border-color: @border-color !important; | |||
} | |||
.bar { | |||
fill: #b8c2cc; | |||
stroke: #8D99A6; | |||
stroke-width: 0; | |||
transition: stroke-width .3s ease; | |||
} | |||
.bar-label { | |||
fill: #fff; | |||
dominant-baseline: central; | |||
text-anchor: middle; | |||
font-size: 12px; | |||
font-weight: lighter; | |||
letter-spacing: 0.8px; | |||
.fn-gantt .navigate { | |||
border: none !important; | |||
} | |||
&.big { | |||
fill: #555; | |||
text-anchor: start; | |||
} | |||
} | |||
.fn-gantt .leftPanel .name, .fn-gantt .leftPanel .desc, | |||
.fn-gantt .spacer, | |||
.fn-gantt .wd, | |||
.fn-gantt .rightPanel .month, .fn-gantt .rightPanel .year, | |||
.fn-gantt .bottom { | |||
background-color: @panel-bg !important; | |||
} | |||
.handle { | |||
fill: #ddd; | |||
cursor: ew-resize; | |||
opacity: 0; | |||
visibility: hidden; | |||
transition: opacity .3s ease; | |||
} | |||
.bar-wrapper { | |||
cursor: pointer; | |||
.fn-gantt .today { | |||
background-color: #D9F6FF !important; | |||
&:hover { | |||
.bar { | |||
stroke-width: 2; | |||
} | |||
.handle { | |||
visibility: visible; | |||
opacity: 1; | |||
} | |||
} | |||
&.active { | |||
.bar { | |||
stroke-width: 2; | |||
} | |||
} | |||
} | |||
.primary-text, .secondary-text { | |||
font-size: 12px; | |||
text-anchor: middle; | |||
} | |||
.primary-text { | |||
fill: #999; | |||
} | |||
.secondary-text { | |||
fill: #555; | |||
} | |||
} | |||
@@ -0,0 +1 @@ | |||
bench.patches.v3.deprecate_old_config |