@workiom/frappe-gantt 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/frappe-gantt.css +1 -1
- package/dist/frappe-gantt.es.js +753 -512
- package/dist/frappe-gantt.umd.js +92 -35
- package/package.json +1 -1
- package/src/arrow.js +205 -14
- package/src/bar.js +44 -0
- package/src/defaults.js +1 -0
- package/src/index.js +262 -2
- package/src/styles/dark.css +27 -0
- package/src/styles/gantt.css +69 -0
- package/src/styles/light.css +6 -0
package/src/index.js
CHANGED
|
@@ -449,6 +449,9 @@ export default class Gantt {
|
|
|
449
449
|
this.bind_bar_events();
|
|
450
450
|
this.bind_task_column_resize();
|
|
451
451
|
this.bind_task_column_scroll();
|
|
452
|
+
if (this.options.allow_dependency_creation) {
|
|
453
|
+
this.bind_dependency_linking();
|
|
454
|
+
}
|
|
452
455
|
}
|
|
453
456
|
|
|
454
457
|
render() {
|
|
@@ -474,6 +477,12 @@ export default class Gantt {
|
|
|
474
477
|
append_to: this.$svg,
|
|
475
478
|
});
|
|
476
479
|
}
|
|
480
|
+
if (this.options.allow_dependency_creation) {
|
|
481
|
+
this.layers.linking = createSVG('g', {
|
|
482
|
+
class: 'linking',
|
|
483
|
+
append_to: this.$svg,
|
|
484
|
+
});
|
|
485
|
+
}
|
|
477
486
|
this.$extras = this.create_el({
|
|
478
487
|
classes: 'extras',
|
|
479
488
|
append_to: this.$container,
|
|
@@ -1078,6 +1087,7 @@ export default class Gantt {
|
|
|
1078
1087
|
|
|
1079
1088
|
make_arrows() {
|
|
1080
1089
|
this.arrows = [];
|
|
1090
|
+
this.active_arrow = null;
|
|
1081
1091
|
|
|
1082
1092
|
// Calculate critical path if enabled
|
|
1083
1093
|
if (this.options.critical_path) {
|
|
@@ -1346,7 +1356,7 @@ export default class Gantt {
|
|
|
1346
1356
|
'.grid-row, .grid-header, .ignored-bar, .holiday-highlight',
|
|
1347
1357
|
(e, delegatedTarget) => {
|
|
1348
1358
|
// Check if click is on a grid-row (not header or other elements)
|
|
1349
|
-
if (delegatedTarget && delegatedTarget.classList.contains('grid-row')) {
|
|
1359
|
+
if (delegatedTarget && (delegatedTarget.classList.contains('grid-row') || delegatedTarget.classList.contains('ignored-bar') || delegatedTarget.classList.contains('holiday-highlight'))) {
|
|
1350
1360
|
// Get the click position relative to the SVG
|
|
1351
1361
|
const svg = this.$svg;
|
|
1352
1362
|
const pt = svg.createSVGPoint();
|
|
@@ -1370,6 +1380,13 @@ export default class Gantt {
|
|
|
1370
1380
|
this.config.unit
|
|
1371
1381
|
);
|
|
1372
1382
|
|
|
1383
|
+
// If weekend/ignored skipping is enabled, advance to next non-ignored day
|
|
1384
|
+
if (this.config.ignored_function) {
|
|
1385
|
+
while (this.config.ignored_function(clicked_date)) {
|
|
1386
|
+
clicked_date = date_utils.add(clicked_date, 1, 'day');
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1373
1390
|
// Set start date to clicked date and end date to 1 day after
|
|
1374
1391
|
task._start = clicked_date;
|
|
1375
1392
|
task._end = date_utils.add(clicked_date, 1, 'day');
|
|
@@ -1454,6 +1471,7 @@ export default class Gantt {
|
|
|
1454
1471
|
let parent_bar_id = null;
|
|
1455
1472
|
let bars = []; // instanceof Bar
|
|
1456
1473
|
this.bar_being_dragged = null;
|
|
1474
|
+
this.active_arrow = null;
|
|
1457
1475
|
|
|
1458
1476
|
const action_in_progress = () =>
|
|
1459
1477
|
is_dragging || is_resizing_left || is_resizing_right;
|
|
@@ -1462,6 +1480,11 @@ export default class Gantt {
|
|
|
1462
1480
|
if (e.target.classList.contains('grid-row')) this.unselect_all();
|
|
1463
1481
|
};
|
|
1464
1482
|
|
|
1483
|
+
if (!this._document_click_handler) {
|
|
1484
|
+
this._document_click_handler = () => this.set_active_arrow(null);
|
|
1485
|
+
document.addEventListener('click', this._document_click_handler);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1465
1488
|
let pos = 0;
|
|
1466
1489
|
$.on(this.$svg, 'mousemove', '.bar-wrapper, .handle', (e) => {
|
|
1467
1490
|
if (
|
|
@@ -1472,6 +1495,7 @@ export default class Gantt {
|
|
|
1472
1495
|
});
|
|
1473
1496
|
|
|
1474
1497
|
$.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {
|
|
1498
|
+
if (e.target.classList.contains('connector-circle')) return;
|
|
1475
1499
|
const bar_wrapper = $.closest('.bar-wrapper', element);
|
|
1476
1500
|
if (element.classList.contains('left')) {
|
|
1477
1501
|
is_resizing_left = true;
|
|
@@ -1938,7 +1962,6 @@ export default class Gantt {
|
|
|
1938
1962
|
}
|
|
1939
1963
|
|
|
1940
1964
|
let dx = now_x - x_on_start;
|
|
1941
|
-
console.log($bar_progress);
|
|
1942
1965
|
if (dx > $bar_progress.max_dx) {
|
|
1943
1966
|
dx = $bar_progress.max_dx;
|
|
1944
1967
|
}
|
|
@@ -1965,6 +1988,229 @@ export default class Gantt {
|
|
|
1965
1988
|
});
|
|
1966
1989
|
}
|
|
1967
1990
|
|
|
1991
|
+
bind_dependency_linking() {
|
|
1992
|
+
this.is_linking = false;
|
|
1993
|
+
this.linking_source_bar = null;
|
|
1994
|
+
this.linking_source_endpoint = null;
|
|
1995
|
+
this.linking_temp_line = null;
|
|
1996
|
+
this.linking_snap_badge = null;
|
|
1997
|
+
|
|
1998
|
+
$.on(this.$svg, 'mousedown', '.connector-circle', (e, circle) => {
|
|
1999
|
+
const bar_wrapper = $.closest('.bar-wrapper', circle);
|
|
2000
|
+
if (!bar_wrapper) return;
|
|
2001
|
+
const bar_id = bar_wrapper.getAttribute('data-id');
|
|
2002
|
+
const source_bar = this.get_bar(bar_id);
|
|
2003
|
+
if (!source_bar) return;
|
|
2004
|
+
|
|
2005
|
+
this.is_linking = true;
|
|
2006
|
+
this.linking_source_bar = source_bar;
|
|
2007
|
+
this.linking_source_endpoint = circle.getAttribute('data-endpoint');
|
|
2008
|
+
|
|
2009
|
+
const cx = parseFloat(circle.getAttribute('cx'));
|
|
2010
|
+
const cy = parseFloat(circle.getAttribute('cy'));
|
|
2011
|
+
|
|
2012
|
+
this.linking_temp_line = createSVG('line', {
|
|
2013
|
+
x1: cx,
|
|
2014
|
+
y1: cy,
|
|
2015
|
+
x2: cx,
|
|
2016
|
+
y2: cy,
|
|
2017
|
+
class: 'linking-temp-line',
|
|
2018
|
+
append_to: this.layers.linking,
|
|
2019
|
+
});
|
|
2020
|
+
});
|
|
2021
|
+
|
|
2022
|
+
$.on(this.$svg, 'mousemove', (e) => {
|
|
2023
|
+
if (!this.is_linking || !this.linking_temp_line) return;
|
|
2024
|
+
const pt = this.$svg.createSVGPoint();
|
|
2025
|
+
pt.x = e.clientX;
|
|
2026
|
+
pt.y = e.clientY;
|
|
2027
|
+
const svgP = pt.matrixTransform(this.$svg.getScreenCTM().inverse());
|
|
2028
|
+
this.linking_temp_line.setAttribute('x2', svgP.x);
|
|
2029
|
+
this.linking_temp_line.setAttribute('y2', svgP.y);
|
|
2030
|
+
});
|
|
2031
|
+
|
|
2032
|
+
$.on(this.$svg, 'mouseover', '.connector-circle', (e, circle) => {
|
|
2033
|
+
if (!this.is_linking) return;
|
|
2034
|
+
const bar_wrapper = $.closest('.bar-wrapper', circle);
|
|
2035
|
+
if (!bar_wrapper) return;
|
|
2036
|
+
const bar_id = bar_wrapper.getAttribute('data-id');
|
|
2037
|
+
if (bar_id === this.linking_source_bar.task.id) return;
|
|
2038
|
+
|
|
2039
|
+
circle.setAttribute('r', '9');
|
|
2040
|
+
if (this.linking_temp_line) {
|
|
2041
|
+
this.linking_temp_line.classList.add('snap');
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
if (!this.linking_snap_badge) {
|
|
2045
|
+
const to_ep = circle.getAttribute('data-endpoint');
|
|
2046
|
+
const type = this._resolve_dependency_type(
|
|
2047
|
+
this.linking_source_endpoint,
|
|
2048
|
+
to_ep,
|
|
2049
|
+
);
|
|
2050
|
+
const abbr = { 'finish-to-start': 'FS', 'start-to-start': 'SS', 'finish-to-finish': 'FF', 'start-to-finish': 'SF' }[type] || 'FS';
|
|
2051
|
+
const cx = parseFloat(circle.getAttribute('cx'));
|
|
2052
|
+
const cy = parseFloat(circle.getAttribute('cy'));
|
|
2053
|
+
this.linking_snap_badge = createSVG('text', {
|
|
2054
|
+
x: cx + 12,
|
|
2055
|
+
y: cy - 10,
|
|
2056
|
+
class: 'linking-snap-badge',
|
|
2057
|
+
append_to: this.layers.linking,
|
|
2058
|
+
});
|
|
2059
|
+
this.linking_snap_badge.textContent = abbr;
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
$.on(this.$svg, 'mouseout', '.connector-circle', (e, circle) => {
|
|
2064
|
+
if (!this.is_linking) return;
|
|
2065
|
+
circle.setAttribute('r', '4');
|
|
2066
|
+
if (this.linking_temp_line) {
|
|
2067
|
+
this.linking_temp_line.classList.remove('snap');
|
|
2068
|
+
}
|
|
2069
|
+
if (this.linking_snap_badge) {
|
|
2070
|
+
this.linking_snap_badge.remove();
|
|
2071
|
+
this.linking_snap_badge = null;
|
|
2072
|
+
}
|
|
2073
|
+
});
|
|
2074
|
+
|
|
2075
|
+
$.on(this.$svg, 'mouseup', '.connector-circle', (e, circle) => {
|
|
2076
|
+
if (!this.is_linking) return;
|
|
2077
|
+
const bar_wrapper = $.closest('.bar-wrapper', circle);
|
|
2078
|
+
if (!bar_wrapper) return;
|
|
2079
|
+
const bar_id = bar_wrapper.getAttribute('data-id');
|
|
2080
|
+
if (bar_id !== this.linking_source_bar.task.id) {
|
|
2081
|
+
const to_bar = this.get_bar(bar_id);
|
|
2082
|
+
const to_endpoint = circle.getAttribute('data-endpoint');
|
|
2083
|
+
if (to_bar) {
|
|
2084
|
+
this._commit_dependency(to_bar, to_endpoint);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
// _cancel_linking() is called by the document mouseup handler
|
|
2088
|
+
});
|
|
2089
|
+
|
|
2090
|
+
document.addEventListener('mouseup', () => {
|
|
2091
|
+
if (!this.is_linking) return;
|
|
2092
|
+
this._cancel_linking();
|
|
2093
|
+
});
|
|
2094
|
+
|
|
2095
|
+
document.addEventListener('keydown', (e) => {
|
|
2096
|
+
if (
|
|
2097
|
+
(e.key === 'Delete' || e.key === 'Backspace') &&
|
|
2098
|
+
this.active_arrow
|
|
2099
|
+
) {
|
|
2100
|
+
const tag = e.target.tagName;
|
|
2101
|
+
if (tag === 'INPUT' || tag === 'TEXTAREA' || e.target.isContentEditable) return;
|
|
2102
|
+
e.preventDefault();
|
|
2103
|
+
this.delete_dependency(this.active_arrow);
|
|
2104
|
+
}
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
_resolve_dependency_type(from_endpoint, to_endpoint) {
|
|
2109
|
+
if (from_endpoint === 'end' && to_endpoint === 'start') return 'finish-to-start';
|
|
2110
|
+
if (from_endpoint === 'start' && to_endpoint === 'start') return 'start-to-start';
|
|
2111
|
+
if (from_endpoint === 'end' && to_endpoint === 'end') return 'finish-to-finish';
|
|
2112
|
+
if (from_endpoint === 'start' && to_endpoint === 'end') return 'start-to-finish';
|
|
2113
|
+
return 'finish-to-start';
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
_commit_dependency(to_bar, to_endpoint) {
|
|
2117
|
+
const from_task = this.linking_source_bar.task;
|
|
2118
|
+
const to_task = to_bar.task;
|
|
2119
|
+
const type = this._resolve_dependency_type(
|
|
2120
|
+
this.linking_source_endpoint,
|
|
2121
|
+
to_endpoint,
|
|
2122
|
+
);
|
|
2123
|
+
|
|
2124
|
+
// Find any existing dependency from the same source task (any type)
|
|
2125
|
+
const existing = to_task.dependencies.find((d) => d.id === from_task.id);
|
|
2126
|
+
const existing_type = existing
|
|
2127
|
+
? existing.type || this.options.dependencies_type || 'finish-to-start'
|
|
2128
|
+
: null;
|
|
2129
|
+
|
|
2130
|
+
// Remove existing connection between this pair (if any)
|
|
2131
|
+
const deps_without_existing = to_task.dependencies.filter(
|
|
2132
|
+
(d) => d.id !== from_task.id,
|
|
2133
|
+
);
|
|
2134
|
+
|
|
2135
|
+
if (existing_type === type) {
|
|
2136
|
+
// Same type drawn again — toggle off (just remove)
|
|
2137
|
+
this.update_task(to_task.id, { dependencies: deps_without_existing });
|
|
2138
|
+
if (this.options.on_dependency_delete) {
|
|
2139
|
+
this.options.on_dependency_delete(from_task, to_task, type);
|
|
2140
|
+
}
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
// Remove reverse dependency if it exists (prevents cycles)
|
|
2145
|
+
const reverse = from_task.dependencies?.find((d) => d.id === to_task.id);
|
|
2146
|
+
if (reverse) {
|
|
2147
|
+
const reverse_type =
|
|
2148
|
+
reverse.type || this.options.dependencies_type || 'finish-to-start';
|
|
2149
|
+
this.update_task(from_task.id, {
|
|
2150
|
+
dependencies: from_task.dependencies.filter((d) => d.id !== to_task.id),
|
|
2151
|
+
});
|
|
2152
|
+
if (this.options.on_dependency_delete) {
|
|
2153
|
+
this.options.on_dependency_delete(to_task, from_task, reverse_type);
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
// Different type (or no prior connection) — replace with new
|
|
2158
|
+
const new_deps = [...deps_without_existing, { id: from_task.id, type }];
|
|
2159
|
+
this.update_task(to_task.id, { dependencies: new_deps });
|
|
2160
|
+
|
|
2161
|
+
if (existing) {
|
|
2162
|
+
if (this.options.on_dependency_changed) {
|
|
2163
|
+
this.options.on_dependency_changed(
|
|
2164
|
+
from_task,
|
|
2165
|
+
to_task,
|
|
2166
|
+
existing_type,
|
|
2167
|
+
type,
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
} else {
|
|
2171
|
+
if (this.options.on_dependency_create) {
|
|
2172
|
+
this.options.on_dependency_create(from_task, to_task, type);
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
_cancel_linking() {
|
|
2178
|
+
if (this.linking_temp_line) {
|
|
2179
|
+
this.linking_temp_line.remove();
|
|
2180
|
+
this.linking_temp_line = null;
|
|
2181
|
+
}
|
|
2182
|
+
if (this.linking_snap_badge) {
|
|
2183
|
+
this.linking_snap_badge.remove();
|
|
2184
|
+
this.linking_snap_badge = null;
|
|
2185
|
+
}
|
|
2186
|
+
this.$svg
|
|
2187
|
+
.querySelectorAll('.connector-circle[r="9"]')
|
|
2188
|
+
.forEach((el) => el.setAttribute('r', '4'));
|
|
2189
|
+
|
|
2190
|
+
this.is_linking = false;
|
|
2191
|
+
this.linking_source_bar = null;
|
|
2192
|
+
this.linking_source_endpoint = null;
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
delete_dependency(arrow) {
|
|
2196
|
+
const from_task = arrow.from_task.task;
|
|
2197
|
+
const to_task = arrow.to_task.task;
|
|
2198
|
+
const arrow_type = arrow.dependency_type;
|
|
2199
|
+
|
|
2200
|
+
const new_deps = to_task.dependencies.filter((d) => {
|
|
2201
|
+
const dep_type =
|
|
2202
|
+
d.type || this.options.dependencies_type || 'finish-to-start';
|
|
2203
|
+
return !(d.id === from_task.id && dep_type === arrow_type);
|
|
2204
|
+
});
|
|
2205
|
+
|
|
2206
|
+
this.set_active_arrow(null);
|
|
2207
|
+
this.update_task(to_task.id, { dependencies: new_deps });
|
|
2208
|
+
|
|
2209
|
+
if (this.options.on_dependency_delete) {
|
|
2210
|
+
this.options.on_dependency_delete(from_task, to_task, arrow_type);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
|
|
1968
2214
|
get_all_dependent_tasks(task_id) {
|
|
1969
2215
|
let out = [];
|
|
1970
2216
|
let to_process = [task_id];
|
|
@@ -2026,6 +2272,20 @@ export default class Gantt {
|
|
|
2026
2272
|
}
|
|
2027
2273
|
}
|
|
2028
2274
|
|
|
2275
|
+
set_active_arrow(arrow) {
|
|
2276
|
+
if (this.active_arrow === arrow) return;
|
|
2277
|
+
if (this.active_arrow) {
|
|
2278
|
+
this.active_arrow.deactivate();
|
|
2279
|
+
}
|
|
2280
|
+
this.active_arrow = arrow;
|
|
2281
|
+
if (arrow) {
|
|
2282
|
+
arrow.activate();
|
|
2283
|
+
if (this.options.on_arrow_click) {
|
|
2284
|
+
this.options.on_arrow_click(arrow.from_task.task, arrow.to_task.task);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2029
2289
|
unselect_all() {
|
|
2030
2290
|
if (this.popup) this.popup.parent.classList.add('hide');
|
|
2031
2291
|
this.$container
|
package/src/styles/dark.css
CHANGED
|
@@ -11,8 +11,14 @@
|
|
|
11
11
|
--g-arrow-hover-color-dark: #60a5fa;
|
|
12
12
|
--g-arrow-critical-color-dark: #f5c044;
|
|
13
13
|
--g-arrow-invalid-color-dark: #ff7676;
|
|
14
|
+
--g-arrow-type-label-bg-dark: #4a4a4a;
|
|
15
|
+
--g-arrow-type-label-color-dark: #fff;
|
|
14
16
|
--g-resize-handle-hover-dark: rgba(96, 165, 250, 0.4);
|
|
15
17
|
--g-resize-handle-active-dark: rgba(96, 165, 250, 0.6);
|
|
18
|
+
--g-connector-start-color-dark: #4ade80;
|
|
19
|
+
--g-connector-end-color-dark: #fb923c;
|
|
20
|
+
--g-connector-linking-color-dark: #818cf8;
|
|
21
|
+
--g-connector-fill-dark: #ffffff;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
.dark > .gantt-container .gantt {
|
|
@@ -44,11 +50,27 @@
|
|
|
44
50
|
stroke: var(--g-arrow-hover-color-dark);
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
& .arrow-active {
|
|
54
|
+
stroke: var(--g-arrow-hover-color-dark);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
& .arrow-type-label rect {
|
|
58
|
+
fill: var(--g-arrow-type-label-bg-dark);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
& .arrow-type-label text {
|
|
62
|
+
fill: var(--g-arrow-type-label-color-dark);
|
|
63
|
+
}
|
|
64
|
+
|
|
47
65
|
& .bar {
|
|
48
66
|
fill: var(--g-bar-color-dark);
|
|
49
67
|
stroke: none;
|
|
50
68
|
}
|
|
51
69
|
|
|
70
|
+
& .bar-wrapper .bar.bar-arrow-active {
|
|
71
|
+
outline-color: var(--g-arrow-hover-color-dark);
|
|
72
|
+
}
|
|
73
|
+
|
|
52
74
|
& .bar-progress {
|
|
53
75
|
fill: var(--g-progress-color);
|
|
54
76
|
}
|
|
@@ -87,6 +109,11 @@
|
|
|
87
109
|
}
|
|
88
110
|
}
|
|
89
111
|
}
|
|
112
|
+
|
|
113
|
+
--g-connector-start-color: var(--g-connector-start-color-dark);
|
|
114
|
+
--g-connector-end-color: var(--g-connector-end-color-dark);
|
|
115
|
+
--g-connector-linking-color: var(--g-connector-linking-color-dark);
|
|
116
|
+
--g-connector-fill: var(--g-connector-fill-dark);
|
|
90
117
|
}
|
|
91
118
|
|
|
92
119
|
.dark > .gantt-container {
|
package/src/styles/gantt.css
CHANGED
|
@@ -291,6 +291,26 @@
|
|
|
291
291
|
stroke: var(--g-arrow-hover-color);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
& .arrow-active {
|
|
295
|
+
stroke: var(--g-arrow-hover-color);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
& .arrow-type-label {
|
|
299
|
+
stroke-width: 0;
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
& .arrow-type-label rect {
|
|
304
|
+
fill: var(--g-arrow-type-label-bg);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
& .arrow-type-label text {
|
|
308
|
+
fill: var(--g-arrow-type-label-color);
|
|
309
|
+
font-size: 10px;
|
|
310
|
+
font-weight: 600;
|
|
311
|
+
font-family: inherit;
|
|
312
|
+
pointer-events: none;
|
|
313
|
+
}
|
|
294
314
|
|
|
295
315
|
& .bar-wrapper .bar {
|
|
296
316
|
fill: var(--g-bar-color);
|
|
@@ -299,6 +319,12 @@
|
|
|
299
319
|
transition: stroke-width 0.3s ease;
|
|
300
320
|
}
|
|
301
321
|
|
|
322
|
+
& .bar-wrapper .bar.bar-arrow-active {
|
|
323
|
+
outline-color: var(--g-arrow-hover-color);
|
|
324
|
+
outline-width: 2px;
|
|
325
|
+
outline-style: solid;
|
|
326
|
+
}
|
|
327
|
+
|
|
302
328
|
& .bar-wrapper .bar.bar-arrow-critical {
|
|
303
329
|
outline-color: var(--g-arrow-critical-color);
|
|
304
330
|
}
|
|
@@ -372,6 +398,28 @@
|
|
|
372
398
|
display: block;
|
|
373
399
|
}
|
|
374
400
|
}
|
|
401
|
+
|
|
402
|
+
& .connector-circle {
|
|
403
|
+
fill: var(--g-connector-fill);
|
|
404
|
+
opacity: 0;
|
|
405
|
+
cursor: crosshair;
|
|
406
|
+
transition: opacity 0.2s ease;
|
|
407
|
+
pointer-events: all;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
& .connector-circle.connector-start {
|
|
411
|
+
stroke: var(--g-connector-start-color);
|
|
412
|
+
stroke-width: 2;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
& .connector-circle.connector-end {
|
|
416
|
+
stroke: var(--g-connector-end-color);
|
|
417
|
+
stroke-width: 2;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
&:hover .connector-circle {
|
|
421
|
+
opacity: 1;
|
|
422
|
+
}
|
|
375
423
|
}
|
|
376
424
|
|
|
377
425
|
& .add-task-icon {
|
|
@@ -404,6 +452,27 @@
|
|
|
404
452
|
}
|
|
405
453
|
}
|
|
406
454
|
}
|
|
455
|
+
|
|
456
|
+
& .linking-temp-line {
|
|
457
|
+
stroke: var(--g-connector-linking-color);
|
|
458
|
+
stroke-width: 2;
|
|
459
|
+
stroke-dasharray: 5, 4;
|
|
460
|
+
fill: none;
|
|
461
|
+
pointer-events: none;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
& .linking-temp-line.snap {
|
|
465
|
+
stroke: var(--g-connector-start-color);
|
|
466
|
+
stroke-dasharray: 0;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
& .linking-snap-badge {
|
|
470
|
+
font-size: 11px;
|
|
471
|
+
font-weight: 700;
|
|
472
|
+
fill: var(--g-connector-start-color);
|
|
473
|
+
pointer-events: none;
|
|
474
|
+
user-select: none;
|
|
475
|
+
}
|
|
407
476
|
}
|
|
408
477
|
|
|
409
478
|
/* Task Name Column */
|
package/src/styles/light.css
CHANGED
|
@@ -21,9 +21,15 @@
|
|
|
21
21
|
--g-row-border-color: #c7c7c7;
|
|
22
22
|
--g-today-highlight: #37352f;
|
|
23
23
|
--g-popup-actions: #ebeff2;
|
|
24
|
+
--g-arrow-type-label-bg: #dbdbdb;
|
|
25
|
+
--g-arrow-type-label-color: #000;
|
|
24
26
|
--g-weekend-highlight-color: #f7f7f7;
|
|
25
27
|
--g-task-column-bg: #ffffff;
|
|
26
28
|
--g-task-row-bg: #ffffff;
|
|
27
29
|
--g-resize-handle-hover: rgba(59, 130, 246, 0.3);
|
|
28
30
|
--g-resize-handle-active: rgba(59, 130, 246, 0.5);
|
|
31
|
+
--g-connector-start-color: #22c55e;
|
|
32
|
+
--g-connector-end-color: #f97316;
|
|
33
|
+
--g-connector-linking-color: #6366f1;
|
|
34
|
+
--g-connector-fill: #ffffff;
|
|
29
35
|
}
|