fix: bugs in view mode renderings

This commit is contained in:
Safwan Samsudeen 2024-12-13 14:20:26 +05:30
parent 539482e6d9
commit a7d38841b3
5 changed files with 104 additions and 57 deletions

View File

@ -159,9 +159,7 @@ export default class Bar {
let $date_highlight = document.createElement('div'); let $date_highlight = document.createElement('div');
$date_highlight.classList.add('date-highlight'); $date_highlight.classList.add('date-highlight');
$date_highlight.classList.add(`highlight-${this.task.id}`); $date_highlight.classList.add(`highlight-${this.task.id}`);
// $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 = this.gantt.config.header_height - 25 + 'px';
$date_highlight.style.left = x + 'px'; $date_highlight.style.left = x + 'px';
this.$date_highlight = $date_highlight; this.$date_highlight = $date_highlight;
this.gantt.$lower_header.prepend($date_highlight); this.gantt.$lower_header.prepend($date_highlight);

View File

@ -1,10 +1,16 @@
import date_utils from './date_utils'; import date_utils from './date_utils';
function getDecade(d) {
const year = d.getFullYear();
return year - (year % 10) + '';
}
const DEFAULT_VIEW_MODES = [ const DEFAULT_VIEW_MODES = [
{ {
name: 'Hour', name: 'Hour',
padding: '7d', padding: '7d',
step: '1h', step: '1h',
format_string: 'YYYY-MM-DD HH',
lower_text: 'HH', lower_text: 'HH',
upper_text: (d, ld, lang) => upper_text: (d, ld, lang) =>
!ld || d.getDate() !== ld.getDate() !ld || d.getDate() !== ld.getDate()
@ -57,9 +63,10 @@ const DEFAULT_VIEW_MODES = [
name: 'Week', name: 'Week',
padding: '1m', padding: '1m',
step: '7d', step: '7d',
format_string: 'YYYY-MM-DD',
column_width: 140, column_width: 140,
lower_text: (d, ld, lang) => lower_text: (d, ld, lang) =>
d.getMonth() !== ld.getMonth() !ld || d.getMonth() !== ld.getMonth()
? date_utils.format(d, 'D MMM', lang) ? date_utils.format(d, 'D MMM', lang)
: date_utils.format(d, 'D', lang), : date_utils.format(d, 'D', lang),
upper_text: (d, ld, lang) => upper_text: (d, ld, lang) =>
@ -89,7 +96,9 @@ const DEFAULT_VIEW_MODES = [
step: '1y', step: '1y',
column_width: 120, column_width: 120,
format_string: 'YYYY', format_string: 'YYYY',
upper_text: 'YYYY', upper_text: (d, ld, lang) =>
!ld || getDecade(d) !== getDecade(ld) ? getDecade(d) : '',
lower_text: 'YYYY',
default_snap: '30d', default_snap: '30d',
}, },
]; ];
@ -102,9 +111,11 @@ const DEFAULT_OPTIONS = {
container_height: 300, container_height: 300,
column_width: null, column_width: null,
date_format: 'YYYY-MM-DD', date_format: 'YYYY-MM-DD',
upper_header_height: 45,
lower_header_height: 30,
snap_at: null, snap_at: null,
infinite_padding: true, infinite_padding: false,
holidays: { '#fff7ed': 'weekend' }, holidays: { 'var(--g-weekend-highlight-color)': 'weekend' },
ignore: [], ignore: [],
language: 'en', language: 'en',
lines: 'both', lines: 'both',

View File

@ -78,6 +78,8 @@ export default class Gantt {
const CSS_VARIABLES = { const CSS_VARIABLES = {
'grid-height': 'container_height', 'grid-height': 'container_height',
'bar-height': 'bar_height', 'bar-height': 'bar_height',
'lower-header-height': 'lower_header_height',
'upper-header-height': 'upper_header_height',
}; };
for (let name in CSS_VARIABLES) { for (let name in CSS_VARIABLES) {
@ -240,7 +242,10 @@ export default class Gantt {
'--gv-column-width', '--gv-column-width',
this.config.column_width + 'px', this.config.column_width + 'px',
); );
this.config.header_height = this.config.column_width * 2.5; this.config.header_height =
this.options.lower_header_height +
this.options.upper_header_height +
10;
} }
setup_dates() { setup_dates() {
@ -643,14 +648,47 @@ 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() { highlightNow() {
const today = new Date(); let now = new Date();
if (today < this.gantt_start || today > this.gantt_end) return null; if (now < this.gantt_start || now > this.gantt_end) return null;
let current = new Date(),
el = this.$container.querySelector(
'.date_' +
sanitize(
date_utils.format(
current,
this.config.view_mode.format_string,
this.options.language,
),
),
);
// safety check to prevent infinite loop
let c = 0;
while (!el && c < this.config.step) {
current = date_utils.add(current, -1, this.config.unit);
el = this.$container.querySelector(
'.date_' +
sanitize(
date_utils.format(
current,
this.config.view_mode.format_string,
this.options.language,
),
),
);
c++;
}
el.classList.add('current-date-highlight');
const diff_in_units = date_utils.diff( const diff_in_units = date_utils.diff(
today, now,
this.gantt_start, this.gantt_start,
this.config.unit, this.config.unit,
); );
const left = const left =
(diff_in_units / this.config.step) * this.config.column_width; (diff_in_units / this.config.step) * this.config.column_width;
const height = const height =
@ -658,11 +696,6 @@ export default class Gantt {
this.tasks.length + this.tasks.length +
20 + 20 +
this.options.padding / 2; this.options.padding / 2;
const date = date_utils.format(
today,
this.config.view_mode.format_string,
this.options.language,
);
this.$current_highlight = this.create_el({ this.$current_highlight = this.create_el({
top: this.config.header_height - 20, top: this.config.header_height - 20,
@ -671,10 +704,6 @@ export default class Gantt {
classes: 'current-highlight', classes: 'current-highlight',
append_to: this.$extras, append_to: this.$extras,
}); });
let $today = this.$container
.querySelector('.date_' + date.replaceAll(' ', '_'))
.classList.add('current-date-highlight');
} }
make_grid_highlights() { make_grid_highlights() {
@ -722,7 +751,7 @@ export default class Gantt {
}); });
} }
const highlightDimensions = this.highlightToday(this.config.view_mode); const highlightDimensions = this.highlightNow(this.config.view_mode);
if (!highlightDimensions) return; if (!highlightDimensions) return;
} }
@ -742,16 +771,18 @@ export default class Gantt {
make_dates() { make_dates() {
this.upper_texts_x = {}; this.upper_texts_x = {};
this.get_dates_to_draw().forEach((date, i) => { this.get_dates_to_draw().forEach((date, i) => {
if (date.lower_text) {
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,
classes: 'lower-text date_' + date.formatted_date, classes: 'lower-text date_' + sanitize(date.formatted_date),
append_to: this.$lower_header, append_to: this.$lower_header,
}); });
$lower_text.innerText = date.lower_text; $lower_text.innerText = date.lower_text;
$lower_text.style.left = $lower_text.style.left =
+$lower_text.style.left.slice(0, -2) + 'px'; +$lower_text.style.left.slice(0, -2) + 'px';
}
if (date.upper_text) { if (date.upper_text) {
this.upper_texts_x[date.upper_text] = date.upper_x; this.upper_texts_x[date.upper_text] = date.upper_x;
@ -785,13 +816,9 @@ export default class Gantt {
let column_width = this.config.column_width; let column_width = this.config.column_width;
const base_pos = { const base_x = last_date_info
x: last_date_info ? last_date_info.base_x + last_date_info.column_width
? last_date_info.base_pos_x + last_date_info.column_width : 0;
: 0,
lower_y: this.config.column_width * 1.5,
upper_y: 15,
};
let upper_text = this.config.view_mode.upper_text; let upper_text = this.config.view_mode.upper_text;
let lower_text = this.config.view_mode.lower_text; let lower_text = this.config.view_mode.lower_text;
@ -812,11 +839,11 @@ export default class Gantt {
return { return {
date, date,
formatted_date: date_utils formatted_date: sanitize(
.format(date, this.config.view_mode.format_string) date_utils.format(date, this.config.view_mode.format_string),
.replaceAll(' ', '_'), ),
column_width: this.config.column_width, column_width: this.config.column_width,
base_pos_x: base_pos.x, base_x,
upper_text: this.config.view_mode.upper_text( upper_text: this.config.view_mode.upper_text(
date, date,
last_date, last_date,
@ -828,13 +855,13 @@ export default class Gantt {
this.options.language, this.options.language,
), ),
upper_x: upper_x:
base_pos.x + base_x +
(column_width * this.config.view_mode.upper_text_frequency || (column_width * this.config.view_mode.upper_text_frequency ||
1) / 1) /
2, 2,
upper_y: base_pos.upper_y, upper_y: 15,
lower_x: base_pos.x, lower_x: base_x,
lower_y: base_pos.lower_y, lower_y: this.options.upper_header_height + 5,
}; };
} }
@ -924,6 +951,7 @@ export default class Gantt {
this.$container.scrollLeft / this.config.column_width, this.$container.scrollLeft / this.config.column_width,
this.config.unit, this.config.unit,
); );
let current_upper = this.config.view_mode.upper_text(this.current_date); let current_upper = this.config.view_mode.upper_text(this.current_date);
let $el = this.upperTexts.find( let $el = this.upperTexts.find(
(el) => el.textContent === current_upper, (el) => el.textContent === current_upper,
@ -1094,9 +1122,11 @@ export default class Gantt {
// Calculate current scroll position's upper text // Calculate current scroll position's upper text
this.current_date = date_utils.add( this.current_date = 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.step,
this.config.unit, this.config.unit,
); );
let current_upper = this.config.view_mode.upper_text( let current_upper = this.config.view_mode.upper_text(
this.current_date, this.current_date,
); );
@ -1107,8 +1137,9 @@ export default class Gantt {
// Recalculate for smoother experience // Recalculate for smoother experience
this.current_date = date_utils.add( this.current_date = date_utils.add(
this.gantt_start, this.gantt_start,
(e.currentTarget.scrollLeft + $el.clientWidth) / ((e.currentTarget.scrollLeft + $el.clientWidth) /
this.config.column_width, this.config.column_width) *
this.config.step,
this.config.unit, this.config.unit,
); );
current_upper = this.config.view_mode.upper_text(this.current_date); current_upper = this.config.view_mode.upper_text(this.current_date);
@ -1436,3 +1467,7 @@ Gantt.VIEW_MODE = {
function generate_id(task) { function generate_id(task) {
return task.name + '_' + Math.random().toString(36).slice(2, 12); return task.name + '_' + Math.random().toString(36).slice(2, 12);
} }
function sanitize(s) {
return s.replaceAll(' ', '_').replaceAll(':', '_').replaceAll('.', '_');
}

View File

@ -53,18 +53,18 @@
} }
& .upper-header { & .upper-header {
height: calc(var(--gv-column-width) * 1.5); height: var(--gv-upper-header-height);
} }
& .lower-header { & .lower-header {
height: var(--gv-column-width); height: var(--gv-lower-header-height);
} }
& .lower-text { & .lower-text {
font-size: 12px; font-size: 12px;
position: absolute; position: absolute;
width: calc(var(--gv-column-width) * 0.8); width: calc(var(--gv-column-width) * 0.8);
height: calc(var(--gv-column-width) * 0.8); height: calc(var(--gv-lower-header-height) * 0.8);
margin: 0 calc(var(--gv-column-width) * 0.1); margin: 0 calc(var(--gv-column-width) * 0.1);
align-content: center; align-content: center;
text-align: center; text-align: center;
@ -77,13 +77,13 @@
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
color: var(--g-text-dark); color: var(--g-text-dark);
height: calc(var(--gv-lower-header-height) * 0.66);
} }
& .current-upper { & .current-upper {
position: sticky; position: sticky;
left: 0 !important; left: 0 !important;
padding: 0 10px; padding: 0 calc(var(--gv-lower-header-height) * 0.33);
height: 20px;
background: white; background: white;
} }
@ -128,9 +128,11 @@
& .date-highlight { & .date-highlight {
background-color: var(--g-progress-color); background-color: var(--g-progress-color);
border-radius: 12px; border-radius: 20px;
height: calc(var(--gv-bar-height) * 0.8); height: var(--gv-lower-header-height);
top: calc(var(--gv-column-width) * 1.5); top: calc(
var(--gv-upper-header-height) + var(--gv-lower-header-height) * 0.1
);
position: absolute; position: absolute;
display: none; display: none;
} }
@ -145,7 +147,7 @@
& .current-date-highlight { & .current-date-highlight {
background: var(--g-blue-dark); background: var(--g-blue-dark);
color: var(--g-text-light); color: var(--g-text-light);
border-radius: 100px; border-radius: 5px;
} }
& .holiday-label { & .holiday-label {

View File

@ -20,4 +20,5 @@
--g-blue-dark: #2c94ec; --g-blue-dark: #2c94ec;
--g-header-background: #ffffff; --g-header-background: #ffffff;
--g-row-color: #fff; --g-row-color: #fff;
--g-weekend-highlight-color: #bfdbfe;
} }