make daily mode work after rewrite of date system
This commit is contained in:
parent
8f03ba0572
commit
6e0e0a9704
3
.gitignore
vendored
3
.gitignore
vendored
@ -21,6 +21,7 @@ coverage
|
|||||||
|
|
||||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
build/Release
|
build/Release
|
||||||
|
dist/*
|
||||||
|
|
||||||
# Dependency directory
|
# Dependency directory
|
||||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
# 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
|
.DS_Store
|
||||||
|
|
||||||
gh-pages
|
gh-pages
|
||||||
|
|||||||
46
index.html
46
index.html
@ -37,7 +37,7 @@
|
|||||||
let tasks = [
|
let tasks = [
|
||||||
{
|
{
|
||||||
start: '2024-04-01',
|
start: '2024-04-01',
|
||||||
end: '2024-04-01',
|
end: '2024-04-04',
|
||||||
name: 'Redesign website',
|
name: 'Redesign website',
|
||||||
id: 'Task 0',
|
id: 'Task 0',
|
||||||
progress: 30,
|
progress: 30,
|
||||||
@ -77,7 +77,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: '2024-04-21',
|
start: '2024-04-21',
|
||||||
end: '2024-04-29',
|
end: '2024-05-29',
|
||||||
name: 'Go Live!',
|
name: 'Go Live!',
|
||||||
id: 'Task 5',
|
id: 'Task 5',
|
||||||
progress: 0,
|
progress: 0,
|
||||||
@ -85,22 +85,22 @@
|
|||||||
custom_class: 'bar-milestone',
|
custom_class: 'bar-milestone',
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// start: '2014-01-05',
|
// start: '2014-01-05',
|
||||||
// end: '2019-10-12',
|
// end: '2019-10-12',
|
||||||
// name: 'Long term task',
|
// name: 'Long term task',
|
||||||
// id: "Task 6",
|
// id: 'Task 6',
|
||||||
// progress: 0
|
// progress: 0,
|
||||||
// }
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Uncomment to test fixed header
|
// Uncomment to test fixed header
|
||||||
tasks = [
|
// tasks = [
|
||||||
...tasks,
|
// ...tasks,
|
||||||
...Array.from({ length: tasks.length * 3 }, (_, i) => ({
|
// ...Array.from({ length: tasks.length * 3 }, (_, i) => ({
|
||||||
...tasks[i % 3],
|
// ...tasks[i % 3],
|
||||||
id: i,
|
// id: i,
|
||||||
})),
|
// })),
|
||||||
];
|
// ];
|
||||||
let gantt_chart = new Gantt('.gantt-target', tasks, {
|
let gantt_chart = new Gantt('.gantt-target', tasks, {
|
||||||
on_click(task) {
|
on_click(task) {
|
||||||
console.log('Click', task);
|
console.log('Click', task);
|
||||||
@ -109,15 +109,13 @@
|
|||||||
// console.log("Hover", x, y);
|
// console.log("Hover", x, y);
|
||||||
// }
|
// }
|
||||||
view_mode: 'Day',
|
view_mode: 'Day',
|
||||||
view_mode_padding: { DAY: '3d' },
|
// view_modes: [
|
||||||
custom_view_modes: [
|
// {
|
||||||
{
|
// name: 'Custom Day',
|
||||||
name: 'Custom Day',
|
// padding: '1m',
|
||||||
padding: '1m',
|
// step: '1d',
|
||||||
step: 3,
|
// },
|
||||||
unit: 'day',
|
// ],
|
||||||
},
|
|
||||||
],
|
|
||||||
// popup_on: 'click',
|
// popup_on: 'click',
|
||||||
// move_dependencies: false,
|
// move_dependencies: false,
|
||||||
// scroll_to: 'today',
|
// scroll_to: 'today',
|
||||||
|
|||||||
71
src/bar.js
71
src/bar.js
@ -28,9 +28,9 @@ export default class Bar {
|
|||||||
this.compute_y();
|
this.compute_y();
|
||||||
this.compute_duration();
|
this.compute_duration();
|
||||||
this.corner_radius = this.gantt.options.bar_corner_radius;
|
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.progress_width =
|
||||||
this.gantt.options.column_width *
|
this.gantt.config.column_width *
|
||||||
this.duration *
|
this.duration *
|
||||||
(this.task.progress / 100) || 0;
|
(this.task.progress / 100) || 0;
|
||||||
this.group = createSVG('g', {
|
this.group = createSVG('g', {
|
||||||
@ -107,7 +107,6 @@ export default class Bar {
|
|||||||
: ''),
|
: ''),
|
||||||
append_to: this.bar_group,
|
append_to: this.bar_group,
|
||||||
});
|
});
|
||||||
|
|
||||||
animateSVG(this.$bar, 'width', 0, this.width);
|
animateSVG(this.$bar, 'width', 0, this.width);
|
||||||
|
|
||||||
if (this.invalid) {
|
if (this.invalid) {
|
||||||
@ -138,6 +137,7 @@ export default class Bar {
|
|||||||
|
|
||||||
draw_progress_bar() {
|
draw_progress_bar() {
|
||||||
if (this.invalid) return;
|
if (this.invalid) return;
|
||||||
|
|
||||||
this.$bar_progress = createSVG('rect', {
|
this.$bar_progress = createSVG('rect', {
|
||||||
x: this.x,
|
x: this.x,
|
||||||
y: this.y,
|
y: this.y,
|
||||||
@ -150,8 +150,8 @@ export default class Bar {
|
|||||||
});
|
});
|
||||||
const x =
|
const x =
|
||||||
(date_utils.diff(this.task._start, this.gantt.gantt_start, 'hour') /
|
(date_utils.diff(this.task._start, this.gantt.gantt_start, 'hour') /
|
||||||
this.gantt.options.step) *
|
this.gantt.config.step) *
|
||||||
this.gantt.options.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.id = `highlight-${this.task.id}`;
|
||||||
@ -285,7 +285,6 @@ export default class Bar {
|
|||||||
if (this.gantt.options.popup_on === 'click') {
|
if (this.gantt.options.popup_on === 'click') {
|
||||||
let opened = false;
|
let opened = false;
|
||||||
$.on(this.group, 'click', (e) => {
|
$.on(this.group, 'click', (e) => {
|
||||||
console.log(opened);
|
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
this.show_popup(e.offsetX || e.layerX);
|
this.show_popup(e.offsetX || e.layerX);
|
||||||
document.getElementById(
|
document.getElementById(
|
||||||
@ -304,17 +303,12 @@ 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(
|
|
||||||
`${task_id}-highlight`,
|
|
||||||
).style.display = 'block';
|
|
||||||
}, 200)),
|
}, 200)),
|
||||||
);
|
);
|
||||||
|
|
||||||
$.on(this.group, 'mouseleave', () => {
|
$.on(this.group, 'mouseleave', () => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
this.gantt.popup?.hide?.();
|
this.gantt.popup?.hide?.();
|
||||||
document.getElementById(`${task_id}-highlight`).style.display =
|
|
||||||
'none';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +422,6 @@ export default class Bar {
|
|||||||
date_changed() {
|
date_changed() {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
const { new_start_date, new_end_date } = this.compute_start_end_date();
|
const { new_start_date, new_end_date } = this.compute_start_end_date();
|
||||||
|
|
||||||
if (Number(this.task._start) !== Number(new_start_date)) {
|
if (Number(this.task._start) !== Number(new_start_date)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
this.task._start = new_start_date;
|
this.task._start = new_start_date;
|
||||||
@ -461,15 +454,16 @@ export default class Bar {
|
|||||||
|
|
||||||
compute_start_end_date() {
|
compute_start_end_date() {
|
||||||
const bar = this.$bar;
|
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(
|
let new_start_date = date_utils.add(
|
||||||
this.gantt.gantt_start,
|
this.gantt.gantt_start,
|
||||||
x_in_units * this.gantt.options.step,
|
x_in_units * this.gantt.config.step,
|
||||||
'hour',
|
this.gantt.config.unit,
|
||||||
);
|
);
|
||||||
const start_offset =
|
const start_offset =
|
||||||
this.gantt.gantt_start.getTimezoneOffset() -
|
this.gantt.gantt_start.getTimezoneOffset() -
|
||||||
new_start_date.getTimezoneOffset();
|
new_start_date.getTimezoneOffset();
|
||||||
|
|
||||||
if (start_offset) {
|
if (start_offset) {
|
||||||
new_start_date = date_utils.add(
|
new_start_date = date_utils.add(
|
||||||
new_start_date,
|
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(
|
const new_end_date = date_utils.add(
|
||||||
new_start_date,
|
new_start_date,
|
||||||
width_in_units * this.gantt.options.step,
|
width_in_units * this.gantt.config.step,
|
||||||
'hour',
|
this.gantt.config.unit,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { new_start_date, new_end_date };
|
return { new_start_date, new_end_date };
|
||||||
@ -497,7 +491,7 @@ export default class Bar {
|
|||||||
compute_expected_progress() {
|
compute_expected_progress() {
|
||||||
this.expected_progress =
|
this.expected_progress =
|
||||||
date_utils.diff(date_utils.today(), this.task._start, 'hour') /
|
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.expected_progress < this.duration
|
((this.expected_progress < this.duration
|
||||||
? this.expected_progress
|
? this.expected_progress
|
||||||
@ -507,17 +501,22 @@ export default class Bar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compute_x() {
|
compute_x() {
|
||||||
const { step, column_width } = this.gantt.options;
|
const { step, column_width } = this.gantt.config;
|
||||||
const task_start = this.task._start;
|
const task_start = this.task._start;
|
||||||
const gantt_start = this.gantt.gantt_start;
|
const gantt_start = this.gantt.gantt_start;
|
||||||
|
|
||||||
const diff = date_utils.diff(task_start, gantt_start, 'hour');
|
const diff = date_utils.diff(
|
||||||
let x = (diff / step) * column_width;
|
task_start,
|
||||||
|
gantt_start,
|
||||||
|
this.gantt.config.unit,
|
||||||
|
);
|
||||||
|
let x = diff * column_width;
|
||||||
|
|
||||||
/* Since the column width is based on 30,
|
/* Since the column width is based on 30,
|
||||||
we count the month-difference, multiply it by 30 for a "pseudo-month"
|
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
|
and then add the days in the month, making sure the number does not exceed 29
|
||||||
so it is within the column */
|
so it is within the column */
|
||||||
|
|
||||||
if (this.gantt.view_is('Month')) {
|
if (this.gantt.view_is('Month')) {
|
||||||
const diffDaysBasedOn30DayMonths =
|
const diffDaysBasedOn30DayMonths =
|
||||||
date_utils.diff(task_start, gantt_start, 'month') * 30;
|
date_utils.diff(task_start, gantt_start, 'month') * 30;
|
||||||
@ -529,6 +528,7 @@ export default class Bar {
|
|||||||
|
|
||||||
x = (diff * column_width) / 30;
|
x = (diff * column_width) / 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,8 +541,11 @@ export default class Bar {
|
|||||||
|
|
||||||
compute_duration() {
|
compute_duration() {
|
||||||
this.duration =
|
this.duration =
|
||||||
date_utils.diff(this.task._end, this.task._start, 'hour') /
|
date_utils.diff(
|
||||||
this.gantt.options.step;
|
this.task._end,
|
||||||
|
this.task._start,
|
||||||
|
this.gantt.config.unit,
|
||||||
|
) / this.gantt.config.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_snap_position(dx) {
|
get_snap_position(dx) {
|
||||||
@ -551,29 +554,29 @@ export default class Bar {
|
|||||||
position;
|
position;
|
||||||
|
|
||||||
if (this.gantt.view_is('Week')) {
|
if (this.gantt.view_is('Week')) {
|
||||||
rem = dx % (this.gantt.options.column_width / 7);
|
rem = dx % (this.gantt.config.column_width / 7);
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.gantt.options.column_width / 14
|
(rem < this.gantt.config.column_width / 14
|
||||||
? 0
|
? 0
|
||||||
: this.gantt.options.column_width / 7);
|
: this.gantt.config.column_width / 7);
|
||||||
} else if (this.gantt.view_is('Month')) {
|
} else if (this.gantt.view_is('Month')) {
|
||||||
rem = dx % (this.gantt.options.column_width / 30);
|
rem = dx % (this.gantt.config.column_width / 30);
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.gantt.options.column_width / 60
|
(rem < this.gantt.config.column_width / 60
|
||||||
? 0
|
? 0
|
||||||
: this.gantt.options.column_width / 30);
|
: this.gantt.config.column_width / 30);
|
||||||
} else {
|
} else {
|
||||||
rem = dx % this.gantt.options.column_width;
|
rem = dx % this.gantt.config.column_width;
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.gantt.options.column_width / 2
|
(rem < this.gantt.config.column_width / 2
|
||||||
? 0
|
? 0
|
||||||
: this.gantt.options.column_width);
|
: this.gantt.config.column_width);
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
@ -592,7 +595,7 @@ export default class Bar {
|
|||||||
this.compute_expected_progress();
|
this.compute_expected_progress();
|
||||||
this.$expected_bar_progress.setAttribute(
|
this.$expected_bar_progress.setAttribute(
|
||||||
'width',
|
'width',
|
||||||
this.gantt.options.column_width *
|
this.gantt.config.column_width *
|
||||||
this.duration *
|
this.duration *
|
||||||
(this.expected_progress / 100) || 0,
|
(this.expected_progress / 100) || 0,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,7 +6,6 @@ const MINUTE = 'minute';
|
|||||||
const SECOND = 'second';
|
const SECOND = 'second';
|
||||||
const MILLISECOND = 'millisecond';
|
const MILLISECOND = 'millisecond';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse_duration(duration) {
|
parse_duration(duration) {
|
||||||
const regex = /([0-9]+)(y|m|d|h|min|s|ms)/gm;
|
const regex = /([0-9]+)(y|m|d|h|min|s|ms)/gm;
|
||||||
@ -84,7 +83,7 @@ export default {
|
|||||||
month: 'long',
|
month: 'long',
|
||||||
});
|
});
|
||||||
const dateTimeFormatShort = new Intl.DateTimeFormat(lang, {
|
const dateTimeFormatShort = new Intl.DateTimeFormat(lang, {
|
||||||
month: "short",
|
month: 'short',
|
||||||
});
|
});
|
||||||
const month_name = dateTimeFormat.format(date);
|
const month_name = dateTimeFormat.format(date);
|
||||||
const month_name_capitalized =
|
const month_name_capitalized =
|
||||||
|
|||||||
115
src/defaults.js
Normal file
115
src/defaults.js
Normal file
@ -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 };
|
||||||
500
src/index.js
500
src/index.js
@ -1,55 +1,22 @@
|
|||||||
import date_utils from './date_utils';
|
import date_utils from './date_utils';
|
||||||
import { $, createSVG } from './svg_utils';
|
import { $, createSVG } from './svg_utils';
|
||||||
import Bar from './bar';
|
|
||||||
import Arrow from './arrow';
|
import Arrow from './arrow';
|
||||||
|
import Bar from './bar';
|
||||||
import Popup from './popup';
|
import Popup from './popup';
|
||||||
|
|
||||||
|
import { DEFAULT_OPTIONS, DEFAULT_VIEW_MODES } from './defaults';
|
||||||
|
|
||||||
import './gantt.css';
|
import './gantt.css';
|
||||||
|
|
||||||
const VIEW_MODE = {
|
const VIEW_MODE = {
|
||||||
HOUR: 'Hour',
|
HOUR: DEFAULT_VIEW_MODES[0],
|
||||||
QUARTER_DAY: 'Quarter Day',
|
QUARTER_DAY: DEFAULT_VIEW_MODES[1],
|
||||||
HALF_DAY: 'Half Day',
|
HALF_DAY: DEFAULT_VIEW_MODES[2],
|
||||||
DAY: 'Day',
|
DAY: DEFAULT_VIEW_MODES[3],
|
||||||
WEEK: 'Week',
|
WEEK: DEFAULT_VIEW_MODES[4],
|
||||||
MONTH: 'Month',
|
MONTH: DEFAULT_VIEW_MODES[5],
|
||||||
YEAR: 'Year',
|
YEAR: DEFAULT_VIEW_MODES[6],
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Gantt {
|
export default class Gantt {
|
||||||
@ -57,7 +24,6 @@ export default class Gantt {
|
|||||||
this.setup_wrapper(wrapper);
|
this.setup_wrapper(wrapper);
|
||||||
this.setup_options(options);
|
this.setup_options(options);
|
||||||
this.setup_tasks(tasks);
|
this.setup_tasks(tasks);
|
||||||
// initialize with default view mode
|
|
||||||
this.change_view_mode();
|
this.change_view_mode();
|
||||||
this.bind_events();
|
this.bind_events();
|
||||||
}
|
}
|
||||||
@ -113,25 +79,12 @@ export default class Gantt {
|
|||||||
this.options = { ...DEFAULT_OPTIONS, ...options };
|
this.options = { ...DEFAULT_OPTIONS, ...options };
|
||||||
const custom_mode = this.options.custom_view_modes
|
const custom_mode = this.options.custom_view_modes
|
||||||
? this.options.custom_view_modes.find(
|
? this.options.custom_view_modes.find(
|
||||||
(m) => m.name === this.options.view_mode,
|
(m) => m.name === this.config.view_mode.name,
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
if (custom_mode) this.options = { ...this.options, custom_mode };
|
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 = {
|
this.config = {};
|
||||||
...VIEW_MODE_PADDING,
|
|
||||||
...options.view_mode_padding,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_tasks(tasks) {
|
setup_tasks(tasks) {
|
||||||
@ -234,54 +187,21 @@ export default class Gantt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
change_view_mode(mode = this.options.view_mode) {
|
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.update_view_scale(mode);
|
||||||
this.setup_dates();
|
this.setup_dates();
|
||||||
this.render();
|
this.render();
|
||||||
// fire viewmode_change event
|
|
||||||
this.trigger_event('view_change', [mode]);
|
this.trigger_event('view_change', [mode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_view_scale(view_mode) {
|
update_view_scale(mode) {
|
||||||
this.options.view_mode = view_mode;
|
let { duration, scale } = date_utils.parse_duration(mode.step);
|
||||||
const custom_mode = this.options.custom_mode;
|
this.config.step = duration;
|
||||||
if (custom_mode) {
|
this.config.unit = scale;
|
||||||
//configure step and column width for custom view case
|
this.config.column_width = mode.column_width || 38;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_dates() {
|
setup_dates() {
|
||||||
@ -290,60 +210,39 @@ export default class Gantt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup_gantt_dates() {
|
setup_gantt_dates() {
|
||||||
this.gantt_start = this.gantt_end = null;
|
// set global start and end date
|
||||||
|
|
||||||
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 (!this.gantt_end || task._end > this.gantt_end) {
|
|
||||||
this.gantt_end = task._end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let gantt_start, gantt_end;
|
let gantt_start, gantt_end;
|
||||||
if (!this.gantt_start) gantt_start = new Date();
|
for (let task of this.tasks) {
|
||||||
else gantt_start = date_utils.start_of(this.gantt_start, 'day');
|
if (!gantt_start || task._start < gantt_start) {
|
||||||
if (!this.gantt_end) gantt_end = new Date();
|
gantt_start = task._start;
|
||||||
else gantt_end = date_utils.start_of(this.gantt_end, 'day');
|
}
|
||||||
|
if (!gantt_end || task._end > gantt_end) {
|
||||||
const custom_mode = this.options.custom_mode;
|
gantt_end = task._end;
|
||||||
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 = date_utils.add(
|
||||||
gantt_start,
|
gantt_start,
|
||||||
-padding_start.duration,
|
-padding_start.duration,
|
||||||
padding_start.scale,
|
padding_start.scale,
|
||||||
);
|
);
|
||||||
|
|
||||||
let format_string;
|
let format_string =
|
||||||
if (this.view_is(VIEW_MODE.YEAR)) {
|
this.config.view_mode.format_string || 'YYYY-MM-DD HH';
|
||||||
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';
|
|
||||||
}
|
|
||||||
this.gantt_start = date_utils.parse(
|
this.gantt_start = date_utils.parse(
|
||||||
date_utils.format(gantt_start, format_string),
|
date_utils.format(gantt_start, format_string),
|
||||||
);
|
);
|
||||||
@ -356,36 +255,15 @@ export default class Gantt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup_date_values() {
|
setup_date_values() {
|
||||||
this.dates = [];
|
let cur_date = this.gantt_start;
|
||||||
let cur_date = null;
|
this.dates = [cur_date];
|
||||||
|
|
||||||
while (cur_date === null || cur_date < this.gantt_end) {
|
while (cur_date < this.gantt_end) {
|
||||||
if (this.options.custom_mode) {
|
cur_date = date_utils.add(
|
||||||
const step = this.options.custom_mode.step || 1;
|
cur_date,
|
||||||
const unit = this.options.custom_mode.unit || 'day';
|
this.config.step,
|
||||||
|
this.config.unit,
|
||||||
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',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.dates.push(cur_date);
|
this.dates.push(cur_date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,7 +312,7 @@ export default class Gantt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_grid_background() {
|
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 =
|
const grid_height =
|
||||||
this.options.header_height +
|
this.options.header_height +
|
||||||
this.options.padding +
|
this.options.padding +
|
||||||
@ -458,7 +336,7 @@ export default class Gantt {
|
|||||||
make_grid_rows() {
|
make_grid_rows() {
|
||||||
const rows_layer = createSVG('g', { append_to: this.layers.grid });
|
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;
|
const row_height = this.options.bar_height + this.options.padding;
|
||||||
|
|
||||||
let row_y = this.options.header_height + this.options.padding / 2;
|
let row_y = this.options.header_height + this.options.padding / 2;
|
||||||
@ -485,7 +363,7 @@ export default class Gantt {
|
|||||||
let $header = document.createElement('div');
|
let $header = document.createElement('div');
|
||||||
$header.style.height = this.options.header_height + 10 + 'px';
|
$header.style.height = this.options.header_height + 10 + 'px';
|
||||||
$header.style.width =
|
$header.style.width =
|
||||||
this.dates.length * this.options.column_width + 'px';
|
this.dates.length * this.config.column_width + 'px';
|
||||||
$header.classList.add('grid-header');
|
$header.classList.add('grid-header');
|
||||||
this.$header = $header;
|
this.$header = $header;
|
||||||
this.$container.appendChild($header);
|
this.$container.appendChild($header);
|
||||||
@ -524,7 +402,7 @@ export default class Gantt {
|
|||||||
$option.textContent = VIEW_MODE[key];
|
$option.textContent = VIEW_MODE[key];
|
||||||
$select.appendChild($option);
|
$select.appendChild($option);
|
||||||
}
|
}
|
||||||
// $select.value = this.options.view_mode
|
|
||||||
$select.addEventListener(
|
$select.addEventListener(
|
||||||
'change',
|
'change',
|
||||||
function () {
|
function () {
|
||||||
@ -608,7 +486,7 @@ export default class Gantt {
|
|||||||
|
|
||||||
let row_y = this.options.header_height + this.options.padding / 2;
|
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;
|
const row_height = this.options.bar_height + this.options.padding;
|
||||||
if (this.options.lines !== 'vertical') {
|
if (this.options.lines !== 'vertical') {
|
||||||
for (let _ of this.tasks) {
|
for (let _ of this.tasks) {
|
||||||
@ -651,10 +529,10 @@ export default class Gantt {
|
|||||||
if (this.view_is(VIEW_MODE.MONTH)) {
|
if (this.view_is(VIEW_MODE.MONTH)) {
|
||||||
tick_x +=
|
tick_x +=
|
||||||
(date_utils.get_days_in_month(date) *
|
(date_utils.get_days_in_month(date) *
|
||||||
this.options.column_width) /
|
this.config.column_width) /
|
||||||
30;
|
30;
|
||||||
} else {
|
} 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) {
|
if (d.getDay() === 0 || d.getDay() === 6) {
|
||||||
const x =
|
const x =
|
||||||
(date_utils.diff(d, this.gantt_start, 'hour') /
|
(date_utils.diff(d, this.gantt_start, 'hour') /
|
||||||
this.options.step) *
|
this.config.step) *
|
||||||
this.options.column_width;
|
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;
|
||||||
@ -679,7 +557,7 @@ export default class Gantt {
|
|||||||
y: this.options.header_height + this.options.padding / 2,
|
y: this.options.header_height + this.options.padding / 2,
|
||||||
width:
|
width:
|
||||||
(this.view_is('Day') ? 1 : 2) *
|
(this.view_is('Day') ? 1 : 2) *
|
||||||
this.options.column_width,
|
this.config.column_width,
|
||||||
height,
|
height,
|
||||||
class: 'holiday-highlight',
|
class: 'holiday-highlight',
|
||||||
append_to: this.layers.grid,
|
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.
|
* 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.
|
* @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) {
|
computeGridHighlightDimensions(view_mode) {
|
||||||
const todayDate = new Date();
|
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)) {
|
if (this.view_is(VIEW_MODE.DAY)) {
|
||||||
return {
|
return {
|
||||||
x:
|
x:
|
||||||
x +
|
x +
|
||||||
(date_utils.diff(today, this.gantt_start, 'hour') /
|
(date_utils.diff(today, this.gantt_start, 'hour') /
|
||||||
this.options.step) *
|
this.config.step) *
|
||||||
this.options.column_width,
|
this.config.column_width,
|
||||||
date: today,
|
date: today,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -728,7 +607,7 @@ export default class Gantt {
|
|||||||
if (todayDate >= startDate && todayDate <= endDate) {
|
if (todayDate >= startDate && todayDate <= endDate) {
|
||||||
return { x, date: startDate };
|
return { x, date: startDate };
|
||||||
} else {
|
} 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)
|
this.view_is(VIEW_MODE.YEAR)
|
||||||
) {
|
) {
|
||||||
// Used as we must find the _end_ of session if view is not Day
|
// 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;
|
if (!highlightDimensions) return;
|
||||||
const { x: left, date } = highlightDimensions;
|
const { x: left, date } = highlightDimensions;
|
||||||
if (!this.dates.find((d) => d.getTime() == date.getTime())) return;
|
if (!this.dates.find((d) => d.getTime() == date.getTime())) return;
|
||||||
@ -830,152 +711,8 @@ export default class Gantt {
|
|||||||
let last_date = last_date_info
|
let last_date = last_date_info
|
||||||
? last_date_info.date
|
? last_date_info.date
|
||||||
: date_utils.add(date, 1, 'day');
|
: 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 =
|
let column_width = this.config.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;
|
|
||||||
|
|
||||||
const base_pos = {
|
const base_pos = {
|
||||||
x: last_date_info
|
x: last_date_info
|
||||||
@ -1000,34 +737,25 @@ export default class Gantt {
|
|||||||
Year_lower: column_width / 2,
|
Year_lower: column_width / 2,
|
||||||
Year_upper: (column_width * 30) / 2,
|
Year_upper: (column_width * 30) / 2,
|
||||||
};
|
};
|
||||||
if (custom_mode) {
|
let upper_text = this.config.view_mode.upper_text;
|
||||||
x_pos[`${custom_mode.name}_upper`] = column_width / 2;
|
let lower_text = this.config.view_mode.lower_text;
|
||||||
x_pos[`${custom_mode.name}_lower`] =
|
|
||||||
column_width /
|
|
||||||
(custom_mode.unit.toLowerCase() === 'day' ? 1 : 2);
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
date,
|
date,
|
||||||
formatted_date: date_utils.format(date).replaceAll(' ', '_'),
|
formatted_date: date_utils.format(date).replaceAll(' ', '_'),
|
||||||
column_width,
|
column_width: this.config.column_width,
|
||||||
base_pos_x: base_pos.x,
|
base_pos_x: base_pos.x,
|
||||||
upper_text: this.options.upper_text
|
upper_text:
|
||||||
? this.options.upper_text(
|
typeof upper_text === 'string'
|
||||||
date,
|
? date_utils.format(date, upper_text, this.options.language)
|
||||||
this.options.view_mode,
|
: upper_text(date, last_date, this.options.language),
|
||||||
date_text[`${this.options.view_mode}_upper`],
|
lower_text:
|
||||||
)
|
typeof upper_text === 'string'
|
||||||
: date_text[`${this.options.view_mode}_upper`],
|
? date_utils.format(date, lower_text, this.options.language)
|
||||||
lower_text: this.options.lower_text
|
: lower_text(date, last_date, this.options.language),
|
||||||
? this.options.lower_text(
|
upper_x: base_pos.x + x_pos[`${this.config.view_mode.name}_upper`],
|
||||||
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_y: base_pos.upper_y,
|
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,
|
lower_y: base_pos.lower_y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1098,9 +826,9 @@ export default class Gantt {
|
|||||||
date_utils.diff(date, this.gantt_start, 'hour') + 24;
|
date_utils.diff(date, this.gantt_start, 'hour') + 24;
|
||||||
|
|
||||||
const scroll_pos =
|
const scroll_pos =
|
||||||
(hours_before_first_task / this.options.step) *
|
(hours_before_first_task / this.config.step) *
|
||||||
this.options.column_width -
|
this.config.column_width -
|
||||||
this.options.column_width;
|
this.config.column_width;
|
||||||
parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' });
|
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) => {
|
$.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {
|
||||||
const bar_wrapper = $.closest('.bar-wrapper', element);
|
const bar_wrapper = $.closest('.bar-wrapper', element);
|
||||||
bars.forEach((bar) => bar.group.classList.remove('active'));
|
bars.forEach((bar) => bar.group.classList.remove('active'));
|
||||||
|
|
||||||
if (element.classList.contains('left')) {
|
if (element.classList.contains('left')) {
|
||||||
is_resizing_left = true;
|
is_resizing_left = true;
|
||||||
} else if (element.classList.contains('right')) {
|
} else if (element.classList.contains('right')) {
|
||||||
@ -1187,13 +914,13 @@ export default class Gantt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const daysSinceStart =
|
const daysSinceStart =
|
||||||
((e.currentTarget.scrollLeft / this.options.column_width) *
|
((e.currentTarget.scrollLeft / this.config.column_width) *
|
||||||
this.options.step) /
|
this.config.step) /
|
||||||
24;
|
24;
|
||||||
let format_str = 'D MMM';
|
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';
|
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';
|
format_str = 'MMMM';
|
||||||
else if (this.view_is('Half Day')) format_str = 'D';
|
else if (this.view_is('Half Day')) format_str = 'D';
|
||||||
else if (this.view_is('Hour')) format_str = 'D MMMM';
|
else if (this.view_is('Hour')) format_str = 'D MMMM';
|
||||||
@ -1310,7 +1037,6 @@ export default class Gantt {
|
|||||||
is_resizing = true;
|
is_resizing = true;
|
||||||
x_on_start = e.offsetX || e.layerX;
|
x_on_start = e.offsetX || e.layerX;
|
||||||
y_on_start = e.offsetY || e.layerY;
|
y_on_start = e.offsetY || e.layerY;
|
||||||
console.log(e, handle);
|
|
||||||
|
|
||||||
const $bar_wrapper = $.closest('.bar-wrapper', handle);
|
const $bar_wrapper = $.closest('.bar-wrapper', handle);
|
||||||
const id = $bar_wrapper.getAttribute('data-id');
|
const id = $bar_wrapper.getAttribute('data-id');
|
||||||
@ -1328,12 +1054,6 @@ export default class Gantt {
|
|||||||
$.on(this.$svg, 'mousemove', (e) => {
|
$.on(this.$svg, 'mousemove', (e) => {
|
||||||
if (!is_resizing) return;
|
if (!is_resizing) return;
|
||||||
let dx = (e.offsetX || e.layerX) - x_on_start;
|
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) {
|
if (dx > $bar_progress.max_dx) {
|
||||||
dx = $bar_progress.max_dx;
|
dx = $bar_progress.max_dx;
|
||||||
}
|
}
|
||||||
@ -1382,29 +1102,29 @@ export default class Gantt {
|
|||||||
position;
|
position;
|
||||||
|
|
||||||
if (this.view_is(VIEW_MODE.WEEK)) {
|
if (this.view_is(VIEW_MODE.WEEK)) {
|
||||||
rem = dx % (this.options.column_width / 7);
|
rem = dx % (this.config.column_width / 7);
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.options.column_width / 14
|
(rem < this.config.column_width / 14
|
||||||
? 0
|
? 0
|
||||||
: this.options.column_width / 7);
|
: this.config.column_width / 7);
|
||||||
} else if (this.view_is(VIEW_MODE.MONTH)) {
|
} else if (this.view_is(VIEW_MODE.MONTH)) {
|
||||||
rem = dx % (this.options.column_width / 30);
|
rem = dx % (this.config.column_width / 30);
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.options.column_width / 60
|
(rem < this.config.column_width / 60
|
||||||
? 0
|
? 0
|
||||||
: this.options.column_width / 30);
|
: this.config.column_width / 30);
|
||||||
} else {
|
} else {
|
||||||
rem = dx % this.options.column_width;
|
rem = dx % this.config.column_width;
|
||||||
position =
|
position =
|
||||||
odx -
|
odx -
|
||||||
rem +
|
rem +
|
||||||
(rem < this.options.column_width / 2
|
(rem < this.config.column_width / 2
|
||||||
? 0
|
? 0
|
||||||
: this.options.column_width);
|
: this.config.column_width);
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
@ -1418,11 +1138,11 @@ export default class Gantt {
|
|||||||
|
|
||||||
view_is(modes) {
|
view_is(modes) {
|
||||||
if (typeof modes === 'string') {
|
if (typeof modes === 'string') {
|
||||||
return this.options.view_mode === modes;
|
return this.config.view_mode.name === modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(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;
|
return false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user