From 6e0e0a9704e32872d0f375ae67c18c33e58534fc Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Fri, 29 Nov 2024 16:34:33 +0530 Subject: [PATCH 01/13] make daily mode work after rewrite of date system --- .gitignore | 3 +- index.html | 46 ++--- src/bar.js | 71 +++---- src/date_utils.js | 3 +- src/defaults.js | 115 +++++++++++ src/index.js | 500 ++++++++++------------------------------------ 6 files changed, 287 insertions(+), 451 deletions(-) create mode 100644 src/defaults.js diff --git a/.gitignore b/.gitignore index 8ee493f7..14af5267 100755 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ coverage # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release +dist/* # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git @@ -29,4 +30,4 @@ node_modules .DS_Store -gh-pages \ No newline at end of file +gh-pages diff --git a/index.html b/index.html index bf3a2760..b8643569 100644 --- a/index.html +++ b/index.html @@ -37,7 +37,7 @@

let tasks = [ { start: '2024-04-01', - end: '2024-04-01', + end: '2024-04-04', name: 'Redesign website', id: 'Task 0', progress: 30, @@ -77,7 +77,7 @@

}, { start: '2024-04-21', - end: '2024-04-29', + end: '2024-05-29', name: 'Go Live!', id: 'Task 5', progress: 0, @@ -85,22 +85,22 @@

custom_class: 'bar-milestone', }, // { - // start: '2014-01-05', - // end: '2019-10-12', - // name: 'Long term task', - // id: "Task 6", - // progress: 0 - // } + // start: '2014-01-05', + // end: '2019-10-12', + // name: 'Long term task', + // id: 'Task 6', + // progress: 0, + // }, ]; // Uncomment to test fixed header - tasks = [ - ...tasks, - ...Array.from({ length: tasks.length * 3 }, (_, i) => ({ - ...tasks[i % 3], - id: i, - })), - ]; + // tasks = [ + // ...tasks, + // ...Array.from({ length: tasks.length * 3 }, (_, i) => ({ + // ...tasks[i % 3], + // id: i, + // })), + // ]; let gantt_chart = new Gantt('.gantt-target', tasks, { on_click(task) { console.log('Click', task); @@ -109,15 +109,13 @@

// console.log("Hover", x, y); // } view_mode: 'Day', - view_mode_padding: { DAY: '3d' }, - custom_view_modes: [ - { - name: 'Custom Day', - padding: '1m', - step: 3, - unit: 'day', - }, - ], + // view_modes: [ + // { + // name: 'Custom Day', + // padding: '1m', + // step: '1d', + // }, + // ], // popup_on: 'click', // move_dependencies: false, // scroll_to: 'today', diff --git a/src/bar.js b/src/bar.js index f6be4369..9f5b542c 100644 --- a/src/bar.js +++ b/src/bar.js @@ -28,9 +28,9 @@ export default class Bar { this.compute_y(); this.compute_duration(); this.corner_radius = this.gantt.options.bar_corner_radius; - this.width = this.gantt.options.column_width * this.duration; + this.width = this.gantt.config.column_width * this.duration; this.progress_width = - this.gantt.options.column_width * + this.gantt.config.column_width * this.duration * (this.task.progress / 100) || 0; this.group = createSVG('g', { @@ -107,7 +107,6 @@ export default class Bar { : ''), append_to: this.bar_group, }); - animateSVG(this.$bar, 'width', 0, this.width); if (this.invalid) { @@ -138,6 +137,7 @@ export default class Bar { draw_progress_bar() { if (this.invalid) return; + this.$bar_progress = createSVG('rect', { x: this.x, y: this.y, @@ -150,8 +150,8 @@ export default class Bar { }); const x = (date_utils.diff(this.task._start, this.gantt.gantt_start, 'hour') / - this.gantt.options.step) * - this.gantt.options.column_width; + this.gantt.config.step) * + this.gantt.config.column_width; let $date_highlight = document.createElement('div'); $date_highlight.id = `highlight-${this.task.id}`; @@ -285,7 +285,6 @@ export default class Bar { if (this.gantt.options.popup_on === 'click') { let opened = false; $.on(this.group, 'click', (e) => { - console.log(opened); if (!opened) { this.show_popup(e.offsetX || e.layerX); document.getElementById( @@ -304,17 +303,12 @@ export default class Bar { (e) => (timeout = setTimeout(() => { this.show_popup(e.offsetX || e.layerX); - document.getElementById( - `${task_id}-highlight`, - ).style.display = 'block'; }, 200)), ); $.on(this.group, 'mouseleave', () => { clearTimeout(timeout); this.gantt.popup?.hide?.(); - document.getElementById(`${task_id}-highlight`).style.display = - 'none'; }); } @@ -428,7 +422,6 @@ export default class Bar { date_changed() { let changed = false; const { new_start_date, new_end_date } = this.compute_start_end_date(); - if (Number(this.task._start) !== Number(new_start_date)) { changed = true; this.task._start = new_start_date; @@ -461,15 +454,16 @@ export default class Bar { compute_start_end_date() { const bar = this.$bar; - const x_in_units = bar.getX() / this.gantt.options.column_width; + const x_in_units = bar.getX() / this.gantt.config.column_width; let new_start_date = date_utils.add( this.gantt.gantt_start, - x_in_units * this.gantt.options.step, - 'hour', + x_in_units * this.gantt.config.step, + this.gantt.config.unit, ); const start_offset = this.gantt.gantt_start.getTimezoneOffset() - new_start_date.getTimezoneOffset(); + if (start_offset) { new_start_date = date_utils.add( new_start_date, @@ -478,11 +472,11 @@ export default class Bar { ); } - const width_in_units = bar.getWidth() / this.gantt.options.column_width; + const width_in_units = bar.getWidth() / this.gantt.config.column_width; const new_end_date = date_utils.add( new_start_date, - width_in_units * this.gantt.options.step, - 'hour', + width_in_units * this.gantt.config.step, + this.gantt.config.unit, ); return { new_start_date, new_end_date }; @@ -497,7 +491,7 @@ export default class Bar { compute_expected_progress() { this.expected_progress = date_utils.diff(date_utils.today(), this.task._start, 'hour') / - this.gantt.options.step; + this.gantt.config.step; this.expected_progress = ((this.expected_progress < this.duration ? this.expected_progress @@ -507,17 +501,22 @@ export default class Bar { } compute_x() { - const { step, column_width } = this.gantt.options; + const { step, column_width } = this.gantt.config; const task_start = this.task._start; const gantt_start = this.gantt.gantt_start; - const diff = date_utils.diff(task_start, gantt_start, 'hour'); - let x = (diff / step) * column_width; + const diff = date_utils.diff( + task_start, + gantt_start, + this.gantt.config.unit, + ); + let x = diff * column_width; /* Since the column width is based on 30, we count the month-difference, multiply it by 30 for a "pseudo-month" and then add the days in the month, making sure the number does not exceed 29 so it is within the column */ + if (this.gantt.view_is('Month')) { const diffDaysBasedOn30DayMonths = date_utils.diff(task_start, gantt_start, 'month') * 30; @@ -529,6 +528,7 @@ export default class Bar { x = (diff * column_width) / 30; } + this.x = x; } @@ -541,8 +541,11 @@ export default class Bar { compute_duration() { this.duration = - date_utils.diff(this.task._end, this.task._start, 'hour') / - this.gantt.options.step; + date_utils.diff( + this.task._end, + this.task._start, + this.gantt.config.unit, + ) / this.gantt.config.step; } get_snap_position(dx) { @@ -551,29 +554,29 @@ export default class Bar { position; if (this.gantt.view_is('Week')) { - rem = dx % (this.gantt.options.column_width / 7); + rem = dx % (this.gantt.config.column_width / 7); position = odx - rem + - (rem < this.gantt.options.column_width / 14 + (rem < this.gantt.config.column_width / 14 ? 0 - : this.gantt.options.column_width / 7); + : this.gantt.config.column_width / 7); } else if (this.gantt.view_is('Month')) { - rem = dx % (this.gantt.options.column_width / 30); + rem = dx % (this.gantt.config.column_width / 30); position = odx - rem + - (rem < this.gantt.options.column_width / 60 + (rem < this.gantt.config.column_width / 60 ? 0 - : this.gantt.options.column_width / 30); + : this.gantt.config.column_width / 30); } else { - rem = dx % this.gantt.options.column_width; + rem = dx % this.gantt.config.column_width; position = odx - rem + - (rem < this.gantt.options.column_width / 2 + (rem < this.gantt.config.column_width / 2 ? 0 - : this.gantt.options.column_width); + : this.gantt.config.column_width); } return position; } @@ -592,7 +595,7 @@ export default class Bar { this.compute_expected_progress(); this.$expected_bar_progress.setAttribute( 'width', - this.gantt.options.column_width * + this.gantt.config.column_width * this.duration * (this.expected_progress / 100) || 0, ); diff --git a/src/date_utils.js b/src/date_utils.js index 695f83de..0dc6e36b 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -6,7 +6,6 @@ const MINUTE = 'minute'; const SECOND = 'second'; const MILLISECOND = 'millisecond'; - export default { parse_duration(duration) { const regex = /([0-9]+)(y|m|d|h|min|s|ms)/gm; @@ -84,7 +83,7 @@ export default { month: 'long', }); const dateTimeFormatShort = new Intl.DateTimeFormat(lang, { - month: "short", + month: 'short', }); const month_name = dateTimeFormat.format(date); const month_name_capitalized = diff --git a/src/defaults.js b/src/defaults.js new file mode 100644 index 00000000..0c8d1829 --- /dev/null +++ b/src/defaults.js @@ -0,0 +1,115 @@ +import date_utils from './date_utils'; + +const DEFAULT_VIEW_MODES = [ + { + name: 'Hour', + padding: '7d', + step: '1h', + lower_text: 'HH', + upper_text: (d, ld, lang) => + d.getDate() !== ld.getDate() + ? date_utils.format(d, 'D MMMM', lang) + : '', + }, + { + name: 'Quarter Day', + padding: '7d', + step: '6h', + format_string: 'YYYY-MM-DD HH', + lower_text: 'HH', + upper_text: (d, ld, lang) => + d.getDate() !== ld.getDate() + ? date_utils.format(d, 'D MMM', lang) + : '', + }, + { + name: 'Half Day', + padding: '7d', + step: '12h', + format_string: 'YYYY-MM-DD HH', + lower_text: 'HH', + upper_text: (d, ld, lang) => + d.getDate() !== ld.getDate() + ? d.getMonth() !== d.getMonth() + ? date_utils.format(d, 'D MMM', lang) + : date_utils.format(d, 'D', lang) + : '', + }, + { + name: 'Day', + padding: '14d', + step: '1d', + lower_text: (d, ld, lang) => + d.getDate() !== ld.getDate() ? date_utils.format(d, 'D', lang) : '', + upper_text: (d, ld, lang) => + d.getMonth() !== ld.getMonth() + ? date_utils.format(d, 'MMMM', lang) + : '', + }, + { + name: 'Week', + padding: '1m', + step: '7d', + column_width: 140, + lower_text: (d, ld, lang) => + d.getMonth() !== ld.getMonth() + ? date_utils.format(d, 'D MMM', lang) + : date_utils.format(d, 'D', lang), + upper_text: (d, ld, lang) => + d.getMonth() !== ld.getMonth() + ? date_utils.format(d, 'MMMM', lang) + : '', + }, + { + name: 'Month', + padding: '1m', + step: '1m', + column_width: 120, + format_string: 'YYYY-MM', + lower_text: 'MMMM', + upper_text: (d, ld, lang) => + d.getMonth() !== ld.getMonth() + ? date_utils.format(d, 'YYYY', lang) + : '', + }, + { + name: 'Year', + padding: '1m', + step: '1y', + column_width: 120, + format_string: 'YYYY', + lower_text: 'YYYY', + upper_text: (d, ld, lang) => + d.getMonth() !== ld.getMonth() + ? date_utils.format(d, 'YYYY', lang) + : '', + }, +]; + +const DEFAULT_OPTIONS = { + header_height: 65, + column_width: 30, + view_modes: DEFAULT_VIEW_MODES, + bar_height: 30, + bar_corner_radius: 3, + arrow_curve: 5, + padding: 18, + view_mode: 'Day', + 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, + highlight_weekend: true, + scroll_to: 'start', + lines: 'both', + auto_move_label: true, + today_button: true, + view_mode_select: false, +}; + +export { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES }; diff --git a/src/index.js b/src/index.js index ae73f7a6..b09ee771 100644 --- a/src/index.js +++ b/src/index.js @@ -1,55 +1,22 @@ import date_utils from './date_utils'; import { $, createSVG } from './svg_utils'; -import Bar from './bar'; + import Arrow from './arrow'; +import Bar from './bar'; import Popup from './popup'; +import { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES } from './defaults'; + import './gantt.css'; const VIEW_MODE = { - HOUR: 'Hour', - QUARTER_DAY: 'Quarter Day', - HALF_DAY: 'Half Day', - DAY: 'Day', - WEEK: 'Week', - MONTH: 'Month', - YEAR: 'Year', -}; - -const VIEW_MODE_PADDING = { - HOUR: ['7d', '7d'], - QUARTER_DAY: ['7d', '7d'], - HALF_DAY: ['7d', '7d'], - DAY: ['1m', '1m'], - WEEK: ['1m', '1m'], - MONTH: ['1m', '1m'], - YEAR: ['2y', '2y'], -}; - -const DEFAULT_OPTIONS = { - header_height: 65, - column_width: 30, - view_modes: [...Object.values(VIEW_MODE)], - bar_height: 30, - bar_corner_radius: 3, - arrow_curve: 5, - padding: 18, - view_mode: 'Day', - 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, - highlight_weekend: true, - scroll_to: 'start', - lines: 'both', - auto_move_label: true, - today_button: true, - view_mode_select: false, + HOUR: DEFAULT_VIEW_MODES[0], + QUARTER_DAY: DEFAULT_VIEW_MODES[1], + HALF_DAY: DEFAULT_VIEW_MODES[2], + DAY: DEFAULT_VIEW_MODES[3], + WEEK: DEFAULT_VIEW_MODES[4], + MONTH: DEFAULT_VIEW_MODES[5], + YEAR: DEFAULT_VIEW_MODES[6], }; export default class Gantt { @@ -57,7 +24,6 @@ export default class Gantt { this.setup_wrapper(wrapper); this.setup_options(options); this.setup_tasks(tasks); - // initialize with default view mode this.change_view_mode(); this.bind_events(); } @@ -113,25 +79,12 @@ export default class Gantt { this.options = { ...DEFAULT_OPTIONS, ...options }; const custom_mode = this.options.custom_view_modes ? this.options.custom_view_modes.find( - (m) => m.name === this.options.view_mode, + (m) => m.name === this.config.view_mode.name, ) : null; if (custom_mode) this.options = { ...this.options, custom_mode }; - if (!this.options.view_mode_padding) - this.options.view_mode_padding = {}; - for (let [key, value] of Object.entries( - this.options.view_mode_padding, - )) { - if (typeof value === 'string') { - // Configure for single value given - this.options.view_mode_padding[key] = [value, value]; - } - } - this.options.view_mode_padding = { - ...VIEW_MODE_PADDING, - ...options.view_mode_padding, - }; + this.config = {}; } setup_tasks(tasks) { @@ -234,54 +187,21 @@ export default class Gantt { } change_view_mode(mode = this.options.view_mode) { + if (typeof mode === 'string') { + mode = this.options.view_modes.find((d) => d.name === mode); + } + this.config.view_mode = mode; this.update_view_scale(mode); this.setup_dates(); this.render(); - // fire viewmode_change event this.trigger_event('view_change', [mode]); } - update_view_scale(view_mode) { - this.options.view_mode = view_mode; - const custom_mode = this.options.custom_mode; - if (custom_mode) { - //configure step and column width for custom view case - if (custom_mode.unit === 'hour') { - this.options.step = custom_mode.step; - this.options.column_width = 38; - } else if (custom_mode.unit === 'day') { - this.options.step = custom_mode.step * 24; - this.options.column_width = 38; - } else if (custom_mode.unit === 'month') { - this.options.step = custom_mode.step * 24 * 30; - this.options.column_width = 120; - } else { - this.options.step = 24; - this.options.column_width = 38; - } - } - if (view_mode === VIEW_MODE.HOUR) { - this.options.step = 24 / 24; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.DAY) { - this.options.step = 24; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.HALF_DAY) { - this.options.step = 24 / 2; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.QUARTER_DAY) { - this.options.step = 24 / 4; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.WEEK) { - this.options.step = 24 * 7; - this.options.column_width = 140; - } else if (view_mode === VIEW_MODE.MONTH) { - this.options.step = 24 * 30; - this.options.column_width = 120; - } else if (view_mode === VIEW_MODE.YEAR) { - this.options.step = 24 * 365; - this.options.column_width = 120; - } + update_view_scale(mode) { + let { duration, scale } = date_utils.parse_duration(mode.step); + this.config.step = duration; + this.config.unit = scale; + this.config.column_width = mode.column_width || 38; } setup_dates() { @@ -290,60 +210,39 @@ export default class Gantt { } setup_gantt_dates() { - this.gantt_start = this.gantt_end = null; - + // set global start and end date + let gantt_start, gantt_end; for (let task of this.tasks) { - // set global start and end date - if (!this.gantt_start || task._start < this.gantt_start) { - this.gantt_start = task._start; + if (!gantt_start || task._start < gantt_start) { + gantt_start = task._start; } - if (!this.gantt_end || task._end > this.gantt_end) { - this.gantt_end = task._end; + if (!gantt_end || task._end > gantt_end) { + gantt_end = task._end; } } - let gantt_start, gantt_end; - if (!this.gantt_start) gantt_start = new Date(); - else gantt_start = date_utils.start_of(this.gantt_start, 'day'); - if (!this.gantt_end) gantt_end = new Date(); - else gantt_end = date_utils.start_of(this.gantt_end, 'day'); - - const custom_mode = this.options.custom_mode; - let [padding_start, padding_end] = [ - { duration: 1, scale: 'day' }, - { duration: 1, scale: 'day' }, - ]; - if (custom_mode) { - [padding_start, padding_end] = [ - custom_mode.padding, - custom_mode.padding, - ].map(date_utils.parse_duration); - } else { - let viewKey; - for (let [key, value] of Object.entries(VIEW_MODE)) { - if (value === this.options.view_mode) { - viewKey = key; - } - } - [padding_start, padding_end] = this.options.view_mode_padding[ - viewKey - ].map(date_utils.parse_duration); - } + + gantt_start = date_utils.start_of(gantt_start, 'day'); + gantt_end = date_utils.start_of(gantt_end, 'day'); + + // handle single value for padding + if (typeof this.config.view_mode.padding === 'string') + this.config.view_mode.padding = [ + this.config.view_mode.padding, + this.config.view_mode.padding, + ]; + + let [padding_start, padding_end] = this.config.view_mode.padding.map( + date_utils.parse_duration, + ); gantt_start = date_utils.add( gantt_start, -padding_start.duration, padding_start.scale, ); - let format_string; - if (this.view_is(VIEW_MODE.YEAR)) { - format_string = 'YYYY'; - } else if (this.view_is(VIEW_MODE.MONTH)) { - format_string = 'YYYY-MM'; - } else if (this.view_is(VIEW_MODE.DAY)) { - format_string = 'YYYY-MM-DD'; - } else { - format_string = 'YYYY-MM-DD HH'; - } + let format_string = + this.config.view_mode.format_string || 'YYYY-MM-DD HH'; + this.gantt_start = date_utils.parse( date_utils.format(gantt_start, format_string), ); @@ -356,36 +255,15 @@ export default class Gantt { } setup_date_values() { - this.dates = []; - let cur_date = null; - - while (cur_date === null || cur_date < this.gantt_end) { - if (this.options.custom_mode) { - const step = this.options.custom_mode.step || 1; - const unit = this.options.custom_mode.unit || 'day'; - - if (!cur_date) { - cur_date = date_utils.clone(this.gantt_start); - } else { - cur_date = date_utils.add(cur_date, step, unit); - } - } else { - if (!cur_date) { - cur_date = date_utils.clone(this.gantt_start); - } else { - if (this.view_is(VIEW_MODE.YEAR)) { - cur_date = date_utils.add(cur_date, 1, 'year'); - } else if (this.view_is(VIEW_MODE.MONTH)) { - cur_date = date_utils.add(cur_date, 1, 'month'); - } else { - cur_date = date_utils.add( - cur_date, - this.options.step, - 'hour', - ); - } - } - } + let cur_date = this.gantt_start; + this.dates = [cur_date]; + + while (cur_date < this.gantt_end) { + cur_date = date_utils.add( + cur_date, + this.config.step, + this.config.unit, + ); this.dates.push(cur_date); } } @@ -434,7 +312,7 @@ export default class Gantt { } make_grid_background() { - const grid_width = this.dates.length * this.options.column_width; + const grid_width = this.dates.length * this.config.column_width; const grid_height = this.options.header_height + this.options.padding + @@ -458,7 +336,7 @@ export default class Gantt { make_grid_rows() { const rows_layer = createSVG('g', { append_to: this.layers.grid }); - const row_width = this.dates.length * this.options.column_width; + const row_width = this.dates.length * this.config.column_width; const row_height = this.options.bar_height + this.options.padding; let row_y = this.options.header_height + this.options.padding / 2; @@ -485,7 +363,7 @@ export default class Gantt { let $header = document.createElement('div'); $header.style.height = this.options.header_height + 10 + 'px'; $header.style.width = - this.dates.length * this.options.column_width + 'px'; + this.dates.length * this.config.column_width + 'px'; $header.classList.add('grid-header'); this.$header = $header; this.$container.appendChild($header); @@ -524,7 +402,7 @@ export default class Gantt { $option.textContent = VIEW_MODE[key]; $select.appendChild($option); } - // $select.value = this.options.view_mode + $select.addEventListener( 'change', function () { @@ -608,7 +486,7 @@ export default class Gantt { let row_y = this.options.header_height + this.options.padding / 2; - const row_width = this.dates.length * this.options.column_width; + const row_width = this.dates.length * this.config.column_width; const row_height = this.options.bar_height + this.options.padding; if (this.options.lines !== 'vertical') { for (let _ of this.tasks) { @@ -651,10 +529,10 @@ export default class Gantt { if (this.view_is(VIEW_MODE.MONTH)) { tick_x += (date_utils.get_days_in_month(date) * - this.options.column_width) / + this.config.column_width) / 30; } else { - tick_x += this.options.column_width; + tick_x += this.config.column_width; } } } @@ -669,8 +547,8 @@ export default class Gantt { if (d.getDay() === 0 || d.getDay() === 6) { const x = (date_utils.diff(d, this.gantt_start, 'hour') / - this.options.step) * - this.options.column_width; + this.config.step) * + this.config.column_width; const height = (this.options.bar_height + this.options.padding) * this.tasks.length; @@ -679,7 +557,7 @@ export default class Gantt { y: this.options.header_height + this.options.padding / 2, width: (this.view_is('Day') ? 1 : 2) * - this.options.column_width, + this.config.column_width, height, class: 'holiday-highlight', append_to: this.layers.grid, @@ -689,23 +567,24 @@ export default class Gantt { } /** - * Compute the horizontal x-axis distance and associated date for the current date and view. - * - * @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. - */ + * Compute the horizontal x-axis distance and associated date for the current date and view. + * + * @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. + */ computeGridHighlightDimensions(view_mode) { const todayDate = new Date(); - if (todayDate < this.gantt_start || todayDate > this.gantt_end) return null; + if (todayDate < this.gantt_start || todayDate > this.gantt_end) + return null; - let x = this.options.column_width / 2; + let x = this.config.column_width / 2; if (this.view_is(VIEW_MODE.DAY)) { return { x: x + (date_utils.diff(today, this.gantt_start, 'hour') / - this.options.step) * - this.options.column_width, + this.config.step) * + this.config.column_width, date: today, }; } @@ -728,7 +607,7 @@ export default class Gantt { if (todayDate >= startDate && todayDate <= endDate) { return { x, date: startDate }; } else { - x += this.options.column_width; + x += this.config.column_width; } } @@ -746,7 +625,9 @@ export default class Gantt { this.view_is(VIEW_MODE.YEAR) ) { // Used as we must find the _end_ of session if view is not Day - const highlightDimensions = this.computeGridHighlightDimensions(this.options.view_mode); + const highlightDimensions = this.computeGridHighlightDimensions( + this.config.view_mode, + ); if (!highlightDimensions) return; const { x: left, date } = highlightDimensions; if (!this.dates.find((d) => d.getTime() == date.getTime())) return; @@ -830,152 +711,8 @@ export default class Gantt { let last_date = last_date_info ? last_date_info.date : date_utils.add(date, 1, 'day'); - let date_text = {}; - const custom_mode = this.options.custom_mode; - if (custom_mode) { - let lower_text, upper_text; - const unit = custom_mode ? custom_mode.unit.toLowerCase() : 'day'; - if (unit === 'hour') { - lower_text = date_utils.format( - date, - 'HH', - this.options.language, - ); - upper_text = - date.getDate() !== last_date.getDate() - ? date_utils.format( - date, - 'D MMMM', - this.options.language, - ) - : ''; - } else if (unit === 'day') { - lower_text = - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D', this.options.language) - : ''; - upper_text = - date.getMonth() !== last_date.getMonth() || !last_date_info - ? date_utils.format(date, 'MMMM', this.options.language) - : ''; - } else if (unit === 'month') { - lower_text = date_utils.format( - date, - 'MMMM', - this.options.language, - ); - upper_text = - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : ''; - } else { - lower_text = date_utils.format( - date, - 'YYYY', - this.options.language, - ); - upper_text = ''; // Default to no upper text for very large units - } - date_text[`${custom_mode.name}_upper`] = upper_text; - date_text[`${custom_mode.name}_lower`] = lower_text; - } else { - date_text = { - Hour_lower: date_utils.format( - date, - 'HH', - this.options.language, - ), - 'Quarter Day_lower': date_utils.format( - date, - 'HH', - this.options.language, - ), - 'Half Day_lower': date_utils.format( - date, - 'HH', - this.options.language, - ), - Day_lower: - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D', this.options.language) - : '', - Week_lower: - date.getMonth() !== last_date.getMonth() - ? date_utils.format( - date, - 'D MMM', - this.options.language, - ) - : date_utils.format(date, 'D', this.options.language), - Month_lower: date_utils.format( - date, - 'MMMM', - this.options.language, - ), - Year_lower: date_utils.format( - date, - 'YYYY', - this.options.language, - ), - Hour_upper: - date.getDate() !== last_date.getDate() - ? date_utils.format( - date, - 'D MMMM', - this.options.language, - ) - : '', - 'Quarter Day_upper': - date.getDate() !== last_date.getDate() - ? date_utils.format( - date, - 'D MMM', - this.options.language, - ) - : '', - 'Half Day_upper': - date.getDate() !== last_date.getDate() - ? date.getMonth() !== last_date.getMonth() - ? date_utils.format( - date, - 'D MMM', - this.options.language, - ) - : date_utils.format( - date, - 'D', - this.options.language, - ) - : '', - Day_upper: - date.getMonth() !== last_date.getMonth() || !last_date_info - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Week_upper: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Month_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - Year_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - }; - } - let column_width = - custom_mode && - custom_mode.lower_text && - custom_mode.lower_text.column_width - ? custom_mode.lower_text.column_width * (custom_mode.step ?? 1) - : this.view_is(VIEW_MODE.MONTH) - ? (date_utils.get_days_in_month(date) * - this.options.column_width) / - 30 - : this.options.column_width; + let column_width = this.config.column_width; const base_pos = { x: last_date_info @@ -1000,34 +737,25 @@ export default class Gantt { Year_lower: column_width / 2, Year_upper: (column_width * 30) / 2, }; - if (custom_mode) { - x_pos[`${custom_mode.name}_upper`] = column_width / 2; - x_pos[`${custom_mode.name}_lower`] = - column_width / - (custom_mode.unit.toLowerCase() === 'day' ? 1 : 2); - } + let upper_text = this.config.view_mode.upper_text; + let lower_text = this.config.view_mode.lower_text; + return { date, formatted_date: date_utils.format(date).replaceAll(' ', '_'), - column_width, + column_width: this.config.column_width, base_pos_x: base_pos.x, - upper_text: this.options.upper_text - ? this.options.upper_text( - date, - this.options.view_mode, - date_text[`${this.options.view_mode}_upper`], - ) - : date_text[`${this.options.view_mode}_upper`], - lower_text: this.options.lower_text - ? this.options.lower_text( - date, - this.options.view_mode, - date_text[`${this.options.view_mode}_lower`], - ) - : date_text[`${this.options.view_mode}_lower`], - upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`], + upper_text: + typeof upper_text === 'string' + ? date_utils.format(date, upper_text, this.options.language) + : upper_text(date, last_date, this.options.language), + lower_text: + typeof upper_text === 'string' + ? date_utils.format(date, lower_text, this.options.language) + : lower_text(date, last_date, this.options.language), + upper_x: base_pos.x + x_pos[`${this.config.view_mode.name}_upper`], upper_y: base_pos.upper_y, - lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`], + lower_x: base_pos.x + x_pos[`${this.config.view_mode.name}_lower`], lower_y: base_pos.lower_y, }; } @@ -1098,9 +826,9 @@ export default class Gantt { date_utils.diff(date, this.gantt_start, 'hour') + 24; const scroll_pos = - (hours_before_first_task / this.options.step) * - this.options.column_width - - this.options.column_width; + (hours_before_first_task / this.config.step) * + this.config.column_width - + this.config.column_width; parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' }); } @@ -1137,7 +865,6 @@ export default class Gantt { $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => { const bar_wrapper = $.closest('.bar-wrapper', element); bars.forEach((bar) => bar.group.classList.remove('active')); - if (element.classList.contains('left')) { is_resizing_left = true; } else if (element.classList.contains('right')) { @@ -1187,13 +914,13 @@ export default class Gantt { } const daysSinceStart = - ((e.currentTarget.scrollLeft / this.options.column_width) * - this.options.step) / + ((e.currentTarget.scrollLeft / this.config.column_width) * + this.config.step) / 24; let format_str = 'D MMM'; - if (['Year', 'Month'].includes(this.options.view_mode)) + if (['Year', 'Month'].includes(this.config.view_mode.name)) format_str = 'YYYY'; - else if (['Day', 'Week'].includes(this.options.view_mode)) + else if (['Day', 'Week'].includes(this.config.view_mode.name)) format_str = 'MMMM'; else if (this.view_is('Half Day')) format_str = 'D'; else if (this.view_is('Hour')) format_str = 'D MMMM'; @@ -1310,7 +1037,6 @@ export default class Gantt { is_resizing = true; x_on_start = e.offsetX || e.layerX; y_on_start = e.offsetY || e.layerY; - console.log(e, handle); const $bar_wrapper = $.closest('.bar-wrapper', handle); const id = $bar_wrapper.getAttribute('data-id'); @@ -1328,12 +1054,6 @@ export default class Gantt { $.on(this.$svg, 'mousemove', (e) => { if (!is_resizing) return; let dx = (e.offsetX || e.layerX) - x_on_start; - console.log( - dx, - $bar_progress.getWidth(), - $bar_progress.min_dx, - $bar_progress.max_dx, - ); if (dx > $bar_progress.max_dx) { dx = $bar_progress.max_dx; } @@ -1382,29 +1102,29 @@ export default class Gantt { position; if (this.view_is(VIEW_MODE.WEEK)) { - rem = dx % (this.options.column_width / 7); + rem = dx % (this.config.column_width / 7); position = odx - rem + - (rem < this.options.column_width / 14 + (rem < this.config.column_width / 14 ? 0 - : this.options.column_width / 7); + : this.config.column_width / 7); } else if (this.view_is(VIEW_MODE.MONTH)) { - rem = dx % (this.options.column_width / 30); + rem = dx % (this.config.column_width / 30); position = odx - rem + - (rem < this.options.column_width / 60 + (rem < this.config.column_width / 60 ? 0 - : this.options.column_width / 30); + : this.config.column_width / 30); } else { - rem = dx % this.options.column_width; + rem = dx % this.config.column_width; position = odx - rem + - (rem < this.options.column_width / 2 + (rem < this.config.column_width / 2 ? 0 - : this.options.column_width); + : this.config.column_width); } return position; } @@ -1418,11 +1138,11 @@ export default class Gantt { view_is(modes) { if (typeof modes === 'string') { - return this.options.view_mode === modes; + return this.config.view_mode.name === modes; } if (Array.isArray(modes)) { - return modes.some((mode) => this.options.view_mode === mode); + return modes.some((mode) => this.config.view_mode.name === mode); } return false; From 2eaa127c5b3f4902dea22f0234b07cb8106451a0 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 11:28:48 +0530 Subject: [PATCH 02/13] fix date calculation bugs --- index.html | 6 +++--- src/bar.js | 15 ++++++++++----- src/date_utils.js | 31 +++++++++++++++++-------------- src/index.js | 3 ++- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/index.html b/index.html index b8643569..69468e83 100644 --- a/index.html +++ b/index.html @@ -68,8 +68,8 @@

dependencies: 'Task 2', }, { - start: '2024-04-08', - end: '2024-04-10', + start: '2024-03-08', + end: '2024-05-10', name: 'Deploy', id: 'Task 4', progress: 0, @@ -108,7 +108,7 @@

// on_hover (task, x, y) { // console.log("Hover", x, y); // } - view_mode: 'Day', + view_mode: 'Month', // view_modes: [ // { // name: 'Custom Day', diff --git a/src/bar.js b/src/bar.js index 9f5b542c..f9680720 100644 --- a/src/bar.js +++ b/src/bar.js @@ -505,11 +505,9 @@ export default class Bar { const task_start = this.task._start; const gantt_start = this.gantt.gantt_start; - const diff = date_utils.diff( - task_start, - gantt_start, - this.gantt.config.unit, - ); + const diff = + date_utils.diff(task_start, gantt_start, this.gantt.config.unit) / + this.gantt.config.step; let x = diff * column_width; /* Since the column width is based on 30, @@ -540,6 +538,13 @@ export default class Bar { } compute_duration() { + console.log( + date_utils.diff( + this.task._end, + this.task._start, + this.gantt.config.unit, + ), + ); this.duration = date_utils.diff( this.task._end, diff --git a/src/date_utils.js b/src/date_utils.js index 0dc6e36b..2bc7c1bc 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -122,7 +122,7 @@ export default { return str; }, - diff(date_a, date_b, scale = DAY) { + diff(date_a, date_b, scale = 'day') { let milliseconds, seconds, hours, minutes, days, months, years; milliseconds = date_a - date_b; @@ -131,13 +131,14 @@ export default { hours = minutes / 60; days = hours / 24; // Calculate months across years - const yearDiff = date_a.getFullYear() - date_b.getFullYear(); - const monthDiff = date_a.getMonth() - date_b.getMonth(); + let yearDiff = date_a.getFullYear() - date_b.getFullYear(); + let monthDiff = date_a.getMonth() - date_b.getMonth(); + // calculate extra + monthDiff += (days % 30) / 30; /* If monthDiff is negative, date_b is in an earlier month than date_a and thus subtracted from the year difference in months */ months = yearDiff * 12 + monthDiff; - /* If date_a's (e.g. march 1st) day of the month is smaller than date_b (e.g. february 28th), adjust the month difference */ if (date_a.getDate() < date_b.getDate()) { @@ -151,16 +152,18 @@ export default { scale += 's'; } - return Math.floor( - { - milliseconds, - seconds, - minutes, - hours, - days, - months, - years, - }[scale], + return ( + Math.round( + { + milliseconds, + seconds, + minutes, + hours, + days, + months, + years, + }[scale] * 100, + ) / 100 ); }, diff --git a/src/index.js b/src/index.js index b09ee771..eda07807 100644 --- a/src/index.js +++ b/src/index.js @@ -349,6 +349,7 @@ export default class Gantt { class: 'grid-row', append_to: rows_layer, }); + // FIX if ( this.options.lines === 'both' || this.options.lines === 'horizontal' @@ -750,7 +751,7 @@ export default class Gantt { ? date_utils.format(date, upper_text, this.options.language) : upper_text(date, last_date, this.options.language), lower_text: - typeof upper_text === 'string' + typeof lower_text === 'string' ? date_utils.format(date, lower_text, this.options.language) : lower_text(date, last_date, this.options.language), upper_x: base_pos.x + x_pos[`${this.config.view_mode.name}_upper`], From 8c526b5ed633eb7e0459daedb6783a1d6e769bad Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 11:52:44 +0530 Subject: [PATCH 03/13] fix highlighting bugs --- src/index.js | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/index.js b/src/index.js index eda07807..b7201cfd 100644 --- a/src/index.js +++ b/src/index.js @@ -201,7 +201,8 @@ export default class Gantt { let { duration, scale } = date_utils.parse_duration(mode.step); this.config.step = duration; this.config.unit = scale; - this.config.column_width = mode.column_width || 38; + this.config.column_width = + mode.column_width || this.options.column_width; } setup_dates() { @@ -526,7 +527,6 @@ export default class Gantt { class: tick_class, append_to: this.layers.grid, }); - if (this.view_is(VIEW_MODE.MONTH)) { tick_x += (date_utils.get_days_in_month(date) * @@ -547,7 +547,7 @@ export default class Gantt { ) { if (d.getDay() === 0 || d.getDay() === 6) { const x = - (date_utils.diff(d, this.gantt_start, 'hour') / + (date_utils.diff(d, this.gantt_start, this.config.unit) / this.config.step) * this.config.column_width; const height = @@ -573,19 +573,19 @@ 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. */ computeGridHighlightDimensions(view_mode) { - const todayDate = new Date(); - if (todayDate < this.gantt_start || todayDate > this.gantt_end) - return null; - - let x = this.config.column_width / 2; + const today = new Date(); + if (today < this.gantt_start || today > this.gantt_end) return null; if (this.view_is(VIEW_MODE.DAY)) { + let diff_in_units = date_utils.diff( + today, + this.gantt_start, + this.config.unit, + ); return { x: - x + - (date_utils.diff(today, this.gantt_start, 'hour') / - this.config.step) * - this.config.column_width, + (diff_in_units / this.config.step) * + this.config.column_width, date: today, }; } @@ -631,7 +631,6 @@ export default class Gantt { ); if (!highlightDimensions) return; const { x: left, date } = highlightDimensions; - if (!this.dates.find((d) => d.getTime() == date.getTime())) return; const top = this.options.header_height + this.options.padding / 2; const height = (this.options.bar_height + this.options.padding) * @@ -819,18 +818,19 @@ export default class Gantt { } else if (typeof date === 'string') { date = date_utils.parse(date); } - const parent_element = this.$svg.parentElement; if (!parent_element) return; - - const hours_before_first_task = - date_utils.diff(date, this.gantt_start, 'hour') + 24; - + const units_since_first_task = date_utils.diff( + date, + this.gantt_start, + this.config.unit, + ); const scroll_pos = - (hours_before_first_task / this.config.step) * + (units_since_first_task / this.config.step) * this.config.column_width - this.config.column_width; - parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' }); + console.log(scroll_pos); + parent_element.scrollTo({ left: 400, behavior: 'smooth' }); } scroll_today() { @@ -1143,10 +1143,10 @@ export default class Gantt { } if (Array.isArray(modes)) { - return modes.some((mode) => this.config.view_mode.name === mode); + return modes.some(view_is); } - return false; + return this.config.view_mode.name === modes.name; } get_task(id) { From c13c0cde4d670abeb04d6c9c45a6f91fc0c27ebb Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 12:21:57 +0530 Subject: [PATCH 04/13] feat: snap_by_day option --- src/bar.js | 57 ++++++++++++++++++++++--------------------------- src/defaults.js | 1 + src/index.js | 53 +++++++++++++++++++-------------------------- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/src/bar.js b/src/bar.js index f9680720..e57f8620 100644 --- a/src/bar.js +++ b/src/bar.js @@ -538,13 +538,6 @@ export default class Bar { } compute_duration() { - console.log( - date_utils.diff( - this.task._end, - this.task._start, - this.gantt.config.unit, - ), - ); this.duration = date_utils.diff( this.task._end, @@ -558,31 +551,31 @@ export default class Bar { rem, position; - if (this.gantt.view_is('Week')) { - rem = dx % (this.gantt.config.column_width / 7); - position = - odx - - rem + - (rem < this.gantt.config.column_width / 14 - ? 0 - : this.gantt.config.column_width / 7); - } else if (this.gantt.view_is('Month')) { - rem = dx % (this.gantt.config.column_width / 30); - position = - odx - - rem + - (rem < this.gantt.config.column_width / 60 - ? 0 - : this.gantt.config.column_width / 30); - } else { - rem = dx % this.gantt.config.column_width; - position = - odx - - rem + - (rem < this.gantt.config.column_width / 2 - ? 0 - : this.gantt.config.column_width); - } + // if (this.gantt.view_is('Week')) { + // rem = dx % (this.gantt.config.column_width / 7); + // position = + // odx - + // rem + + // (rem < this.gantt.config.column_width / 14 + // ? 0 + // : this.gantt.config.column_width / 7); + // } else if (this.gantt.view_is('Month')) { + // rem = dx % (this.gantt.config.column_width / 30); + // position = + // odx - + // rem + + // (rem < this.gantt.config.column_width / 60 + // ? 0 + // : this.gantt.config.column_width / 30); + // } else { + rem = dx % this.gantt.config.column_width; + position = + odx - + rem + + (rem < this.gantt.config.column_width / 2 + ? 0 + : this.gantt.config.column_width); + // } return position; } diff --git a/src/defaults.js b/src/defaults.js index 0c8d1829..f96397ad 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -110,6 +110,7 @@ const DEFAULT_OPTIONS = { auto_move_label: true, today_button: true, view_mode_select: false, + snap_by_day: false, }; export { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES }; diff --git a/src/index.js b/src/index.js index b7201cfd..670fca7e 100644 --- a/src/index.js +++ b/src/index.js @@ -575,7 +575,6 @@ export default class Gantt { computeGridHighlightDimensions(view_mode) { const today = new Date(); if (today < this.gantt_start || today > this.gantt_end) return null; - if (this.view_is(VIEW_MODE.DAY)) { let diff_in_units = date_utils.diff( today, @@ -590,18 +589,19 @@ export default class Gantt { }; } + let x = 0; for (let date of this.dates) { const todayDate = new Date(); const startDate = new Date(date); const endDate = new Date(date); - switch (view_mode) { - case VIEW_MODE.WEEK: + switch (view_mode.name) { + case VIEW_MODE.WEEK.name: endDate.setDate(date.getDate() + 7); break; - case VIEW_MODE.MONTH: + case VIEW_MODE.MONTH.name: endDate.setMonth(date.getMonth() + 1); break; - case VIEW_MODE.YEAR: + case VIEW_MODE.YEAR.name: endDate.setFullYear(date.getFullYear() + 1); break; } @@ -829,7 +829,6 @@ export default class Gantt { (units_since_first_task / this.config.step) * this.config.column_width - this.config.column_width; - console.log(scroll_pos); parent_element.scrollTo({ left: 400, behavior: 'smooth' }); } @@ -1101,32 +1100,24 @@ export default class Gantt { let odx = dx, rem, position; - - if (this.view_is(VIEW_MODE.WEEK)) { - rem = dx % (this.config.column_width / 7); - position = - odx - - rem + - (rem < this.config.column_width / 14 - ? 0 - : this.config.column_width / 7); - } else if (this.view_is(VIEW_MODE.MONTH)) { - rem = dx % (this.config.column_width / 30); - position = - odx - - rem + - (rem < this.config.column_width / 60 - ? 0 - : this.config.column_width / 30); - } else { - rem = dx % this.config.column_width; - position = - odx - - rem + - (rem < this.config.column_width / 2 - ? 0 - : this.config.column_width); + let unit_length = 1; + if (this.options.snap_by_day) { + const { duration, scale } = date_utils.parse_duration( + this.config.view_mode.step, + ); + unit_length = + duration * + ({ hour: 1 / 24, week: 7, month: 30, year: 365 }[scale] || 1); } + + rem = dx % (this.config.column_width / unit_length); + position = + odx - + rem + + (rem < this.config.column_width / unit_length / 2 + ? 0 + : this.config.column_width / unit_length); + return position; } From fc71da6550ea753494eb3a1b13fe3e8dede4ff04 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 12:51:34 +0530 Subject: [PATCH 05/13] remove VIEW_MODE usages, fix bugs --- src/date_utils.js | 4 ++ src/defaults.js | 4 ++ src/index.js | 158 +++++++++++++++++----------------------------- 3 files changed, 66 insertions(+), 100 deletions(-) diff --git a/src/date_utils.js b/src/date_utils.js index 2bc7c1bc..572fb94c 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -251,6 +251,10 @@ export default { } return 28; }, + + get_days_in_year(date) { + return date.getFullYear() % 4 ? 365 : 366; + }, }; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart diff --git a/src/defaults.js b/src/defaults.js index f96397ad..6b1b42a4 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -38,6 +38,7 @@ const DEFAULT_VIEW_MODES = [ { name: 'Day', padding: '14d', + format_string: 'YYYY-MM-DD', step: '1d', lower_text: (d, ld, lang) => d.getDate() !== ld.getDate() ? date_utils.format(d, 'D', lang) : '', @@ -45,6 +46,7 @@ const DEFAULT_VIEW_MODES = [ d.getMonth() !== ld.getMonth() ? date_utils.format(d, 'MMMM', lang) : '', + thick_line: (d) => d.getDay() === 1, }, { name: 'Week', @@ -59,6 +61,7 @@ const DEFAULT_VIEW_MODES = [ d.getMonth() !== ld.getMonth() ? date_utils.format(d, 'MMMM', lang) : '', + thick_line: (d) => d.getDate() >= 1 && d.getDate() <= 7, }, { name: 'Month', @@ -71,6 +74,7 @@ const DEFAULT_VIEW_MODES = [ d.getMonth() !== ld.getMonth() ? date_utils.format(d, 'YYYY', lang) : '', + thick_line: (d) => d.getMonth() % 3 === 0, }, { name: 'Year', diff --git a/src/index.js b/src/index.js index 670fca7e..ab39db09 100644 --- a/src/index.js +++ b/src/index.js @@ -9,16 +9,6 @@ import { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES } from './defaults'; import './gantt.css'; -const VIEW_MODE = { - HOUR: DEFAULT_VIEW_MODES[0], - QUARTER_DAY: DEFAULT_VIEW_MODES[1], - HALF_DAY: DEFAULT_VIEW_MODES[2], - DAY: DEFAULT_VIEW_MODES[3], - WEEK: DEFAULT_VIEW_MODES[4], - MONTH: DEFAULT_VIEW_MODES[5], - YEAR: DEFAULT_VIEW_MODES[6], -}; - export default class Gantt { constructor(wrapper, tasks, options) { this.setup_wrapper(wrapper); @@ -398,10 +388,10 @@ export default class Gantt { $el.textContent = 'Mode'; $select.appendChild($el); - for (const key in VIEW_MODE) { + for (const mode of this.options.view_modes) { const $option = document.createElement('option'); - $option.value = VIEW_MODE[key]; - $option.textContent = VIEW_MODE[key]; + $option.value = mode.name; + $option.textContent = mode.name; $select.appendChild($option); } @@ -473,8 +463,7 @@ export default class Gantt { } make_grid_ticks() { - if (!['both', 'vertical', 'horizontal'].includes(this.options.lines)) - return; + if (this.options.lines === 'none') return; let tick_x = 0; let tick_y = this.options.header_height + this.options.padding / 2; let tick_height = @@ -504,34 +493,32 @@ export default class Gantt { } } if (this.options.lines === 'horizontal') return; + for (let date of this.dates) { let tick_class = 'tick'; - // thick tick for monday - if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) { - tick_class += ' thick'; - } - // thick tick for first week if ( - this.view_is(VIEW_MODE.WEEK) && - date.getDate() >= 1 && - date.getDate() < 8 + this.config.view_mode.thick_line && + this.config.view_mode.thick_line(date) ) { tick_class += ' thick'; } - // thick ticks for quarters - if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) { - tick_class += ' thick'; - } + createSVG('path', { d: `M ${tick_x} ${tick_y} v ${tick_height}`, class: tick_class, append_to: this.layers.grid, }); - if (this.view_is(VIEW_MODE.MONTH)) { + + if (this.view_is('month')) { tick_x += (date_utils.get_days_in_month(date) * this.config.column_width) / 30; + } else if (this.view_is('year')) { + tick_x += + (date_utils.get_days_in_year(date) * + this.config.column_width) / + 365; } else { tick_x += this.config.column_width; } @@ -539,6 +526,7 @@ export default class Gantt { } highlightWeekends() { + // FIX if (!this.view_is('Day') && !this.view_is('Half Day')) return; for ( let d = new Date(this.gantt_start); @@ -575,81 +563,41 @@ export default class Gantt { computeGridHighlightDimensions(view_mode) { const today = new Date(); if (today < this.gantt_start || today > this.gantt_end) return null; - if (this.view_is(VIEW_MODE.DAY)) { - let diff_in_units = date_utils.diff( - today, - this.gantt_start, - this.config.unit, - ); - return { - x: - (diff_in_units / this.config.step) * - this.config.column_width, - date: today, - }; - } - - let x = 0; - for (let date of this.dates) { - const todayDate = new Date(); - const startDate = new Date(date); - const endDate = new Date(date); - switch (view_mode.name) { - case VIEW_MODE.WEEK.name: - endDate.setDate(date.getDate() + 7); - break; - case VIEW_MODE.MONTH.name: - endDate.setMonth(date.getMonth() + 1); - break; - case VIEW_MODE.YEAR.name: - endDate.setFullYear(date.getFullYear() + 1); - break; - } - if (todayDate >= startDate && todayDate <= endDate) { - return { x, date: startDate }; - } else { - x += this.config.column_width; - } - } - - return { x }; + let diff_in_units = date_utils.diff( + today, + this.gantt_start, + this.config.unit, + ); + return { + x: (diff_in_units / this.config.step) * this.config.column_width, + date: date_utils.format(today, this.config.view_mode.format_string), + }; } make_grid_highlights() { if (this.options.highlight_weekend) this.highlightWeekends(); - // highlight today's | week's | month's | year's - if ( - this.view_is(VIEW_MODE.DAY) || - this.view_is(VIEW_MODE.WEEK) || - this.view_is(VIEW_MODE.MONTH) || - this.view_is(VIEW_MODE.YEAR) - ) { - // Used as we must find the _end_ of session if view is not Day - const highlightDimensions = this.computeGridHighlightDimensions( - this.config.view_mode, - ); - if (!highlightDimensions) return; - const { x: left, date } = highlightDimensions; - const top = this.options.header_height + this.options.padding / 2; - const height = - (this.options.bar_height + this.options.padding) * - this.tasks.length; - this.$current_highlight = this.create_el({ - top, - left, - height, - classes: 'current-highlight', - append_to: this.$container, - }); - let $today = document.getElementById( - date_utils.format(date).replaceAll(' ', '_'), - ); - if ($today) { - $today.classList.add('current-date-highlight'); - $today.style.top = +$today.style.top.slice(0, -2) - 4 + 'px'; - $today.style.left = +$today.style.left.slice(0, -2) - 8 + 'px'; - } + const highlightDimensions = this.computeGridHighlightDimensions( + this.config.view_mode, + ); + if (!highlightDimensions) return; + const { x: left, date } = highlightDimensions; + + const top = this.options.header_height + this.options.padding / 2; + const height = + (this.options.bar_height + this.options.padding) * + this.tasks.length; + this.$current_highlight = this.create_el({ + top, + left, + height, + classes: 'current-highlight', + append_to: this.$container, + }); + let $today = document.getElementById(date.replaceAll(' ', '_')); + if ($today) { + $today.classList.add('current-date-highlight'); + $today.style.top = +$today.style.top.slice(0, -2) - 4 + 'px'; } } @@ -742,7 +690,9 @@ export default class Gantt { return { date, - formatted_date: date_utils.format(date).replaceAll(' ', '_'), + formatted_date: date_utils + .format(date, this.config.view_mode.format_string) + .replaceAll(' ', '_'), column_width: this.config.column_width, base_pos_x: base_pos.x, upper_text: @@ -1198,7 +1148,15 @@ export default class Gantt { } } -Gantt.VIEW_MODE = VIEW_MODE; +Gantt.VIEW_MODE = { + HOUR: DEFAULT_VIEW_MODES[0], + QUARTER_DAY: DEFAULT_VIEW_MODES[1], + HALF_DAY: DEFAULT_VIEW_MODES[2], + DAY: DEFAULT_VIEW_MODES[3], + WEEK: DEFAULT_VIEW_MODES[4], + MONTH: DEFAULT_VIEW_MODES[5], + YEAR: DEFAULT_VIEW_MODES[6], +}; function generate_id(task) { return task.name + '_' + Math.random().toString(36).slice(2, 12); From 7ac54229500ed6fe1cd2c5d004a87a1824419153 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 13:07:05 +0530 Subject: [PATCH 06/13] more simplification --- src/defaults.js | 5 +++++ src/index.js | 29 +++++++++-------------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/defaults.js b/src/defaults.js index 6b1b42a4..4b1d9a22 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -10,6 +10,7 @@ const DEFAULT_VIEW_MODES = [ d.getDate() !== ld.getDate() ? date_utils.format(d, 'D MMMM', lang) : '', + upper_text_frequency: 24, }, { name: 'Quarter Day', @@ -21,6 +22,7 @@ const DEFAULT_VIEW_MODES = [ d.getDate() !== ld.getDate() ? date_utils.format(d, 'D MMM', lang) : '', + upper_text_frequency: 4, }, { name: 'Half Day', @@ -34,6 +36,7 @@ const DEFAULT_VIEW_MODES = [ ? date_utils.format(d, 'D MMM', lang) : date_utils.format(d, 'D', lang) : '', + upper_text_frequency: 2, }, { name: 'Day', @@ -62,6 +65,7 @@ const DEFAULT_VIEW_MODES = [ ? date_utils.format(d, 'MMMM', lang) : '', thick_line: (d) => d.getDate() >= 1 && d.getDate() <= 7, + upper_text_frequency: 4, }, { name: 'Month', @@ -87,6 +91,7 @@ const DEFAULT_VIEW_MODES = [ d.getMonth() !== ld.getMonth() ? date_utils.format(d, 'YYYY', lang) : '', + upper_text_frequency: 30, }, ]; diff --git a/src/index.js b/src/index.js index ab39db09..f3ef5368 100644 --- a/src/index.js +++ b/src/index.js @@ -669,24 +669,9 @@ export default class Gantt { lower_y: this.options.header_height - 20, upper_y: this.options.header_height - 50, }; - const x_pos = { - Hour_lower: column_width / 2, - Hour_upper: column_width * 12, - 'Quarter Day_lower': column_width / 2, - 'Quarter Day_upper': column_width * 2, - 'Half Day_lower': column_width / 2, - 'Half Day_upper': column_width, - Day_lower: column_width / 2, - Day_upper: column_width / 2, - Week_lower: column_width / 2, - Week_upper: (column_width * 4) / 2, - Month_lower: column_width / 2, - Month_upper: column_width / 2, - Year_lower: column_width / 2, - Year_upper: (column_width * 30) / 2, - }; - let upper_text = this.config.view_mode.upper_text; - let lower_text = this.config.view_mode.lower_text; + + const upper_text = this.config.view_mode.upper_text; + const lower_text = this.config.view_mode.lower_text; return { date, @@ -703,9 +688,13 @@ export default class Gantt { typeof lower_text === 'string' ? date_utils.format(date, lower_text, this.options.language) : lower_text(date, last_date, this.options.language), - upper_x: base_pos.x + x_pos[`${this.config.view_mode.name}_upper`], + upper_x: + base_pos.x + + (column_width * this.config.view_mode.upper_text_frequency || + 1) / + 2, upper_y: base_pos.upper_y, - lower_x: base_pos.x + x_pos[`${this.config.view_mode.name}_lower`], + lower_x: base_pos.x + column_width / 2, lower_y: base_pos.lower_y, }; } From 3519755dc355a526e5375cf6208fa7a20ad28210 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 14:34:11 +0530 Subject: [PATCH 07/13] improve date handling and fix empty tasks error --- src/index.js | 140 +++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/src/index.js b/src/index.js index f3ef5368..b9200320 100644 --- a/src/index.js +++ b/src/index.js @@ -79,85 +79,81 @@ export default class Gantt { setup_tasks(tasks) { // prepare tasks - this.tasks = tasks.map((task, i) => { - // convert to Date objects - task._start = date_utils.parse(task.start); - if (task.end === undefined && task.duration !== undefined) { - task.end = task._start; - let durations = task.duration.split(' '); - - durations.forEach((tmpDuration) => { - let { duration, scale } = - date_utils.parse_duration(tmpDuration); - task.end = date_utils.add(task.end, duration, scale); - }); - } - task._end = date_utils.parse(task.end); - let diff = date_utils.diff(task._end, task._start, 'year'); - if (diff < 0) { - throw Error( - "start of task can't be after end of task: in task #, " + - (i + 1), - ); - } - // make task invalid if duration too large - if (date_utils.diff(task._end, task._start, 'year') > 10) { - task.end = null; - } + this.tasks = tasks + .map((task, i) => { + // invalid flag + if (!task.start || !task.end) { + console.error(`task "${task.id}" doesn't have valid dates`); + return false; + } - // cache index - task._index = i; + // convert to Date objects + task._start = date_utils.parse(task.start); + if (task.end === undefined && task.duration !== undefined) { + task.end = task._start; + let durations = task.duration.split(' '); - // invalid dates - if (!task.start && !task.end) { - const today = date_utils.today(); - task._start = today; - task._end = date_utils.add(today, 2, 'day'); - } + durations.forEach((tmpDuration) => { + let { duration, scale } = + date_utils.parse_duration(tmpDuration); + task.end = date_utils.add(task.end, duration, scale); + }); + } + task._end = date_utils.parse(task.end); - if (!task.start && task.end) { - task._start = date_utils.add(task._end, -2, 'day'); - } + let diff = date_utils.diff(task._end, task._start, 'year'); + if (diff < 0) { + console.error( + `start of task can't be after end of task: in task "${task.id}"`, + ); + return false; + } - if (task.start && !task.end) { - task._end = date_utils.add(task._start, 2, 'day'); - } + // make task invalid if duration too large + if (date_utils.diff(task._end, task._start, 'year') > 10) { + console.error( + `the duration of task "${task.id}" is too long (above ten years)`, + ); + return false; + } - // if hours is not set, assume the last day is full day - // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 - const task_end_values = date_utils.get_date_values(task._end); - if (task_end_values.slice(3).every((d) => d === 0)) { - task._end = date_utils.add(task._end, 24, 'hour'); - } + // cache index + task._index = i; - // invalid flag - if (!task.start || !task.end) { - task.invalid = true; - } + // if hours is not set, assume the last day is full day + // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 + const task_end_values = date_utils.get_date_values(task._end); + if (task_end_values.slice(3).every((d) => d === 0)) { + task._end = date_utils.add(task._end, 24, 'hour'); + } - // dependencies - if (typeof task.dependencies === 'string' || !task.dependencies) { - let deps = []; - if (task.dependencies) { - deps = task.dependencies - .split(',') - .map((d) => d.trim().replaceAll(' ', '_')) - .filter((d) => d); + // dependencies + if ( + typeof task.dependencies === 'string' || + !task.dependencies + ) { + let deps = []; + if (task.dependencies) { + deps = task.dependencies + .split(',') + .map((d) => d.trim().replaceAll(' ', '_')) + .filter((d) => d); + } + task.dependencies = deps; } - task.dependencies = deps; - } - // uids - if (!task.id) { - task.id = generate_id(task); - } else if (typeof task.id === 'string') { - task.id = task.id.replaceAll(' ', '_'); - } else { - task.id = `${task.id}`; - } + // uids + if (!task.id) { + task.id = generate_id(task); + } else if (typeof task.id === 'string') { + task.id = task.id.replaceAll(' ', '_'); + } else { + task.id = `${task.id}`; + } - return task; - }); + return task; + }) + .filter((t) => t); this.setup_dependencies(); } @@ -201,8 +197,12 @@ export default class Gantt { } setup_gantt_dates() { - // set global start and end date let gantt_start, gantt_end; + if (!this.tasks.length) { + gantt_start = new Date(); + gantt_end = new Date(); + } + for (let task of this.tasks) { if (!gantt_start || task._start < gantt_start) { gantt_start = task._start; From d7fb48031afe834ccc2b4f383baacd1ff356a13b Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 14:52:15 +0530 Subject: [PATCH 08/13] chore: format --- src/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index b9200320..7c3650a6 100644 --- a/src/index.js +++ b/src/index.js @@ -670,8 +670,10 @@ export default class Gantt { upper_y: this.options.header_height - 50, }; - const upper_text = this.config.view_mode.upper_text; - const lower_text = this.config.view_mode.lower_text; + let upper_text = this.config.view_mode.upper_text; + let lower_text = this.config.view_mode.lower_text; + if (!upper_text) upper_text = () => ''; + if (!lower_text) lower_text = () => ''; return { date, From 8152f5ad173f0a9ebf4cd6763d4fc2b24087c5e4 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 15:43:53 +0530 Subject: [PATCH 09/13] fix: all format uses lang --- src/bar.js | 6 +++++- src/index.js | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/bar.js b/src/bar.js index e57f8620..7f52bb63 100644 --- a/src/bar.js +++ b/src/bar.js @@ -520,7 +520,11 @@ export default class Bar { date_utils.diff(task_start, gantt_start, 'month') * 30; const dayInMonth = Math.min( 29, - date_utils.format(task_start, 'DD'), + date_utils.format( + task_start, + 'DD', + this.gantt.options.language, + ), ); const diff = diffDaysBasedOn30DayMonths + dayInMonth; diff --git a/src/index.js b/src/index.js index 7c3650a6..de6044f2 100644 --- a/src/index.js +++ b/src/index.js @@ -235,7 +235,11 @@ export default class Gantt { this.config.view_mode.format_string || 'YYYY-MM-DD HH'; this.gantt_start = date_utils.parse( - date_utils.format(gantt_start, format_string), + date_utils.format( + gantt_start, + format_string, + this.options.language, + ), ); this.gantt_start.setHours(0, 0, 0, 0); this.gantt_end = date_utils.add( @@ -570,7 +574,11 @@ export default class Gantt { ); return { x: (diff_in_units / this.config.step) * this.config.column_width, - date: date_utils.format(today, this.config.view_mode.format_string), + date: date_utils.format( + today, + this.config.view_mode.format_string, + this.options.language, + ), }; } @@ -869,6 +877,7 @@ export default class Gantt { let currentUpper = date_utils.format( date_utils.add(this.gantt_start, daysSinceStart, 'day'), format_str, + this.options.language, ); const upperTexts = Array.from( document.querySelectorAll('.upper-text'), From d87022eb3fb0daabe172dd1d3e87f05b50122dcc Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 15:53:50 +0530 Subject: [PATCH 10/13] modify gitignore --- .gitignore | 1 + src/index.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 14af5267..faae2ff3 100755 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ node_modules .DS_Store gh-pages +feedback.md diff --git a/src/index.js b/src/index.js index de6044f2..10c83039 100644 --- a/src/index.js +++ b/src/index.js @@ -81,13 +81,13 @@ export default class Gantt { // prepare tasks this.tasks = tasks .map((task, i) => { - // invalid flag - if (!task.start || !task.end) { - console.error(`task "${task.id}" doesn't have valid dates`); + if (!task.start) { + console.error( + `task "${task.id}" doesn't have a start date`, + ); return false; } - // convert to Date objects task._start = date_utils.parse(task.start); if (task.end === undefined && task.duration !== undefined) { task.end = task._start; @@ -99,6 +99,10 @@ export default class Gantt { task.end = date_utils.add(task.end, duration, scale); }); } + if (!task.end) { + console.error(`task "${task.id}" doesn't have an end date`); + return false; + } task._end = date_utils.parse(task.end); let diff = date_utils.diff(task._end, task._start, 'year'); From 50f9c2ca13cf013329947c9fe000a8d5e61db3d4 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 17:36:40 +0530 Subject: [PATCH 11/13] configurable snapping --- src/date_utils.js | 15 +++++++++++++++ src/defaults.js | 4 +++- src/gantt.css | 7 ++++--- src/index.js | 17 +++++++++-------- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/date_utils.js b/src/date_utils.js index 572fb94c..f0526bf6 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -235,6 +235,21 @@ export default { ]; }, + convert_scales(period, to_scale) { + const TO_DAYS = { + millisecond: 1 / 60 / 60 / 24 / 1000, + second: 1 / 60 / 60 / 24, + minute: 1 / 60 / 24, + hour: 1 / 24, + day: 1, + month: 30, + year: 365, + }; + const { duration, scale } = this.parse_duration(period); + let in_days = duration * TO_DAYS[scale]; + return in_days / TO_DAYS[to_scale]; + }, + get_days_in_month(date) { const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; diff --git a/src/defaults.js b/src/defaults.js index 4b1d9a22..60a5a097 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -79,6 +79,7 @@ const DEFAULT_VIEW_MODES = [ ? date_utils.format(d, 'YYYY', lang) : '', thick_line: (d) => d.getMonth() % 3 === 0, + default_snap: '7d', }, { name: 'Year', @@ -92,6 +93,7 @@ const DEFAULT_VIEW_MODES = [ ? date_utils.format(d, 'YYYY', lang) : '', upper_text_frequency: 30, + default_snap: '1m', }, ]; @@ -119,7 +121,7 @@ const DEFAULT_OPTIONS = { auto_move_label: true, today_button: true, view_mode_select: false, - snap_by_day: false, + default_snap: '1d', }; export { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES }; diff --git a/src/gantt.css b/src/gantt.css index ad428382..f644095d 100644 --- a/src/gantt.css +++ b/src/gantt.css @@ -10,10 +10,10 @@ --light-border-color: #ebeff2; --light-yellow: #f6e796; --holiday-color: #f9fafa; - --text-muted: #666; + --text-muted: #7c7c7c; --text-grey: #98a1a9; --text-light: #fff; - --text-dark: #111; + --text-dark: #171717; --progress: #ebeef0; --handle-color: #dcdce4; --handle-color-important: #94c4f4; @@ -74,7 +74,6 @@ & .lower-text, & .upper-text { text-anchor: middle; - color: var(--text-dark); } & .upper-header { @@ -90,6 +89,7 @@ position: absolute; width: fit-content; transform: translateX(-50%); + color: var(--text-muted); } & .upper-text { @@ -97,6 +97,7 @@ width: fit-content; font-weight: 500; font-size: 16px; + color: var(--text-dark); } & .current-upper { diff --git a/src/index.js b/src/index.js index 10c83039..fcfc0283 100644 --- a/src/index.js +++ b/src/index.js @@ -1054,24 +1054,25 @@ export default class Gantt { let odx = dx, rem, position; + let unit_length = 1; - if (this.options.snap_by_day) { - const { duration, scale } = date_utils.parse_duration( - this.config.view_mode.step, - ); + const default_snap = + this.config.view_mode.default_snap || this.options.default_snap; + if (default_snap !== 'unit') { + const { duration, scale } = date_utils.parse_duration(default_snap); unit_length = - duration * - ({ hour: 1 / 24, week: 7, month: 30, year: 365 }[scale] || 1); + date_utils.convert_scales(this.config.view_mode.step, scale) / + duration; } rem = dx % (this.config.column_width / unit_length); + position = odx - rem + - (rem < this.config.column_width / unit_length / 2 + (rem < (this.config.column_width / unit_length) * 2 ? 0 : this.config.column_width / unit_length); - return position; } From e20c7e0b6b0b46997c08e8a3f6e65d4e74f42617 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 17:41:18 +0530 Subject: [PATCH 12/13] fix disappearing text bug --- src/defaults.js | 2 +- src/gantt.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/defaults.js b/src/defaults.js index 60a5a097..94406456 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -93,7 +93,7 @@ const DEFAULT_VIEW_MODES = [ ? date_utils.format(d, 'YYYY', lang) : '', upper_text_frequency: 30, - default_snap: '1m', + default_snap: '30d', }, ]; diff --git a/src/gantt.css b/src/gantt.css index f644095d..2fa33285 100644 --- a/src/gantt.css +++ b/src/gantt.css @@ -246,6 +246,10 @@ & .bar-label { fill: var(--text-light); + + &.big { + fill: var(--text-dark); + } } & .handle { From 268d82ad355c5237eabb5166ff1f7cd069d76075 Mon Sep 17 00:00:00 2001 From: safwansamsudeen Date: Mon, 2 Dec 2024 17:52:18 +0530 Subject: [PATCH 13/13] upper text issues --- src/defaults.js | 13 ++++--------- src/index.js | 17 +++++++---------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/defaults.js b/src/defaults.js index 94406456..e1385218 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -69,13 +69,13 @@ const DEFAULT_VIEW_MODES = [ }, { name: 'Month', - padding: '1m', + padding: '2m', step: '1m', column_width: 120, format_string: 'YYYY-MM', lower_text: 'MMMM', upper_text: (d, ld, lang) => - d.getMonth() !== ld.getMonth() + !ld || d.getFullYear() !== ld.getFullYear() ? date_utils.format(d, 'YYYY', lang) : '', thick_line: (d) => d.getMonth() % 3 === 0, @@ -83,16 +83,11 @@ const DEFAULT_VIEW_MODES = [ }, { name: 'Year', - padding: '1m', + padding: '2y', step: '1y', column_width: 120, format_string: 'YYYY', - lower_text: 'YYYY', - upper_text: (d, ld, lang) => - d.getMonth() !== ld.getMonth() - ? date_utils.format(d, 'YYYY', lang) - : '', - upper_text_frequency: 30, + upper_text: 'YYYY', default_snap: '30d', }, ]; diff --git a/src/index.js b/src/index.js index 6fcb23e5..ce52dd05 100644 --- a/src/index.js +++ b/src/index.js @@ -569,7 +569,6 @@ 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. */ computeGridHighlightDimensions(view_mode) { - const today = new Date(); if (today < this.gantt_start || today > this.gantt_end) return null; let diff_in_units = date_utils.diff( @@ -611,7 +610,6 @@ export default class Gantt { if ($today) { $today.classList.add('current-date-highlight'); $today.style.top = +$today.style.top.slice(0, -2) - 4 + 'px'; - } } @@ -660,26 +658,25 @@ export default class Gantt { } get_dates_to_draw() { - let last_date = null; + let last_date_info = null; const dates = this.dates.map((date, i) => { - const d = this.get_date_info(date, last_date, i); - last_date = d; + console.log('starting', date, last_date_info); + const d = this.get_date_info(date, last_date_info, i); + last_date_info = d; return d; }); return dates; } get_date_info(date, last_date_info) { - let last_date = last_date_info - ? last_date_info.date - : date_utils.add(date, 1, 'day'); + let last_date = last_date_info ? last_date_info.date : null; let column_width = this.config.column_width; const base_pos = { x: last_date_info ? last_date_info.base_pos_x + last_date_info.column_width - : 0, + : 20, lower_y: this.options.header_height - 20, upper_y: this.options.header_height - 50, }; @@ -710,7 +707,7 @@ export default class Gantt { 1) / 2, upper_y: base_pos.upper_y, - lower_x: base_pos.x + column_width / 2, + lower_x: base_pos.x + column_width / 2 - 20, lower_y: base_pos.lower_y, }; }