gantt-task-react-powern 0.6.30 → 0.6.32
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/dist/helpers/date-helper.d.ts +16 -0
- package/dist/index.js +130 -54
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +130 -54
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,22 @@ declare type DateHelperScales = "year" | "quarter" | "month" | "day" | "hour" |
|
|
|
5
5
|
export declare const getCachedDateTimeFormat: (locString: string | string[], opts?: DateTimeFormatOptions) => DateTimeFormat;
|
|
6
6
|
export declare const addToDate: (date: Date, quantity: number, scale: DateHelperScales) => Date;
|
|
7
7
|
export declare const startOfDate: (date: Date, scale: DateHelperScales) => Date;
|
|
8
|
+
/**
|
|
9
|
+
* Default number of columns the chart aims to render across the chart pane
|
|
10
|
+
* for each view mode. The Gantt component sizes columns so that this many
|
|
11
|
+
* fit at the current pane width when the view mode is selected.
|
|
12
|
+
*
|
|
13
|
+
* Modes not listed (Hour / QuarterDay / HalfDay / Year) fall through to the
|
|
14
|
+
* legacy `columnWidth` default.
|
|
15
|
+
*/
|
|
16
|
+
export declare const VIEW_MODE_DEFAULT_VISIBLE_COUNT: Partial<Record<ViewMode, number>>;
|
|
17
|
+
/**
|
|
18
|
+
* Maximum number of columns the chart will show at once, even when the user
|
|
19
|
+
* widens the chart pane with the resize bar. The Gantt component clamps
|
|
20
|
+
* column width upward so visible count never exceeds this — overflow becomes
|
|
21
|
+
* horizontal scroll.
|
|
22
|
+
*/
|
|
23
|
+
export declare const VIEW_MODE_MAX_VISIBLE_COUNT: Partial<Record<ViewMode, number>>;
|
|
8
24
|
export declare const ganttDateRange: (tasks: Task[], viewMode: ViewMode, preStepsCount: number, quarterStart?: number) => Date[];
|
|
9
25
|
export declare const seedDates: (startDate: Date, endDate: Date, viewMode: ViewMode) => Date[];
|
|
10
26
|
export declare const getLocaleMonth: (date: Date, locale: string) => string;
|
package/dist/index.js
CHANGED
|
@@ -75,6 +75,7 @@ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
|
|
|
75
75
|
ViewMode["Year"] = "Year";
|
|
76
76
|
})(exports.ViewMode || (exports.ViewMode = {}));
|
|
77
77
|
|
|
78
|
+
var _VIEW_MODE_DEFAULT_VI, _VIEW_MODE_MAX_VISIBL;
|
|
78
79
|
var intlDTCache = {};
|
|
79
80
|
var getCachedDateTimeFormat = function getCachedDateTimeFormat(locString, opts) {
|
|
80
81
|
if (opts === void 0) {
|
|
@@ -116,6 +117,8 @@ var getFiscalQuarterStartDate = function getFiscalQuarterStartDate(date, quarter
|
|
|
116
117
|
return new Date(year, qStartMonth, 1);
|
|
117
118
|
};
|
|
118
119
|
|
|
120
|
+
var VIEW_MODE_DEFAULT_VISIBLE_COUNT = (_VIEW_MODE_DEFAULT_VI = {}, _VIEW_MODE_DEFAULT_VI[exports.ViewMode.Day] = 14, _VIEW_MODE_DEFAULT_VI[exports.ViewMode.Week] = 6, _VIEW_MODE_DEFAULT_VI[exports.ViewMode.Month] = 6, _VIEW_MODE_DEFAULT_VI[exports.ViewMode.Quarter] = 4, _VIEW_MODE_DEFAULT_VI);
|
|
121
|
+
var VIEW_MODE_MAX_VISIBLE_COUNT = (_VIEW_MODE_MAX_VISIBL = {}, _VIEW_MODE_MAX_VISIBL[exports.ViewMode.Day] = 30, _VIEW_MODE_MAX_VISIBL[exports.ViewMode.Week] = 13, _VIEW_MODE_MAX_VISIBL[exports.ViewMode.Month] = 12, _VIEW_MODE_MAX_VISIBL[exports.ViewMode.Quarter] = 8, _VIEW_MODE_MAX_VISIBL);
|
|
119
122
|
var ganttDateRange = function ganttDateRange(tasks, viewMode, preStepsCount, quarterStart) {
|
|
120
123
|
var _tasks$, _tasks$2, _tasks$3, _tasks$4;
|
|
121
124
|
|
|
@@ -2045,8 +2048,8 @@ var drawPathAndTriangle = function drawPathAndTriangle(taskFrom, taskTo, rowHeig
|
|
|
2045
2048
|
|
|
2046
2049
|
if (t.actualSegments && t.actualSegments.length > 0) return t.actualSegments[0].x1;
|
|
2047
2050
|
var candidates = [];
|
|
2048
|
-
if (t.
|
|
2049
|
-
if (t.
|
|
2051
|
+
if (t.x2 > t.x1) candidates.push(t.x1);
|
|
2052
|
+
if (t.actualx2 > t.actualx1) candidates.push(t.actualx1);
|
|
2050
2053
|
return candidates.length > 0 ? Math.min.apply(Math, candidates) : 0;
|
|
2051
2054
|
};
|
|
2052
2055
|
|
|
@@ -2059,8 +2062,8 @@ var drawPathAndTriangle = function drawPathAndTriangle(taskFrom, taskTo, rowHeig
|
|
|
2059
2062
|
|
|
2060
2063
|
if (t.actualSegments && t.actualSegments.length > 0) return t.actualSegments[t.actualSegments.length - 1].x2;
|
|
2061
2064
|
var candidates = [];
|
|
2062
|
-
if (t.x2
|
|
2063
|
-
if (t.actualx2
|
|
2065
|
+
if (t.x2 > t.x1) candidates.push(t.x2);
|
|
2066
|
+
if (t.actualx2 > t.actualx1) candidates.push(t.actualx2);
|
|
2064
2067
|
return candidates.length > 0 ? Math.max.apply(Math, candidates) : 0;
|
|
2065
2068
|
};
|
|
2066
2069
|
|
|
@@ -3582,7 +3585,12 @@ var TaskGanttContent = function TaskGanttContent(_ref) {
|
|
|
3582
3585
|
|
|
3583
3586
|
var getArrows = function getArrows(isCritical, criticalPathType) {
|
|
3584
3587
|
return tasks.flatMap(function (_task) {
|
|
3585
|
-
var
|
|
3588
|
+
var a = ganttEvent.action;
|
|
3589
|
+
var isDraggingThis = (a === "move" || a === "start" || a === "end" || a === "progress") && !!ganttEvent.changedTask && ganttEvent.changedTask.id === _task.id;
|
|
3590
|
+
|
|
3591
|
+
var _live = isDraggingThis ? _extends({}, ganttEvent.changedTask, {
|
|
3592
|
+
y: _task.y
|
|
3593
|
+
}) : _task;
|
|
3586
3594
|
|
|
3587
3595
|
var task = _live.start.getTime() > 0 && _live.end.getTime() > 0 ? _live : undefined;
|
|
3588
3596
|
|
|
@@ -3591,13 +3599,16 @@ var TaskGanttContent = function TaskGanttContent(_ref) {
|
|
|
3591
3599
|
}
|
|
3592
3600
|
|
|
3593
3601
|
return task.barChildren.map(function (child) {
|
|
3594
|
-
|
|
3602
|
+
var taskTo = tasks[child.index];
|
|
3603
|
+
var fromDrawable = task.x2 > task.x1 || task.actualx2 > task.actualx1;
|
|
3604
|
+
var toDrawable = !!taskTo && (taskTo.x2 > taskTo.x1 || taskTo.actualx2 > taskTo.actualx1);
|
|
3605
|
+
|
|
3606
|
+
if (fromDrawable && toDrawable) {
|
|
3595
3607
|
var _task$criticalPathArr;
|
|
3596
3608
|
|
|
3597
3609
|
var criticalTask = (_task$criticalPathArr = task.criticalPathArrows) === null || _task$criticalPathArr === void 0 ? void 0 : _task$criticalPathArr.find(function (arrow) {
|
|
3598
|
-
return arrow.taskId ===
|
|
3610
|
+
return arrow.taskId === taskTo.id && (!!arrow.criticalPathType ? arrow.criticalPathType === criticalPathType : !criticalPathType);
|
|
3599
3611
|
});
|
|
3600
|
-
var taskTo = tasks[child.index];
|
|
3601
3612
|
var yFrom = task.y + taskHeight / 2;
|
|
3602
3613
|
var yTo = taskTo.y + taskHeight / 2;
|
|
3603
3614
|
var minY = Math.min(yFrom, yTo);
|
|
@@ -3609,9 +3620,9 @@ var TaskGanttContent = function TaskGanttContent(_ref) {
|
|
|
3609
3620
|
|
|
3610
3621
|
if (!!criticalTask === isCritical) {
|
|
3611
3622
|
return React__default.createElement(Arrow, {
|
|
3612
|
-
key: "Arrow from " + task.id + " to " +
|
|
3623
|
+
key: "Arrow from " + task.id + " to " + taskTo.id + (isCritical ? "-critical" : ""),
|
|
3613
3624
|
taskFrom: task,
|
|
3614
|
-
taskTo:
|
|
3625
|
+
taskTo: taskTo,
|
|
3615
3626
|
rowHeight: rowHeight,
|
|
3616
3627
|
dependencyType: child.dependencyType,
|
|
3617
3628
|
taskHeight: taskHeight,
|
|
@@ -3805,6 +3816,8 @@ var HorizontalScroll = function HorizontalScroll(_ref) {
|
|
|
3805
3816
|
};
|
|
3806
3817
|
|
|
3807
3818
|
var Gantt = function Gantt(_ref) {
|
|
3819
|
+
var _ref3;
|
|
3820
|
+
|
|
3808
3821
|
var tasks = _ref.tasks,
|
|
3809
3822
|
_ref$leafTasks = _ref.leafTasks,
|
|
3810
3823
|
leafTasks = _ref$leafTasks === void 0 ? [] : _ref$leafTasks,
|
|
@@ -3816,8 +3829,7 @@ var Gantt = function Gantt(_ref) {
|
|
|
3816
3829
|
endDate = _ref$endDate === void 0 ? new Date() : _ref$endDate,
|
|
3817
3830
|
_ref$headerHeight = _ref.headerHeight,
|
|
3818
3831
|
headerHeight = _ref$headerHeight === void 0 ? 50 : _ref$headerHeight,
|
|
3819
|
-
|
|
3820
|
-
columnWidth = _ref$columnWidth === void 0 ? 60 : _ref$columnWidth,
|
|
3832
|
+
columnWidthProp = _ref.columnWidth,
|
|
3821
3833
|
_ref$listCellWidth = _ref.listCellWidth,
|
|
3822
3834
|
listCellWidth = _ref$listCellWidth === void 0 ? "155px" : _ref$listCellWidth,
|
|
3823
3835
|
_ref$rowHeight = _ref.rowHeight,
|
|
@@ -3898,6 +3910,7 @@ var Gantt = function Gantt(_ref) {
|
|
|
3898
3910
|
var wrapperRef = React.useRef(null);
|
|
3899
3911
|
var taskListRef = React.useRef(null);
|
|
3900
3912
|
var isDraggingTable = React.useRef(false);
|
|
3913
|
+
var userResizedRef = React.useRef(false);
|
|
3901
3914
|
var dragStartX = React.useRef(0);
|
|
3902
3915
|
var dragStartWidth = React.useRef(0);
|
|
3903
3916
|
var dragMaxWidth = React.useRef(Infinity);
|
|
@@ -3954,6 +3967,7 @@ var Gantt = function Gantt(_ref) {
|
|
|
3954
3967
|
var _taskListRef$current$, _taskListRef$current, _ref2, _tableHorizontalConta, _tableHorizontalConta2, _tableInnerScrollRef$, _wrapperRef$current$o, _wrapperRef$current;
|
|
3955
3968
|
|
|
3956
3969
|
isDraggingTable.current = true;
|
|
3970
|
+
userResizedRef.current = true;
|
|
3957
3971
|
dragStartX.current = e.clientX;
|
|
3958
3972
|
dragStartWidth.current = tableContainerWidth != null ? tableContainerWidth : (_taskListRef$current$ = (_taskListRef$current = taskListRef.current) === null || _taskListRef$current === void 0 ? void 0 : _taskListRef$current.offsetWidth) != null ? _taskListRef$current$ : 0;
|
|
3959
3973
|
dragMaxWidth.current = (_ref2 = (_tableHorizontalConta = (_tableHorizontalConta2 = tableHorizontalContainerRef.current) === null || _tableHorizontalConta2 === void 0 ? void 0 : _tableHorizontalConta2.scrollWidth) != null ? _tableHorizontalConta : (_tableInnerScrollRef$ = tableInnerScrollRef.current) === null || _tableInnerScrollRef$ === void 0 ? void 0 : _tableInnerScrollRef$.scrollWidth) != null ? _ref2 : Math.max(100, ((_wrapperRef$current$o = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.offsetWidth) != null ? _wrapperRef$current$o : Infinity) - 200);
|
|
@@ -4020,38 +4034,99 @@ var Gantt = function Gantt(_ref) {
|
|
|
4020
4034
|
failedTask = _useState11[0],
|
|
4021
4035
|
setFailedTask = _useState11[1];
|
|
4022
4036
|
|
|
4037
|
+
var _useState12 = React.useState(null),
|
|
4038
|
+
computedColumnWidth = _useState12[0],
|
|
4039
|
+
setComputedColumnWidth = _useState12[1];
|
|
4040
|
+
|
|
4041
|
+
var computedForViewModeRef = React.useRef(null);
|
|
4042
|
+
React.useEffect(function () {
|
|
4043
|
+
if (columnWidthProp != null) return;
|
|
4044
|
+
if (svgContainerWidth <= 0) return;
|
|
4045
|
+
var minVisible = VIEW_MODE_DEFAULT_VISIBLE_COUNT[viewMode];
|
|
4046
|
+
if (!minVisible) return;
|
|
4047
|
+
var maxVisible = VIEW_MODE_MAX_VISIBLE_COUNT[viewMode];
|
|
4048
|
+
var prevViewMode = computedForViewModeRef.current;
|
|
4049
|
+
|
|
4050
|
+
if (prevViewMode != null && prevViewMode !== viewMode && computedColumnWidth != null) {
|
|
4051
|
+
var visible = svgContainerWidth / computedColumnWidth;
|
|
4052
|
+
var oldMin = VIEW_MODE_DEFAULT_VISIBLE_COUNT[prevViewMode];
|
|
4053
|
+
var oldMax = VIEW_MODE_MAX_VISIBLE_COUNT[prevViewMode];
|
|
4054
|
+
var _next = computedColumnWidth;
|
|
4055
|
+
|
|
4056
|
+
if (maxVisible && oldMin != null && oldMax != null && oldMax > oldMin) {
|
|
4057
|
+
var t = Math.min(1, Math.max(0, (visible - oldMin) / (oldMax - oldMin)));
|
|
4058
|
+
var targetVisible = minVisible + t * (maxVisible - minVisible);
|
|
4059
|
+
_next = Math.floor(svgContainerWidth / targetVisible);
|
|
4060
|
+
} else if (visible < minVisible) {
|
|
4061
|
+
_next = Math.floor(svgContainerWidth / minVisible);
|
|
4062
|
+
} else if (maxVisible && visible > maxVisible) {
|
|
4063
|
+
_next = Math.ceil(svgContainerWidth / maxVisible);
|
|
4064
|
+
}
|
|
4065
|
+
|
|
4066
|
+
_next = Math.max(20, _next);
|
|
4067
|
+
computedForViewModeRef.current = viewMode;
|
|
4068
|
+
userResizedRef.current = true;
|
|
4069
|
+
|
|
4070
|
+
if (_next !== computedColumnWidth) {
|
|
4071
|
+
setComputedColumnWidth(_next);
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
return;
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
var alreadySnappedForView = computedForViewModeRef.current === viewMode && computedColumnWidth != null;
|
|
4078
|
+
if (userResizedRef.current && alreadySnappedForView) return;
|
|
4079
|
+
var next = Math.max(20, Math.floor(svgContainerWidth / minVisible));
|
|
4080
|
+
computedForViewModeRef.current = viewMode;
|
|
4081
|
+
|
|
4082
|
+
if (next !== computedColumnWidth) {
|
|
4083
|
+
setComputedColumnWidth(next);
|
|
4084
|
+
}
|
|
4085
|
+
}, [viewMode, svgContainerWidth, columnWidthProp, computedColumnWidth]);
|
|
4086
|
+
var columnWidth = (_ref3 = columnWidthProp != null ? columnWidthProp : computedColumnWidth) != null ? _ref3 : 60;
|
|
4023
4087
|
var effectiveColumnWidth = React.useMemo(function () {
|
|
4024
4088
|
if (svgContainerWidth <= 0 || dateSetup.dates.length <= 0) return columnWidth;
|
|
4089
|
+
|
|
4090
|
+
if (columnWidthProp == null) {
|
|
4091
|
+
var maxVisible = VIEW_MODE_MAX_VISIBLE_COUNT[viewMode];
|
|
4092
|
+
|
|
4093
|
+
if (maxVisible) {
|
|
4094
|
+
return Math.max(columnWidth, Math.ceil(svgContainerWidth / maxVisible));
|
|
4095
|
+
}
|
|
4096
|
+
|
|
4097
|
+
return columnWidth;
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4025
4100
|
return Math.max(columnWidth, Math.ceil(svgContainerWidth / dateSetup.dates.length));
|
|
4026
|
-
}, [columnWidth, svgContainerWidth, dateSetup.dates.length]);
|
|
4101
|
+
}, [columnWidth, columnWidthProp, viewMode, svgContainerWidth, dateSetup.dates.length]);
|
|
4027
4102
|
var svgWidth = effectiveColumnWidth < 55 ? (dateSetup.dates.length + 0.5) * effectiveColumnWidth : dateSetup.dates.length * effectiveColumnWidth;
|
|
4028
4103
|
var ganttFullHeight = React.useMemo(function () {
|
|
4029
4104
|
return barTasks.length * rowHeight;
|
|
4030
4105
|
}, [barTasks.length, rowHeight]);
|
|
4031
4106
|
|
|
4032
|
-
var
|
|
4033
|
-
scrollY =
|
|
4034
|
-
setScrollY =
|
|
4107
|
+
var _useState13 = React.useState(0),
|
|
4108
|
+
scrollY = _useState13[0],
|
|
4109
|
+
setScrollY = _useState13[1];
|
|
4035
4110
|
|
|
4036
|
-
var
|
|
4037
|
-
scrollX =
|
|
4038
|
-
setScrollX =
|
|
4111
|
+
var _useState14 = React.useState(-1),
|
|
4112
|
+
scrollX = _useState14[0],
|
|
4113
|
+
setScrollX = _useState14[1];
|
|
4039
4114
|
|
|
4040
|
-
var
|
|
4041
|
-
ignoreScrollEvent =
|
|
4042
|
-
setIgnoreScrollEvent =
|
|
4043
|
-
|
|
4044
|
-
var _useState15 = React.useState(0),
|
|
4045
|
-
lastTouchX = _useState15[0],
|
|
4046
|
-
setLastTouchX = _useState15[1];
|
|
4115
|
+
var _useState15 = React.useState(false),
|
|
4116
|
+
ignoreScrollEvent = _useState15[0],
|
|
4117
|
+
setIgnoreScrollEvent = _useState15[1];
|
|
4047
4118
|
|
|
4048
4119
|
var _useState16 = React.useState(0),
|
|
4049
|
-
|
|
4050
|
-
|
|
4120
|
+
lastTouchX = _useState16[0],
|
|
4121
|
+
setLastTouchX = _useState16[1];
|
|
4122
|
+
|
|
4123
|
+
var _useState17 = React.useState(0),
|
|
4124
|
+
lastTouchY = _useState17[0],
|
|
4125
|
+
setLastTouchY = _useState17[1];
|
|
4051
4126
|
|
|
4052
|
-
var
|
|
4053
|
-
isProcessing =
|
|
4054
|
-
setIsProcessing =
|
|
4127
|
+
var _useState18 = React.useState(false),
|
|
4128
|
+
isProcessing = _useState18[0],
|
|
4129
|
+
setIsProcessing = _useState18[1];
|
|
4055
4130
|
|
|
4056
4131
|
var buffer = rowHeight * 10;
|
|
4057
4132
|
var visibleStartY = scrollY - buffer;
|
|
@@ -4291,7 +4366,7 @@ var Gantt = function Gantt(_ref) {
|
|
|
4291
4366
|
};
|
|
4292
4367
|
|
|
4293
4368
|
var handleScrollX = function handleScrollX(event) {
|
|
4294
|
-
if (scrollX !== event.currentTarget.scrollLeft) {
|
|
4369
|
+
if (scrollX !== event.currentTarget.scrollLeft && !ignoreScrollEvent) {
|
|
4295
4370
|
setScrollX(event.currentTarget.scrollLeft);
|
|
4296
4371
|
setIgnoreScrollEvent(true);
|
|
4297
4372
|
} else {
|
|
@@ -4601,6 +4676,9 @@ function topologicalOrderingHelper(taskID, taskMap, sortedTaskList) {
|
|
|
4601
4676
|
return true;
|
|
4602
4677
|
}
|
|
4603
4678
|
function getCriticalPaths(leafTasks) {
|
|
4679
|
+
leafTasks = leafTasks.filter(function (t) {
|
|
4680
|
+
return t.type !== "milestone" && (t.start.getTime() !== 0 || t.end.getTime() !== 0);
|
|
4681
|
+
});
|
|
4604
4682
|
var taskMap = {};
|
|
4605
4683
|
|
|
4606
4684
|
for (var i = 0; i < leafTasks.length; i++) {
|
|
@@ -4783,28 +4861,26 @@ function computeCriticalPath(taskID, taskMap) {
|
|
|
4783
4861
|
taskMap[taskID].paths[1].visited = false;
|
|
4784
4862
|
}
|
|
4785
4863
|
}
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
taskMap[taskID].paths[1].visited = false;
|
|
4807
|
-
}
|
|
4864
|
+
} else {
|
|
4865
|
+
var immediateChildDuration = taskMap[taskID].end - taskMap[taskID].start + depDuration - overlap - offTime;
|
|
4866
|
+
|
|
4867
|
+
if (taskMap[taskID].paths.length < 2) {
|
|
4868
|
+
taskMap[taskID].paths.push({
|
|
4869
|
+
duration: immediateChildDuration,
|
|
4870
|
+
task: dependents[j],
|
|
4871
|
+
parent: taskID,
|
|
4872
|
+
visited: false
|
|
4873
|
+
});
|
|
4874
|
+
} else if (immediateChildDuration > taskMap[taskID].paths[0].duration) {
|
|
4875
|
+
taskMap[taskID].paths[0].duration = immediateChildDuration;
|
|
4876
|
+
taskMap[taskID].paths[0].task = dependents[j];
|
|
4877
|
+
taskMap[taskID].paths[0].parent = taskID;
|
|
4878
|
+
taskMap[taskID].paths[0].visited = false;
|
|
4879
|
+
} else if (immediateChildDuration > taskMap[taskID].paths[1].duration) {
|
|
4880
|
+
taskMap[taskID].paths[1].duration = immediateChildDuration;
|
|
4881
|
+
taskMap[taskID].paths[1].task = dependents[j];
|
|
4882
|
+
taskMap[taskID].paths[1].parent = taskID;
|
|
4883
|
+
taskMap[taskID].paths[1].visited = false;
|
|
4808
4884
|
}
|
|
4809
4885
|
}
|
|
4810
4886
|
}
|