fix many bugs as demo is built

This commit is contained in:
safwansamsudeen 2024-12-06 18:09:35 +05:30
parent f37fe4e80f
commit 0c6266e0fe
4 changed files with 111 additions and 64 deletions

View File

@ -166,8 +166,8 @@ export default class Bar {
this.gantt.config.column_width; this.gantt.config.column_width;
let $date_highlight = document.createElement('div'); let $date_highlight = document.createElement('div');
$date_highlight.id = `highlight-${this.task.id}`;
$date_highlight.classList.add('date-highlight'); $date_highlight.classList.add('date-highlight');
$date_highlight.classList.add(`highlight-${this.task.id}`);
$date_highlight.style.height = this.height * 0.8 + 'px'; $date_highlight.style.height = this.height * 0.8 + 'px';
$date_highlight.style.width = this.width + 'px'; $date_highlight.style.width = this.width + 'px';
$date_highlight.style.top = $date_highlight.style.top =
@ -243,7 +243,7 @@ export default class Bar {
const bar = this.$bar; const bar = this.$bar;
const handle_width = 8; const handle_width = 8;
if (!this.gantt.options.dates_readonly) { if (!this.gantt.options.readonly_dates) {
createSVG('rect', { createSVG('rect', {
x: bar.getX() + bar.getWidth() + handle_width - 4, x: bar.getX() + bar.getWidth() + handle_width - 4,
y: bar.getY() + 1, y: bar.getY() + 1,
@ -266,7 +266,7 @@ export default class Bar {
append_to: this.handle_group, append_to: this.handle_group,
}); });
} }
if (!this.gantt.options.progress_readonly) { if (!this.gantt.options.readonly_progress) {
const bar_progress = this.$bar_progress; const bar_progress = this.$bar_progress;
this.$handle_progress = createSVG('circle', { this.$handle_progress = createSVG('circle', {
cx: bar_progress.getEndX(), cx: bar_progress.getEndX(),
@ -299,8 +299,8 @@ export default class Bar {
$.on(this.group, 'click', (e) => { $.on(this.group, 'click', (e) => {
if (!opened) { if (!opened) {
this.show_popup(e.offsetX || e.layerX); this.show_popup(e.offsetX || e.layerX);
document.getElementById( this.gantt.$container.querySelector(
`highlight-${task_id}`, `.highlight-${task_id}`,
).style.display = 'block'; ).style.display = 'block';
} else { } else {
this.gantt.hide_popup(); this.gantt.hide_popup();
@ -315,8 +315,8 @@ export default class Bar {
(e) => (e) =>
(timeout = setTimeout(() => { (timeout = setTimeout(() => {
this.show_popup(e.offsetX || e.layerX); this.show_popup(e.offsetX || e.layerX);
document.getElementById( this.gantt.$container.querySelector(
`highlight-${task_id}`, `.highlight-${task_id}`,
).style.display = 'block'; ).style.display = 'block';
}, 200)), }, 200)),
); );
@ -325,8 +325,9 @@ export default class Bar {
clearTimeout(timeout); clearTimeout(timeout);
this.gantt.popup?.hide?.(); this.gantt.popup?.hide?.();
document.getElementById(`highlight-${task_id}`).style.display = this.gantt.$container.querySelector(
'none'; `.highlight-${task_id}`,
).style.display = 'none';
}); });
} }
@ -589,8 +590,8 @@ export default class Bar {
!this.gantt.config.ignored_dates.find( !this.gantt.config.ignored_dates.find(
(k) => k.getTime() === d.getTime(), (k) => k.getTime() === d.getTime(),
) && ) &&
this.gantt.config.ignored_function && (!this.gantt.config.ignored_function ||
!this.gantt.config.ignored_function(d) !this.gantt.config.ignored_function(d))
) { ) {
actual_duration_in_days++; actual_duration_in_days++;
} }

View File

@ -95,34 +95,33 @@ const DEFAULT_VIEW_MODES = [
]; ];
const DEFAULT_OPTIONS = { const DEFAULT_OPTIONS = {
header_height: 65,
column_width: 30,
view_modes: DEFAULT_VIEW_MODES,
bar_height: 30,
bar_corner_radius: 3,
arrow_curve: 5, arrow_curve: 5,
padding: 18, auto_move_label: false,
view_mode: 'Day', bar_corner_radius: 3,
bar_height: 30,
container_height: 400,
column_width: 30,
date_format: 'YYYY-MM-DD', date_format: 'YYYY-MM-DD',
move_dependencies: true,
show_expected_progress: false,
popup: null,
popup_on: 'hover',
language: 'en',
readonly: false,
progress_readonly: false,
dates_readonly: false,
scroll_to: 'start',
lines: 'both',
auto_move_label: true,
today_button: true,
view_mode_select: false,
default_snap: '1d', default_snap: '1d',
extend_by_units: 7, extend_by_units: 7,
holiday_highlight: { header_height: 65,
green: 'weekend', holiday_highlight: { '#fff7ed': 'weekend' },
},
ignore: [], ignore: [],
language: 'en',
lines: 'both',
move_dependencies: true,
padding: 18,
popup: null,
popup_on: 'hover',
readonly_progress: false,
readonly_dates: false,
readonly: false,
scroll_to: 'start',
show_expected_progress: false,
today_button: true,
view_mode: 'Day',
view_mode_select: false,
view_modes: DEFAULT_VIEW_MODES,
}; };
export { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES }; export { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES };

View File

@ -27,7 +27,7 @@
position: relative; position: relative;
overflow: auto; overflow: auto;
font-size: 12px; font-size: 12px;
height: 500px; height: 300px;
& .popup-wrapper { & .popup-wrapper {
position: absolute; position: absolute;
@ -153,13 +153,14 @@
position: absolute; position: absolute;
background: var(--dark-blue); background: var(--dark-blue);
width: 1px; width: 1px;
z-index: 1000;
} }
& .current-date-highlight { & .current-date-highlight {
background: var(--dark-blue); background: var(--dark-blue);
color: var(--text-light); color: var(--text-light);
padding: 4px 8px; padding: 4px 8px;
border-radius: 200px; border-radius: 5px;
} }
} }

View File

@ -23,7 +23,13 @@ export default class Gantt {
// CSS Selector is passed // CSS Selector is passed
if (typeof element === 'string') { if (typeof element === 'string') {
element = document.querySelector(element); let el = document.querySelector(element);
if (!el) {
throw new ReferenceError(
`CSS selector "${element}" could not be found in DOM`,
);
}
element = el;
} }
// get the SVGElement // get the SVGElement
@ -66,16 +72,10 @@ export default class Gantt {
} }
setup_options(options) { setup_options(options) {
this.original_options = options;
this.options = { ...DEFAULT_OPTIONS, ...options }; this.options = { ...DEFAULT_OPTIONS, ...options };
const custom_mode = this.options.custom_view_modes
? this.options.custom_view_modes.find(
(m) => m.name === this.config.view_mode.name,
)
: null;
if (custom_mode) this.options = { ...this.options, custom_mode };
this.config = {}; this.config = {};
this.config.ignored_dates = []; this.config.ignored_dates = [];
this.config.ignored_positions = []; this.config.ignored_positions = [];
@ -99,6 +99,11 @@ export default class Gantt {
} }
} }
update_options(options) {
this.setup_options({ ...this.original_options, ...options });
this.change_view_mode();
}
setup_tasks(tasks) { setup_tasks(tasks) {
this.tasks = tasks this.tasks = tasks
.map((task, i) => { .map((task, i) => {
@ -201,6 +206,7 @@ export default class Gantt {
if (typeof mode === 'string') { if (typeof mode === 'string') {
mode = this.options.view_modes.find((d) => d.name === mode); mode = this.options.view_modes.find((d) => d.name === mode);
} }
this.config.view_mode = mode; this.config.view_mode = mode;
this.update_view_scale(mode); this.update_view_scale(mode);
this.setup_dates(); this.setup_dates();
@ -303,7 +309,7 @@ export default class Gantt {
this.make_bars(); this.make_bars();
this.make_arrows(); this.make_arrows();
this.map_arrows_on_bars(); this.map_arrows_on_bars();
this.set_width(); this.set_dimensions();
this.set_scroll_position(this.options.scroll_to); this.set_scroll_position(this.options.scroll_to);
} }
@ -348,7 +354,7 @@ export default class Gantt {
}); });
$.attr(this.$svg, { $.attr(this.$svg, {
height: grid_height + this.options.padding + 100, height: grid_height + this.options.padding,
width: '100%', width: '100%',
}); });
} }
@ -578,7 +584,7 @@ export default class Gantt {
* *
* @returns Object containing the x-axis distance and date of the current date, or null if the current date is out of the gantt range. * @returns Object containing the x-axis distance and date of the current date, or null if the current date is out of the gantt range.
*/ */
highlightToday(view_mode) { highlightToday() {
const today = new Date(); const today = new Date();
if (today < this.gantt_start || today > this.gantt_end) return null; if (today < this.gantt_start || today > this.gantt_end) return null;
const diff_in_units = date_utils.diff( const diff_in_units = date_utils.diff(
@ -590,20 +596,25 @@ export default class Gantt {
(diff_in_units / this.config.step) * this.config.column_width; (diff_in_units / this.config.step) * this.config.column_width;
const height = const height =
(this.options.bar_height + this.options.padding) * (this.options.bar_height + this.options.padding) *
this.tasks.length; this.tasks.length +
20 +
this.options.padding / 2;
const date = date_utils.format( const date = date_utils.format(
today, today,
this.config.view_mode.format_string, this.config.view_mode.format_string,
this.options.language, this.options.language,
); );
this.$current_highlight = this.$current_highlight = this.create_el({ console.log(this.$header.clientHeight);
top, this.$current_highlight = this.create_el({
top: this.options.header_height - 20,
left, left,
height, height,
classes: 'current-highlight', classes: 'current-highlight',
append_to: this.$container, append_to: this.$container,
}); });
let $today = document.getElementById(date.replaceAll(' ', '_')); let $today = this.$container.querySelector(
'.date_' + date.replaceAll(' ', '_'),
);
if ($today) { if ($today) {
$today.classList.add('current-date-highlight'); $today.classList.add('current-date-highlight');
$today.style.top = +$today.style.top.slice(0, -2) - 4 + 'px'; $today.style.top = +$today.style.top.slice(0, -2) - 4 + 'px';
@ -663,7 +674,7 @@ export default class Gantt {
create_el({ left, top, width, height, id, classes, append_to }) { create_el({ left, top, width, height, id, classes, append_to }) {
let $el = document.createElement('div'); let $el = document.createElement('div');
$el.classList.add(classes); for (let cls of classes.split(' ')) $el.classList.add(cls);
$el.style.top = top + 'px'; $el.style.top = top + 'px';
$el.style.left = left + 'px'; $el.style.left = left + 'px';
if (id) $el.id = id; if (id) $el.id = id;
@ -679,8 +690,7 @@ export default class Gantt {
let $lower_text = this.create_el({ let $lower_text = this.create_el({
left: date.lower_x, left: date.lower_x,
top: date.lower_y, top: date.lower_y,
id: date.formatted_date, classes: 'lower-text date_' + date.formatted_date,
classes: 'lower-text',
append_to: this.$lower_header, append_to: this.$lower_header,
}); });
@ -799,14 +809,17 @@ export default class Gantt {
} }
} }
set_width() { set_dimensions() {
const cur_width = this.$svg.getBoundingClientRect().width; const { width: cur_width, height } = this.$svg.getBoundingClientRect();
const actual_width = this.$svg.querySelector('.grid .grid-row') const actual_width = this.$svg.querySelector('.grid .grid-row')
? this.$svg.querySelector('.grid .grid-row').getAttribute('width') ? this.$svg.querySelector('.grid .grid-row').getAttribute('width')
: 0; : 0;
if (cur_width < actual_width) { if (cur_width < actual_width) {
this.$svg.setAttribute('width', actual_width); this.$svg.setAttribute('width', actual_width);
} }
this.$container.style.height =
{ auto: height }[this.options.container_height] ||
this.options.container_height + 'px';
} }
set_scroll_position(date) { set_scroll_position(date) {
@ -828,9 +841,43 @@ export default class Gantt {
); );
const scroll_pos = const scroll_pos =
(units_since_first_task / this.config.step) * (units_since_first_task / this.config.step) *
this.config.column_width -
this.config.column_width; this.config.column_width;
parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' }); parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' });
this.$side_header.style.left =
this.$container.clientWidth +
this.$container.scrollLeft -
this.$side_header.clientWidth -
5 +
'px';
// Calculate current scroll position's upper text
if (this.$current) this.$current.classList.remove('current-upper');
this.upperTexts = Array.from(
this.$container.querySelectorAll('.upper-text'),
);
let currentDate = date_utils.add(
this.gantt_start,
this.$container.scrollLeft / this.config.column_width,
this.config.unit,
);
let currentUpper = this.config.view_mode.upper_text(currentDate);
let $el = this.upperTexts.find((el) => el.textContent === currentUpper);
// Recalculate
currentDate = date_utils.add(
this.gantt_start,
(this.$container.scrollLeft + $el.clientWidth) /
this.config.column_width,
this.config.unit,
);
currentUpper = this.config.view_mode.upper_text(currentDate);
$el = this.upperTexts.find((el) => el.textContent === currentUpper);
$el.classList.add('current-upper');
$el.style.left = this.$container.scrollLeft + 'px';
this.$current = $el;
} }
scroll_today() { scroll_today() {
@ -953,7 +1000,7 @@ export default class Gantt {
}); });
$.on(this.$container, 'scroll', (e) => { $.on(this.$container, 'scroll', (e) => {
let elements = document.querySelectorAll('.bar-wrapper'); let elements = this.$container.querySelectorAll('.bar-wrapper');
let localBars = []; let localBars = [];
const ids = []; const ids = [];
let dx; let dx;
@ -971,16 +1018,15 @@ export default class Gantt {
this.$current.style.left = e.currentTarget.scrollLeft + 'px'; this.$current.style.left = e.currentTarget.scrollLeft + 'px';
// Calculate current scroll position's upper text // Calculate current scroll position's upper text
const upperTexts = Array.from(
document.querySelectorAll('.upper-text'),
);
let currentDate = date_utils.add( let currentDate = date_utils.add(
this.gantt_start, this.gantt_start,
e.currentTarget.scrollLeft / this.config.column_width, e.currentTarget.scrollLeft / this.config.column_width,
this.config.unit, this.config.unit,
); );
let currentUpper = this.config.view_mode.upper_text(currentDate); let currentUpper = this.config.view_mode.upper_text(currentDate);
let $el = upperTexts.find((el) => el.textContent === currentUpper); let $el = this.upperTexts.find(
(el) => el.textContent === currentUpper,
);
// Recalculate for smoother experience // Recalculate for smoother experience
currentDate = date_utils.add( currentDate = date_utils.add(
this.gantt_start, this.gantt_start,
@ -989,7 +1035,7 @@ export default class Gantt {
this.config.unit, this.config.unit,
); );
currentUpper = this.config.view_mode.upper_text(currentDate); currentUpper = this.config.view_mode.upper_text(currentDate);
$el = upperTexts.find((el) => el.textContent === currentUpper); $el = this.upperTexts.find((el) => el.textContent === currentUpper);
if ($el !== this.$current) { if ($el !== this.$current) {
if (this.$current) if (this.$current)
@ -1047,7 +1093,7 @@ export default class Gantt {
} else if ( } else if (
is_dragging && is_dragging &&
!this.options.readonly && !this.options.readonly &&
!this.options.dates_readonly !this.options.readonly_dates
) { ) {
bar.update_bar_position({ x: $bar.ox + $bar.finaldx }); bar.update_bar_position({ x: $bar.ox + $bar.finaldx });
} }