feat: make like notion; fix: bar rendering bugs

This commit is contained in:
Safwan Samsudeen 2025-01-06 14:59:19 +05:30
parent abeec1c363
commit 8b523c7125
4 changed files with 53 additions and 52 deletions

View File

@ -272,29 +272,34 @@ export default class Bar {
if (this.invalid || this.gantt.options.readonly) return; if (this.invalid || this.gantt.options.readonly) return;
const bar = this.$bar; const bar = this.$bar;
const handle_width = 8; const handle_width = 3;
this.handles = [];
if (!this.gantt.options.readonly_dates) { if (!this.gantt.options.readonly_dates) {
createSVG('rect', { this.handles.push(
x: bar.getX() + bar.getWidth() + handle_width - 4, createSVG('rect', {
y: bar.getY() + 1, x: bar.getEndX(),
width: handle_width, y: bar.getY() + 1,
height: this.height - 2, width: handle_width,
rx: 3, height: this.height - 2,
ry: 3, rx: 1,
class: 'handle right', ry: 1,
append_to: this.handle_group, class: 'handle right',
}); append_to: this.handle_group,
}),
);
createSVG('rect', { this.handles.push(
x: bar.getX() - handle_width - 4, createSVG('rect', {
y: bar.getY() + 1, x: bar.getX(),
width: handle_width, y: bar.getY() + 1,
height: this.height - 2, width: handle_width,
rx: 3, height: this.height - 2,
ry: 3, rx: 1,
class: 'handle left', ry: 1,
append_to: this.handle_group, class: 'handle left',
}); append_to: this.handle_group,
}),
);
} }
if (!this.gantt.options.readonly_progress) { if (!this.gantt.options.readonly_progress) {
const bar_progress = this.$bar_progress; const bar_progress = this.$bar_progress;
@ -305,6 +310,12 @@ export default class Bar {
class: 'handle progress', class: 'handle progress',
append_to: this.handle_group, append_to: this.handle_group,
}); });
this.handles.push(this.$handle_progress);
}
for (let handle of this.handles) {
$.on(handle, 'mouseenter', () => handle.classList.add('active'));
$.on(handle, 'mouseleave', () => handle.classList.remove('active'));
} }
} }
@ -327,6 +338,9 @@ export default class Bar {
this.popup_opened = false; this.popup_opened = false;
if (this.gantt.options.popup_on === 'click') { if (this.gantt.options.popup_on === 'click') {
$.on(this.group, 'click', (e) => { $.on(this.group, 'click', (e) => {
const posX = e.offsetX || e.layerX;
const cx = +this.$handle_progress.getAttribute('cx');
if (cx > posX - 1 && cx < posX + 1) return;
if (!this.popup_opened) if (!this.popup_opened)
this.gantt.show_popup({ this.gantt.show_popup({
x: e.offsetX || e.layerX, x: e.offsetX || e.layerX,
@ -342,6 +356,7 @@ export default class Bar {
} else { } else {
let timeout; let timeout;
$.on(this.group, 'mouseenter', (e) => { $.on(this.group, 'mouseenter', (e) => {
const pos = e.offsetX || e.layerX;
timeout = setTimeout(() => { timeout = setTimeout(() => {
this.gantt.show_popup({ this.gantt.show_popup({
x: e.offsetX || e.layerX, x: e.offsetX || e.layerX,
@ -390,15 +405,12 @@ export default class Bar {
const valid_x = xs.reduce((_, curr) => { const valid_x = xs.reduce((_, curr) => {
return x >= curr; return x >= curr;
}, x); }, x);
if (!valid_x) { if (!valid_x) return;
width = null;
return;
}
this.update_attr(bar, 'x', x); this.update_attr(bar, 'x', x);
this.x = x; this.x = x;
this.$date_highlight.style.left = x + 'px'; this.$date_highlight.style.left = x + 'px';
} }
if (width) { if (width > 0) {
this.update_attr(bar, 'width', width); this.update_attr(bar, 'width', width);
this.$date_highlight.style.width = width + 'px'; this.$date_highlight.style.width = width + 'px';
} }
@ -534,7 +546,7 @@ export default class Bar {
} }
compute_x() { compute_x() {
const { step, column_width } = this.gantt.config; const { 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;
@ -654,17 +666,11 @@ export default class Bar {
if (labelWidth > barWidth) { if (labelWidth > barWidth) {
label.classList.add('big'); label.classList.add('big');
if (img) { if (img) {
img.setAttribute('x', bar.getX() + bar.getWidth() + padding); img.setAttribute('x', bar.getEndX() + padding);
img_mask.setAttribute( img_mask.setAttribute('x', bar.getEndX() + padding);
'x', label.setAttribute('x', bar.getEndX() + x_offset_label_img);
bar.getX() + bar.getWidth() + padding,
);
label.setAttribute(
'x',
bar.getX() + bar.getWidth() + x_offset_label_img,
);
} else { } else {
label.setAttribute('x', bar.getX() + bar.getWidth() + padding); label.setAttribute('x', bar.getEndX() + padding);
} }
} else { } else {
label.classList.remove('big'); label.classList.remove('big');
@ -689,10 +695,10 @@ export default class Bar {
const bar = this.$bar; const bar = this.$bar;
this.handle_group this.handle_group
.querySelector('.handle.left') .querySelector('.handle.left')
.setAttribute('x', bar.getX() - 12); .setAttribute('x', bar.getX());
this.handle_group this.handle_group
.querySelector('.handle.right') .querySelector('.handle.right')
.setAttribute('x', bar.getEndX() + 4); .setAttribute('x', bar.getEndX());
const handle = this.group.querySelector('.handle.progress'); const handle = this.group.querySelector('.handle.progress');
handle && handle.setAttribute('cx', this.$bar_progress.getEndX()); handle && handle.setAttribute('cx', this.$bar_progress.getEndX());
} }

View File

@ -109,7 +109,7 @@ const DEFAULT_OPTIONS = {
auto_move_label: false, auto_move_label: false,
bar_corner_radius: 3, bar_corner_radius: 3,
bar_height: 30, bar_height: 30,
container_height: 350, container_height: 'auto',
column_width: null, column_width: null,
date_format: 'YYYY-MM-DD', date_format: 'YYYY-MM-DD',
upper_header_height: 45, upper_header_height: 45,

View File

@ -183,7 +183,7 @@
left: 0; left: 0;
opacity: 0; opacity: 0;
z-index: 1000; z-index: 1000;
background: --g-holiday-label-color; background: --g-weekend-label-color;
border-radius: 5px; border-radius: 5px;
padding: 2px 5px; padding: 2px 5px;
@ -287,10 +287,12 @@
& .handle { & .handle {
fill: var(--g-handle-color); fill: var(--g-handle-color);
cursor: ew-resize;
opacity: 0; opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
&.active {
cursor: ew-resize;
opacity: 1;
}
} }
& .handle.progress { & .handle.progress {
@ -300,13 +302,6 @@
& .bar-wrapper { & .bar-wrapper {
cursor: pointer; cursor: pointer;
&.active {
& .handle {
visibility: visible;
opacity: 1;
}
}
& .bar { & .bar {
-webkit-filter: drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.9)); -webkit-filter: drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.9));
filter: drop-shadow(3px 3px 2px rgba(17, 43, 66, 0.26)); filter: drop-shadow(3px 3px 2px rgba(17, 43, 66, 0.26));

View File

@ -10,8 +10,8 @@
--g-text-light: #fff; --g-text-light: #fff;
--g-text-dark: #171717; --g-text-dark: #171717;
--g-progress-color: #f3f3f3; --g-progress-color: #f3f3f3;
--g-handle-color: #dcdce4; --g-handle-color: #37352f;
--g-holiday-label-color: #dcdce4; --g-weekend-label-color: #dcdce4;
--g-expected-progress: #c4c4e9; --g-expected-progress: #c4c4e9;
--g-header-background: #ffffff; --g-header-background: #ffffff;
--g-row-color: #fdfdfd; --g-row-color: #fdfdfd;