akfatimeline 1.0.6 → 1.2.0
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/CHANGELOG.md +98 -35
- package/dist/Timeline.js +4309 -1677
- package/dist/components/Timeline/AutocompleteSelect.js +150 -0
- package/dist/components/Timeline/ContextMenu.js +149 -0
- package/dist/components/Timeline/DailyView.js +255 -0
- package/dist/components/Timeline/DatePickerComponent.js +13 -0
- package/{public/dist/dist → dist}/components/Timeline/DragAndDropHandler.js +34 -34
- package/dist/components/Timeline/EventBadge.js +26 -0
- package/dist/components/Timeline/EventDetailModal.js +138 -0
- package/dist/components/Timeline/EventIcon.js +47 -0
- package/dist/{dist/components → components}/Timeline/EventTooltip.js +206 -206
- package/dist/components/Timeline/FilterPanel.js +179 -0
- package/dist/{dist/components → components}/Timeline/Indicator.js +26 -26
- package/dist/components/Timeline/LoadingSpinner.js +48 -0
- package/dist/{dist/components → components}/Timeline/MasterHeader.js +104 -68
- package/{public/dist/dist → dist}/components/Timeline/Resources.js +53 -53
- package/dist/{dist/components → components}/Timeline/ResourcesHeader.js +14 -14
- package/dist/components/Timeline/Timeline.css +2491 -0
- package/dist/components/Timeline/Timeline.js +607 -0
- package/dist/{dist/components → components}/Timeline/TimelineCell.js +8 -8
- package/dist/components/Timeline/TimelineContent.js +838 -0
- package/{public/dist/dist → dist}/components/Timeline/TimelineEvents.js +114 -114
- package/dist/components/Timeline/TimelineHeader.js +54 -0
- package/{public/dist/dist → dist}/components/Timeline/TimelineMonthContainer.js +29 -29
- package/{public/dist/dist → dist}/components/Timeline/TimelineResources.js +16 -16
- package/{public/dist/dist → dist}/hooks/useDragAndDrop.js +80 -80
- package/dist/{dist/hooks → hooks}/useEventDragDrop.js +126 -126
- package/dist/hooks/useEventManagement.js +173 -0
- package/dist/hooks/useEventSelection.js +82 -0
- package/{public/dist/dist → dist}/hooks/useExtendEvent.js +28 -28
- package/dist/hooks/useKeyboardShortcuts.js +158 -0
- package/dist/hooks/useTouchGestures.js +90 -0
- package/dist/utils/conflictUtils.js +105 -0
- package/dist/{dist/utils → utils}/dateUtils.js +36 -36
- package/dist/{dist/utils → utils}/filterTimelineData.js +20 -20
- package/dist/utils/filterUtils.js +106 -0
- package/dist/utils/timeUtils.js +179 -0
- package/dist/{dist/utils → utils}/timelineUtils.js +39 -39
- package/dist/utils/viewModeUtils.js +54 -0
- package/package.json +89 -19
- package/src/App.js +300 -19
- package/src/components/Timeline/AutocompleteSelect.js +150 -0
- package/src/components/Timeline/ContextMenu.js +149 -0
- package/src/components/Timeline/DailyView.js +255 -0
- package/src/components/Timeline/DatePickerComponent.js +13 -17
- package/src/components/Timeline/DragAndDropHandler.js +34 -34
- package/src/components/Timeline/EventBadge.js +26 -0
- package/src/components/Timeline/EventDetailModal.js +138 -0
- package/src/components/Timeline/EventIcon.js +47 -0
- package/src/components/Timeline/EventTooltip.js +206 -206
- package/src/components/Timeline/FilterPanel.js +179 -0
- package/src/components/Timeline/Indicator.js +26 -26
- package/src/components/Timeline/LoadingSpinner.js +48 -0
- package/src/components/Timeline/MasterHeader.js +104 -68
- package/src/components/Timeline/Resources.js +53 -53
- package/src/components/Timeline/ResourcesHeader.js +14 -14
- package/src/components/Timeline/Timeline.css +2491 -616
- package/src/components/Timeline/Timeline.js +607 -309
- package/src/components/Timeline/TimelineCell.js +8 -8
- package/src/components/Timeline/TimelineContent.js +838 -446
- package/src/components/Timeline/TimelineEvents.js +114 -114
- package/src/components/Timeline/TimelineHeader.js +54 -43
- package/src/components/Timeline/TimelineMonthContainer.js +29 -29
- package/src/components/Timeline/TimelineResources.js +16 -16
- package/src/demo.css +4 -0
- package/src/hooks/useDragAndDrop.js +80 -80
- package/src/hooks/useEventDragDrop.js +126 -126
- package/src/hooks/useEventManagement.js +173 -0
- package/src/hooks/useEventSelection.js +82 -0
- package/src/hooks/useExtendEvent.js +28 -28
- package/src/hooks/useKeyboardShortcuts.js +158 -0
- package/src/hooks/useTouchGestures.js +90 -0
- package/src/index.js +1 -7
- package/src/library.js +26 -0
- package/src/utils/conflictUtils.js +105 -0
- package/src/utils/dateUtils.js +36 -36
- package/src/utils/filterTimelineData.js +20 -20
- package/src/utils/filterUtils.js +106 -0
- package/src/utils/timeUtils.js +179 -0
- package/src/utils/timelineUtils.js +39 -39
- package/src/utils/viewModeUtils.js +54 -0
- package/.babelrc +0 -6
- package/babel.config.json +0 -4
- package/dist/dist/components/Timeline/DatePickerComponent.js +0 -17
- package/dist/dist/components/Timeline/DragAndDropHandler.js +0 -35
- package/dist/dist/components/Timeline/Resources.js +0 -53
- package/dist/dist/components/Timeline/Timeline.css +0 -616
- package/dist/dist/components/Timeline/Timeline.js +0 -309
- package/dist/dist/components/Timeline/TimelineContent.js +0 -446
- package/dist/dist/components/Timeline/TimelineEvents.js +0 -114
- package/dist/dist/components/Timeline/TimelineHeader.js +0 -43
- package/dist/dist/components/Timeline/TimelineMonthContainer.js +0 -29
- package/dist/dist/components/Timeline/TimelineResources.js +0 -16
- package/dist/dist/hooks/useDragAndDrop.js +0 -80
- package/dist/dist/hooks/useExtendEvent.js +0 -28
- package/public/dist/Timeline.js +0 -3277
- package/public/dist/dist/components/Timeline/DatePickerComponent.js +0 -17
- package/public/dist/dist/components/Timeline/EventTooltip.js +0 -206
- package/public/dist/dist/components/Timeline/Indicator.js +0 -29
- package/public/dist/dist/components/Timeline/MasterHeader.js +0 -68
- package/public/dist/dist/components/Timeline/ResourcesHeader.js +0 -14
- package/public/dist/dist/components/Timeline/Timeline.css +0 -616
- package/public/dist/dist/components/Timeline/Timeline.js +0 -304
- package/public/dist/dist/components/Timeline/TimelineCell.js +0 -8
- package/public/dist/dist/components/Timeline/TimelineContent.js +0 -447
- package/public/dist/dist/components/Timeline/TimelineHeader.js +0 -43
- package/public/dist/dist/hooks/useEventDragDrop.js +0 -126
- package/public/dist/dist/utils/HorizontalVirtualScroll.js +0 -0
- package/public/dist/dist/utils/dateUtils.js +0 -36
- package/public/dist/dist/utils/filterTimelineData.js +0 -21
- package/public/dist/dist/utils/timelineUtils.js +0 -40
- package/public/favicon.ico +0 -0
- package/public/index kutuphane /304/261c/304/261n.html" +0 -43
- package/public/index tasarim icin.html +0 -20
- package/public/index.html +0 -43
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +0 -25
- package/public/robots.txt +0 -3
- package/src/App.css +0 -38
- package/src/App.test.js +0 -8
- package/src/dist/Timeline.js +0 -277
- package/src/index.css +0 -13
- package/src/logo.svg +0 -1
- package/src/reportWebVitals.js +0 -13
- package/src/setupTests.js +0 -5
- package/webpack.config.js +0 -49
- /package/dist/{dist/utils → utils}/HorizontalVirtualScroll.js +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// src/components/Timeline/FilterPanel.js (Demo Component)
|
|
2
|
+
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import './Timeline.css';
|
|
5
|
+
|
|
6
|
+
const FilterPanel = ({
|
|
7
|
+
events,
|
|
8
|
+
resources,
|
|
9
|
+
onFilterChange,
|
|
10
|
+
onClearFilters
|
|
11
|
+
}) => {
|
|
12
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
13
|
+
const [selectedResources, setSelectedResources] = useState([]);
|
|
14
|
+
const [selectedStatuses, setSelectedStatuses] = useState([]);
|
|
15
|
+
const [startDate, setStartDate] = useState('');
|
|
16
|
+
const [endDate, setEndDate] = useState('');
|
|
17
|
+
|
|
18
|
+
// Tüm unique status'leri bul
|
|
19
|
+
const allStatuses = [...new Set(events.map(e => e.status).filter(Boolean))];
|
|
20
|
+
|
|
21
|
+
const handleSearchChange = (value) => {
|
|
22
|
+
setSearchTerm(value);
|
|
23
|
+
applyFilters({
|
|
24
|
+
searchTerm: value,
|
|
25
|
+
resourceIds: selectedResources,
|
|
26
|
+
statuses: selectedStatuses,
|
|
27
|
+
startDate: startDate ? new Date(startDate) : null,
|
|
28
|
+
endDate: endDate ? new Date(endDate) : null,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const handleResourceToggle = (resourceId) => {
|
|
33
|
+
const newResources = selectedResources.includes(resourceId)
|
|
34
|
+
? selectedResources.filter(id => id !== resourceId)
|
|
35
|
+
: [...selectedResources, resourceId];
|
|
36
|
+
setSelectedResources(newResources);
|
|
37
|
+
applyFilters({
|
|
38
|
+
searchTerm,
|
|
39
|
+
resourceIds: newResources,
|
|
40
|
+
statuses: selectedStatuses,
|
|
41
|
+
startDate: startDate ? new Date(startDate) : null,
|
|
42
|
+
endDate: endDate ? new Date(endDate) : null,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const handleStatusToggle = (status) => {
|
|
47
|
+
const newStatuses = selectedStatuses.includes(status)
|
|
48
|
+
? selectedStatuses.filter(s => s !== status)
|
|
49
|
+
: [...selectedStatuses, status];
|
|
50
|
+
setSelectedStatuses(newStatuses);
|
|
51
|
+
applyFilters({
|
|
52
|
+
searchTerm,
|
|
53
|
+
resourceIds: selectedResources,
|
|
54
|
+
statuses: newStatuses,
|
|
55
|
+
startDate: startDate ? new Date(startDate) : null,
|
|
56
|
+
endDate: endDate ? new Date(endDate) : null,
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleDateChange = (type, value) => {
|
|
61
|
+
if (type === 'start') {
|
|
62
|
+
setStartDate(value);
|
|
63
|
+
applyFilters({
|
|
64
|
+
searchTerm,
|
|
65
|
+
resourceIds: selectedResources,
|
|
66
|
+
statuses: selectedStatuses,
|
|
67
|
+
startDate: value ? new Date(value) : null,
|
|
68
|
+
endDate: endDate ? new Date(endDate) : null,
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
setEndDate(value);
|
|
72
|
+
applyFilters({
|
|
73
|
+
searchTerm,
|
|
74
|
+
resourceIds: selectedResources,
|
|
75
|
+
statuses: selectedStatuses,
|
|
76
|
+
startDate: startDate ? new Date(startDate) : null,
|
|
77
|
+
endDate: value ? new Date(value) : null,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const applyFilters = (filters) => {
|
|
83
|
+
if (onFilterChange) {
|
|
84
|
+
onFilterChange(filters);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleClear = () => {
|
|
89
|
+
setSearchTerm('');
|
|
90
|
+
setSelectedResources([]);
|
|
91
|
+
setSelectedStatuses([]);
|
|
92
|
+
setStartDate('');
|
|
93
|
+
setEndDate('');
|
|
94
|
+
if (onClearFilters) {
|
|
95
|
+
onClearFilters();
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Tüm resource'ları düzleştir
|
|
100
|
+
const allResources = resources.flatMap(group => group.resources || []);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div className="filter-panel">
|
|
104
|
+
<div className="filter-panel-header">
|
|
105
|
+
<h3>Filtreler</h3>
|
|
106
|
+
<button onClick={handleClear} className="filter-clear-btn">
|
|
107
|
+
Temizle
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div className="filter-section">
|
|
112
|
+
<label>Arama</label>
|
|
113
|
+
<input
|
|
114
|
+
type="text"
|
|
115
|
+
placeholder="Event başlığına göre ara..."
|
|
116
|
+
value={searchTerm}
|
|
117
|
+
onChange={(e) => handleSearchChange(e.target.value)}
|
|
118
|
+
className="filter-search-input"
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="filter-section">
|
|
123
|
+
<label>Tarih Aralığı</label>
|
|
124
|
+
<div className="filter-date-range">
|
|
125
|
+
<input
|
|
126
|
+
type="date"
|
|
127
|
+
value={startDate}
|
|
128
|
+
onChange={(e) => handleDateChange('start', e.target.value)}
|
|
129
|
+
placeholder="Başlangıç"
|
|
130
|
+
className="filter-date-input"
|
|
131
|
+
/>
|
|
132
|
+
<span> - </span>
|
|
133
|
+
<input
|
|
134
|
+
type="date"
|
|
135
|
+
value={endDate}
|
|
136
|
+
onChange={(e) => handleDateChange('end', e.target.value)}
|
|
137
|
+
placeholder="Bitiş"
|
|
138
|
+
className="filter-date-input"
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div className="filter-section">
|
|
144
|
+
<label>Resource'lar</label>
|
|
145
|
+
<div className="filter-checkbox-group">
|
|
146
|
+
{allResources.map(resource => (
|
|
147
|
+
<label key={resource.id} className="filter-checkbox">
|
|
148
|
+
<input
|
|
149
|
+
type="checkbox"
|
|
150
|
+
checked={selectedResources.includes(resource.id)}
|
|
151
|
+
onChange={() => handleResourceToggle(resource.id)}
|
|
152
|
+
/>
|
|
153
|
+
<span>{resource.name || resource.id}</span>
|
|
154
|
+
</label>
|
|
155
|
+
))}
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<div className="filter-section">
|
|
160
|
+
<label>Status</label>
|
|
161
|
+
<div className="filter-checkbox-group">
|
|
162
|
+
{allStatuses.map(status => (
|
|
163
|
+
<label key={status} className="filter-checkbox">
|
|
164
|
+
<input
|
|
165
|
+
type="checkbox"
|
|
166
|
+
checked={selectedStatuses.includes(status)}
|
|
167
|
+
onChange={() => handleStatusToggle(status)}
|
|
168
|
+
/>
|
|
169
|
+
<span>{status}</span>
|
|
170
|
+
</label>
|
|
171
|
+
))}
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
export default FilterPanel;
|
|
179
|
+
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
const Indicator = ({ todayIndex, totalDays }) => {
|
|
4
|
-
if (todayIndex < 0 || todayIndex >= totalDays) {
|
|
5
|
-
return null; // Bugün timeline dışında ise çizgiyi gösterme
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
style={{
|
|
11
|
-
position: "absolute",
|
|
12
|
-
top: 0,
|
|
13
|
-
left: `calc(${(todayIndex + 0.5) / totalDays} * 100%)`, // Günün ortasına yerleştirmek için +0.5
|
|
14
|
-
width: "2px",
|
|
15
|
-
height: "100%",
|
|
16
|
-
backgroundColor: "transparent",
|
|
17
|
-
zIndex: 5,
|
|
18
|
-
borderStyle: "dashed", // Kesikli çizgi için
|
|
19
|
-
borderWidth: "0 0 0 2px", // Sadece sol tarafa kesikli çizgi
|
|
20
|
-
borderColor: "red",
|
|
21
|
-
}}
|
|
22
|
-
></div>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default Indicator;
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const Indicator = ({ todayIndex, totalDays }) => {
|
|
4
|
+
if (todayIndex < 0 || todayIndex >= totalDays) {
|
|
5
|
+
return null; // Bugün timeline dışında ise çizgiyi gösterme
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
style={{
|
|
11
|
+
position: "absolute",
|
|
12
|
+
top: 0,
|
|
13
|
+
left: `calc(${(todayIndex + 0.5) / totalDays} * 100%)`, // Günün ortasına yerleştirmek için +0.5
|
|
14
|
+
width: "2px",
|
|
15
|
+
height: "100%",
|
|
16
|
+
backgroundColor: "transparent",
|
|
17
|
+
zIndex: 5,
|
|
18
|
+
borderStyle: "dashed", // Kesikli çizgi için
|
|
19
|
+
borderWidth: "0 0 0 2px", // Sadece sol tarafa kesikli çizgi
|
|
20
|
+
borderColor: "red",
|
|
21
|
+
}}
|
|
22
|
+
></div>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default Indicator;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Timeline.css';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Loading Spinner Component
|
|
6
|
+
* Yükleme durumlarında gösterilir
|
|
7
|
+
*/
|
|
8
|
+
const LoadingSpinner = ({
|
|
9
|
+
size = 'medium', // 'small', 'medium', 'large'
|
|
10
|
+
type = 'spinner', // 'spinner', 'dots', 'pulse'
|
|
11
|
+
className = '',
|
|
12
|
+
overlay = false // Overlay gösterilsin mi?
|
|
13
|
+
}) => {
|
|
14
|
+
if (overlay) {
|
|
15
|
+
return (
|
|
16
|
+
<div className="loading-overlay">
|
|
17
|
+
<div className={`loading-spinner loading-spinner-${type} loading-spinner-${size} ${className}`}>
|
|
18
|
+
{type === 'spinner' && <div className="spinner-circle"></div>}
|
|
19
|
+
{type === 'dots' && (
|
|
20
|
+
<div className="dots-container">
|
|
21
|
+
<span></span>
|
|
22
|
+
<span></span>
|
|
23
|
+
<span></span>
|
|
24
|
+
</div>
|
|
25
|
+
)}
|
|
26
|
+
{type === 'pulse' && <div className="pulse-circle"></div>}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className={`loading-spinner loading-spinner-${type} loading-spinner-${size} ${className}`}>
|
|
34
|
+
{type === 'spinner' && <div className="spinner-circle"></div>}
|
|
35
|
+
{type === 'dots' && (
|
|
36
|
+
<div className="dots-container">
|
|
37
|
+
<span></span>
|
|
38
|
+
<span></span>
|
|
39
|
+
<span></span>
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
42
|
+
{type === 'pulse' && <div className="pulse-circle"></div>}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default LoadingSpinner;
|
|
48
|
+
|
|
@@ -1,68 +1,104 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import "./Timeline.css";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
import "./Timeline.css";
|
|
3
|
+
|
|
4
|
+
const MasterHeader = ({
|
|
5
|
+
selectedDate,
|
|
6
|
+
onDateSelect,
|
|
7
|
+
onToday,
|
|
8
|
+
onAdvance,
|
|
9
|
+
onRetreat,
|
|
10
|
+
onMonthAdvance,
|
|
11
|
+
onMonthRetreat,
|
|
12
|
+
dayRange,
|
|
13
|
+
setDayRange,
|
|
14
|
+
zoomLevel = 1.0,
|
|
15
|
+
setZoomLevel,
|
|
16
|
+
zoomOn = true,
|
|
17
|
+
minZoomLevel = 0.5,
|
|
18
|
+
maxZoomLevel = 3.0,
|
|
19
|
+
zoomStep = 0.25,
|
|
20
|
+
}) => {
|
|
21
|
+
const formattedDate = new Date(
|
|
22
|
+
selectedDate.getTime() + 24 * 60 * 60 * 1000 - selectedDate.getTimezoneOffset() * 60000
|
|
23
|
+
)
|
|
24
|
+
.toISOString()
|
|
25
|
+
.split("T")[0]; // YYYY-MM-DD formatı
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="master-header-container">
|
|
29
|
+
<div className="master-header-buttons">
|
|
30
|
+
<button className="master-header-btn" onClick={onMonthRetreat}>
|
|
31
|
+
1 Ay Geri
|
|
32
|
+
</button>
|
|
33
|
+
|
|
34
|
+
<button className="master-header-btn" onClick={onRetreat}>
|
|
35
|
+
5 Gün Geri
|
|
36
|
+
</button>
|
|
37
|
+
|
|
38
|
+
<input
|
|
39
|
+
type="date"
|
|
40
|
+
className="master-header-date-picker"
|
|
41
|
+
value={formattedDate} // Seçili tarih burada gösteriliyor
|
|
42
|
+
onChange={(e) => onDateSelect(e.target.value)} // Tarih seçimi
|
|
43
|
+
onKeyDown={(e) => e.preventDefault()} // Manuel girişleri engelle
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
<button className="master-header-btn" onClick={onAdvance}>
|
|
48
|
+
5 Gün İleri
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
<button className="master-header-btn" onClick={onMonthAdvance}>
|
|
52
|
+
1 Ay İleri
|
|
53
|
+
</button>
|
|
54
|
+
|
|
55
|
+
<button className="master-header-btn" onClick={onToday}>
|
|
56
|
+
Bugün
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<select
|
|
61
|
+
className="master-header-select"
|
|
62
|
+
value={dayRange}
|
|
63
|
+
onChange={(e) => setDayRange(parseInt(e.target.value, 10))}
|
|
64
|
+
>
|
|
65
|
+
<option value={30}>30 Gün</option>
|
|
66
|
+
<option value={60}>60 Gün</option>
|
|
67
|
+
<option value={90}>90 Gün</option>
|
|
68
|
+
</select>
|
|
69
|
+
|
|
70
|
+
{/* Zoom Kontrolleri */}
|
|
71
|
+
{zoomOn && setZoomLevel && (
|
|
72
|
+
<div className="master-header-zoom-controls">
|
|
73
|
+
<button
|
|
74
|
+
className="master-header-btn"
|
|
75
|
+
onClick={() => {
|
|
76
|
+
const newZoom = Math.max(minZoomLevel, zoomLevel - zoomStep);
|
|
77
|
+
setZoomLevel(newZoom);
|
|
78
|
+
}}
|
|
79
|
+
disabled={zoomLevel <= minZoomLevel}
|
|
80
|
+
title={`Zoom Out (${Math.round((zoomLevel - zoomStep) * 100)}%)`}
|
|
81
|
+
>
|
|
82
|
+
−
|
|
83
|
+
</button>
|
|
84
|
+
<span className="master-header-zoom-level">
|
|
85
|
+
{Math.round(zoomLevel * 100)}%
|
|
86
|
+
</span>
|
|
87
|
+
<button
|
|
88
|
+
className="master-header-btn"
|
|
89
|
+
onClick={() => {
|
|
90
|
+
const newZoom = Math.min(maxZoomLevel, zoomLevel + zoomStep);
|
|
91
|
+
setZoomLevel(newZoom);
|
|
92
|
+
}}
|
|
93
|
+
disabled={zoomLevel >= maxZoomLevel}
|
|
94
|
+
title={`Zoom In (${Math.round((zoomLevel + zoomStep) * 100)}%)`}
|
|
95
|
+
>
|
|
96
|
+
+
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default MasterHeader;
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
const Resources = ({
|
|
4
|
-
groupedResources = [], // Kaynakların listesi
|
|
5
|
-
collapsedGroups = {}, // Grupların açık/kapalı durumunu tutan nesne
|
|
6
|
-
toggleGroupCollapse, // Grupları açma/kapama fonksiyonu
|
|
7
|
-
resourceSettings = {
|
|
8
|
-
showIdAsName: false, // Varsayılan: `name` varsa onu göster, yoksa `id`
|
|
9
|
-
isGrouped: true, // Varsayılan: Gruplama açık
|
|
10
|
-
isCollapsible: true, // Varsayılan: Gruplar açılıp kapanabilir
|
|
11
|
-
},
|
|
12
|
-
}) => {
|
|
13
|
-
const { showIdAsName, isGrouped, isCollapsible } = resourceSettings;
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<div className="timeline-resources">
|
|
17
|
-
{isGrouped ? (
|
|
18
|
-
// Gruplama aktif
|
|
19
|
-
groupedResources.map((group, groupIndex) => (
|
|
20
|
-
<div key={groupIndex} className="resource-group">
|
|
21
|
-
{/* Grup Başlığı */}
|
|
22
|
-
<div
|
|
23
|
-
className="resource-group-header"
|
|
24
|
-
onClick={() => isCollapsible && toggleGroupCollapse(group.groupName)}
|
|
25
|
-
>
|
|
26
|
-
{group.groupName}{" "}
|
|
27
|
-
{isCollapsible && (collapsedGroups[group.groupName] ? "▲" : "▼")}
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
{/* Grup İçindeki Kaynaklar */}
|
|
31
|
-
{!collapsedGroups[group.groupName] &&
|
|
32
|
-
group.resources.map((resource, resourceIndex) => (
|
|
33
|
-
<div key={resourceIndex} className="resource-cell">
|
|
34
|
-
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
35
|
-
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
36
|
-
</div>
|
|
37
|
-
))}
|
|
38
|
-
</div>
|
|
39
|
-
))
|
|
40
|
-
) : (
|
|
41
|
-
// Gruplama yok
|
|
42
|
-
groupedResources.flatMap((group) => group.resources).map((resource, resourceIndex) => (
|
|
43
|
-
<div key={resourceIndex} className="resource-cell">
|
|
44
|
-
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
45
|
-
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
46
|
-
</div>
|
|
47
|
-
))
|
|
48
|
-
)}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export default Resources;
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const Resources = ({
|
|
4
|
+
groupedResources = [], // Kaynakların listesi
|
|
5
|
+
collapsedGroups = {}, // Grupların açık/kapalı durumunu tutan nesne
|
|
6
|
+
toggleGroupCollapse, // Grupları açma/kapama fonksiyonu
|
|
7
|
+
resourceSettings = {
|
|
8
|
+
showIdAsName: false, // Varsayılan: `name` varsa onu göster, yoksa `id`
|
|
9
|
+
isGrouped: true, // Varsayılan: Gruplama açık
|
|
10
|
+
isCollapsible: true, // Varsayılan: Gruplar açılıp kapanabilir
|
|
11
|
+
},
|
|
12
|
+
}) => {
|
|
13
|
+
const { showIdAsName, isGrouped, isCollapsible } = resourceSettings;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="timeline-resources">
|
|
17
|
+
{isGrouped ? (
|
|
18
|
+
// Gruplama aktif
|
|
19
|
+
groupedResources.map((group, groupIndex) => (
|
|
20
|
+
<div key={groupIndex} className="resource-group">
|
|
21
|
+
{/* Grup Başlığı */}
|
|
22
|
+
<div
|
|
23
|
+
className="resource-group-header"
|
|
24
|
+
onClick={() => isCollapsible && toggleGroupCollapse(group.groupName)}
|
|
25
|
+
>
|
|
26
|
+
{group.groupName}{" "}
|
|
27
|
+
{isCollapsible && (collapsedGroups[group.groupName] ? "▲" : "▼")}
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
{/* Grup İçindeki Kaynaklar */}
|
|
31
|
+
{!collapsedGroups[group.groupName] &&
|
|
32
|
+
group.resources.map((resource, resourceIndex) => (
|
|
33
|
+
<div key={resourceIndex} className="resource-cell">
|
|
34
|
+
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
35
|
+
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
36
|
+
</div>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
))
|
|
40
|
+
) : (
|
|
41
|
+
// Gruplama yok
|
|
42
|
+
groupedResources.flatMap((group) => group.resources).map((resource, resourceIndex) => (
|
|
43
|
+
<div key={resourceIndex} className="resource-cell">
|
|
44
|
+
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
45
|
+
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
46
|
+
</div>
|
|
47
|
+
))
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default Resources;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// ResourcesHeader.js
|
|
2
|
-
import React from "react";
|
|
3
|
-
import "./Timeline.css";
|
|
4
|
-
|
|
5
|
-
const ResourcesHeader = ({ content }) => {
|
|
6
|
-
return (
|
|
7
|
-
<div className="resources-header">
|
|
8
|
-
{/* content => string veya React node */}
|
|
9
|
-
{content}
|
|
10
|
-
</div>
|
|
11
|
-
);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default ResourcesHeader;
|
|
1
|
+
// ResourcesHeader.js
|
|
2
|
+
import React from "react";
|
|
3
|
+
import "./Timeline.css";
|
|
4
|
+
|
|
5
|
+
const ResourcesHeader = ({ content }) => {
|
|
6
|
+
return (
|
|
7
|
+
<div className="resources-header">
|
|
8
|
+
{/* content => string veya React node */}
|
|
9
|
+
{content}
|
|
10
|
+
</div>
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default ResourcesHeader;
|