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,158 @@
|
|
|
1
|
+
import { useEffect, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Keyboard shortcuts hook
|
|
5
|
+
* @param {Object} config - Keyboard shortcuts configuration
|
|
6
|
+
* @param {Function} config.onNavigateLeft - Left arrow key handler
|
|
7
|
+
* @param {Function} config.onNavigateRight - Right arrow key handler
|
|
8
|
+
* @param {Function} config.onNavigateUp - Up arrow key handler
|
|
9
|
+
* @param {Function} config.onNavigateDown - Down arrow key handler
|
|
10
|
+
* @param {Function} config.onDelete - Delete key handler
|
|
11
|
+
* @param {Function} config.onUndo - Ctrl+Z handler
|
|
12
|
+
* @param {Function} config.onRedo - Ctrl+Y handler
|
|
13
|
+
* @param {Function} config.onCopy - Ctrl+C handler
|
|
14
|
+
* @param {Function} config.onPaste - Ctrl+V handler
|
|
15
|
+
* @param {Function} config.onZoomIn - Ctrl+= or Ctrl++ handler
|
|
16
|
+
* @param {Function} config.onZoomOut - Ctrl+- handler
|
|
17
|
+
* @param {Object} config.keyMap - Custom key mappings (optional)
|
|
18
|
+
* @param {boolean} config.enabled - Enable/disable shortcuts
|
|
19
|
+
*/
|
|
20
|
+
const useKeyboardShortcuts = ({
|
|
21
|
+
onNavigateLeft,
|
|
22
|
+
onNavigateRight,
|
|
23
|
+
onNavigateUp,
|
|
24
|
+
onNavigateDown,
|
|
25
|
+
onDelete,
|
|
26
|
+
onUndo,
|
|
27
|
+
onRedo,
|
|
28
|
+
onCopy,
|
|
29
|
+
onPaste,
|
|
30
|
+
onZoomIn,
|
|
31
|
+
onZoomOut,
|
|
32
|
+
keyMap = {},
|
|
33
|
+
enabled = true,
|
|
34
|
+
}) => {
|
|
35
|
+
// Default key mappings
|
|
36
|
+
const defaultKeyMap = {
|
|
37
|
+
navigateLeft: keyMap.navigateLeft || 'ArrowLeft',
|
|
38
|
+
navigateRight: keyMap.navigateRight || 'ArrowRight',
|
|
39
|
+
navigateUp: keyMap.navigateUp || 'ArrowUp',
|
|
40
|
+
navigateDown: keyMap.navigateDown || 'ArrowDown',
|
|
41
|
+
delete: keyMap.delete || 'Delete',
|
|
42
|
+
undo: keyMap.undo || { key: 'z', ctrl: true },
|
|
43
|
+
redo: keyMap.redo || { key: 'y', ctrl: true },
|
|
44
|
+
copy: keyMap.copy || { key: 'c', ctrl: true },
|
|
45
|
+
paste: keyMap.paste || { key: 'v', ctrl: true },
|
|
46
|
+
zoomIn: keyMap.zoomIn || { key: '=', ctrl: true },
|
|
47
|
+
zoomOut: keyMap.zoomOut || { key: '-', ctrl: true },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleKeyDown = useCallback(
|
|
51
|
+
(e) => {
|
|
52
|
+
if (!enabled) return;
|
|
53
|
+
|
|
54
|
+
const key = e.key;
|
|
55
|
+
const isCtrl = e.ctrlKey || e.metaKey; // Mac için cmd tuşu desteği
|
|
56
|
+
|
|
57
|
+
// Arrow keys
|
|
58
|
+
if (key === defaultKeyMap.navigateLeft && onNavigateLeft) {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
onNavigateLeft();
|
|
61
|
+
} else if (key === defaultKeyMap.navigateRight && onNavigateRight) {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
onNavigateRight();
|
|
64
|
+
} else if (key === defaultKeyMap.navigateUp && onNavigateUp) {
|
|
65
|
+
e.preventDefault();
|
|
66
|
+
onNavigateUp();
|
|
67
|
+
} else if (key === defaultKeyMap.navigateDown && onNavigateDown) {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
onNavigateDown();
|
|
70
|
+
}
|
|
71
|
+
// Delete key
|
|
72
|
+
else if (key === defaultKeyMap.delete && onDelete) {
|
|
73
|
+
e.preventDefault();
|
|
74
|
+
onDelete();
|
|
75
|
+
}
|
|
76
|
+
// Ctrl+Z (Undo)
|
|
77
|
+
else if (
|
|
78
|
+
isCtrl &&
|
|
79
|
+
key.toLowerCase() === defaultKeyMap.undo.key.toLowerCase() &&
|
|
80
|
+
onUndo
|
|
81
|
+
) {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
onUndo();
|
|
84
|
+
}
|
|
85
|
+
// Ctrl+Y (Redo)
|
|
86
|
+
else if (
|
|
87
|
+
isCtrl &&
|
|
88
|
+
key.toLowerCase() === defaultKeyMap.redo.key.toLowerCase() &&
|
|
89
|
+
onRedo
|
|
90
|
+
) {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
onRedo();
|
|
93
|
+
}
|
|
94
|
+
// Ctrl+C (Copy)
|
|
95
|
+
else if (
|
|
96
|
+
isCtrl &&
|
|
97
|
+
key.toLowerCase() === defaultKeyMap.copy.key.toLowerCase() &&
|
|
98
|
+
onCopy
|
|
99
|
+
) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
onCopy();
|
|
102
|
+
}
|
|
103
|
+
// Ctrl+V (Paste)
|
|
104
|
+
else if (
|
|
105
|
+
isCtrl &&
|
|
106
|
+
key.toLowerCase() === defaultKeyMap.paste.key.toLowerCase() &&
|
|
107
|
+
onPaste
|
|
108
|
+
) {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
onPaste();
|
|
111
|
+
}
|
|
112
|
+
// Ctrl+= or Ctrl++ (Zoom In)
|
|
113
|
+
else if (
|
|
114
|
+
isCtrl &&
|
|
115
|
+
(key === '=' || key === '+' || (key === '=' && e.shiftKey)) &&
|
|
116
|
+
onZoomIn
|
|
117
|
+
) {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
onZoomIn();
|
|
120
|
+
}
|
|
121
|
+
// Ctrl+- (Zoom Out)
|
|
122
|
+
else if (
|
|
123
|
+
isCtrl &&
|
|
124
|
+
key === '-' &&
|
|
125
|
+
onZoomOut
|
|
126
|
+
) {
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
onZoomOut();
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
[
|
|
132
|
+
enabled,
|
|
133
|
+
defaultKeyMap,
|
|
134
|
+
onNavigateLeft,
|
|
135
|
+
onNavigateRight,
|
|
136
|
+
onNavigateUp,
|
|
137
|
+
onNavigateDown,
|
|
138
|
+
onDelete,
|
|
139
|
+
onUndo,
|
|
140
|
+
onRedo,
|
|
141
|
+
onCopy,
|
|
142
|
+
onPaste,
|
|
143
|
+
onZoomIn,
|
|
144
|
+
onZoomOut,
|
|
145
|
+
]
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
if (enabled) {
|
|
150
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
151
|
+
return () => {
|
|
152
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}, [enabled, handleKeyDown]);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export default useKeyboardShortcuts;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/hooks/useTouchGestures.js
|
|
2
|
+
|
|
3
|
+
import { useRef, useCallback } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Touch gesture hook for mobile support
|
|
7
|
+
* @param {Object} handlers - Gesture handlers
|
|
8
|
+
* @returns {Object} - Touch event handlers
|
|
9
|
+
*/
|
|
10
|
+
export const useTouchGestures = ({
|
|
11
|
+
onSwipeLeft,
|
|
12
|
+
onSwipeRight,
|
|
13
|
+
onSwipeUp,
|
|
14
|
+
onSwipeDown,
|
|
15
|
+
onPinch,
|
|
16
|
+
minSwipeDistance = 50,
|
|
17
|
+
enabled = true,
|
|
18
|
+
}) => {
|
|
19
|
+
const touchStartRef = useRef(null);
|
|
20
|
+
const touchStartTimeRef = useRef(null);
|
|
21
|
+
const lastTouchRef = useRef(null);
|
|
22
|
+
|
|
23
|
+
const handleTouchStart = useCallback((e) => {
|
|
24
|
+
if (!enabled) return;
|
|
25
|
+
|
|
26
|
+
const touch = e.touches[0];
|
|
27
|
+
touchStartRef.current = {
|
|
28
|
+
x: touch.clientX,
|
|
29
|
+
y: touch.clientY,
|
|
30
|
+
};
|
|
31
|
+
touchStartTimeRef.current = Date.now();
|
|
32
|
+
lastTouchRef.current = {
|
|
33
|
+
x: touch.clientX,
|
|
34
|
+
y: touch.clientY,
|
|
35
|
+
};
|
|
36
|
+
}, [enabled]);
|
|
37
|
+
|
|
38
|
+
const handleTouchMove = useCallback((e) => {
|
|
39
|
+
if (!enabled || !touchStartRef.current) return;
|
|
40
|
+
|
|
41
|
+
const touch = e.touches[0];
|
|
42
|
+
if (lastTouchRef.current) {
|
|
43
|
+
lastTouchRef.current = {
|
|
44
|
+
x: touch.clientX,
|
|
45
|
+
y: touch.clientY,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}, [enabled]);
|
|
49
|
+
|
|
50
|
+
const handleTouchEnd = useCallback((e) => {
|
|
51
|
+
if (!enabled || !touchStartRef.current || !lastTouchRef.current) return;
|
|
52
|
+
|
|
53
|
+
const touchEnd = e.changedTouches[0];
|
|
54
|
+
const deltaX = touchEnd.clientX - touchStartRef.current.x;
|
|
55
|
+
const deltaY = touchEnd.clientY - touchStartRef.current.y;
|
|
56
|
+
const deltaTime = Date.now() - touchStartTimeRef.current;
|
|
57
|
+
|
|
58
|
+
const absDeltaX = Math.abs(deltaX);
|
|
59
|
+
const absDeltaY = Math.abs(deltaY);
|
|
60
|
+
|
|
61
|
+
// Hızlı swipe kontrolü (300ms içinde)
|
|
62
|
+
if (deltaTime < 300 && (absDeltaX > minSwipeDistance || absDeltaY > minSwipeDistance)) {
|
|
63
|
+
if (absDeltaX > absDeltaY) {
|
|
64
|
+
// Yatay swipe
|
|
65
|
+
if (deltaX > 0 && onSwipeRight) {
|
|
66
|
+
onSwipeRight();
|
|
67
|
+
} else if (deltaX < 0 && onSwipeLeft) {
|
|
68
|
+
onSwipeLeft();
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// Dikey swipe
|
|
72
|
+
if (deltaY > 0 && onSwipeDown) {
|
|
73
|
+
onSwipeDown();
|
|
74
|
+
} else if (deltaY < 0 && onSwipeUp) {
|
|
75
|
+
onSwipeUp();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
touchStartRef.current = null;
|
|
81
|
+
lastTouchRef.current = null;
|
|
82
|
+
}, [enabled, minSwipeDistance, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown]);
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
onTouchStart: handleTouchStart,
|
|
86
|
+
onTouchMove: handleTouchMove,
|
|
87
|
+
onTouchEnd: handleTouchEnd,
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom/client';
|
|
3
|
-
import './
|
|
3
|
+
import './demo.css';
|
|
4
4
|
import App from './App';
|
|
5
|
-
import reportWebVitals from './reportWebVitals';
|
|
6
5
|
|
|
7
6
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
8
7
|
root.render(
|
|
@@ -10,8 +9,3 @@ root.render(
|
|
|
10
9
|
<App />
|
|
11
10
|
</React.StrictMode>
|
|
12
11
|
);
|
|
13
|
-
|
|
14
|
-
// If you want to start measuring performance in your app, pass a function
|
|
15
|
-
// to log results (for example: reportWebVitals(console.log))
|
|
16
|
-
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
17
|
-
reportWebVitals();
|
package/src/library.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import Timeline from "./components/Timeline/Timeline";
|
|
2
|
+
import DailyView from "./components/Timeline/DailyView";
|
|
3
|
+
import ContextMenu from "./components/Timeline/ContextMenu";
|
|
4
|
+
import EventDetailModal from "./components/Timeline/EventDetailModal";
|
|
5
|
+
import EventIcon from "./components/Timeline/EventIcon";
|
|
6
|
+
import EventBadge from "./components/Timeline/EventBadge";
|
|
7
|
+
import LoadingSpinner from "./components/Timeline/LoadingSpinner";
|
|
8
|
+
import AutocompleteSelect from "./components/Timeline/AutocompleteSelect";
|
|
9
|
+
|
|
10
|
+
// Ana Timeline component'i default export
|
|
11
|
+
export default Timeline;
|
|
12
|
+
|
|
13
|
+
// Named exports - İsteğe bağlı kullanım için
|
|
14
|
+
export {
|
|
15
|
+
DailyView,
|
|
16
|
+
ContextMenu,
|
|
17
|
+
EventDetailModal,
|
|
18
|
+
EventIcon,
|
|
19
|
+
EventBadge,
|
|
20
|
+
LoadingSpinner,
|
|
21
|
+
AutocompleteSelect,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// CSS dosyası package.json'da exports altında tanımlı
|
|
25
|
+
// Kullanım: import 'akfatimeline/components/Timeline/Timeline.css'
|
|
26
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// src/utils/conflictUtils.js
|
|
2
|
+
|
|
3
|
+
import { parseDate } from './dateUtils';
|
|
4
|
+
import { getTimeFromDate } from './timeUtils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* İki event'in çakışıp çakışmadığını kontrol eder (gün bazlı)
|
|
8
|
+
* @param {Object} event1 - İlk event
|
|
9
|
+
* @param {Object} event2 - İkinci event
|
|
10
|
+
* @returns {boolean} - Çakışma varsa true
|
|
11
|
+
*/
|
|
12
|
+
export const checkDayBasedConflict = (event1, event2) => {
|
|
13
|
+
if (event1.resourceId !== event2.resourceId) {
|
|
14
|
+
return false; // Farklı resource'larda çakışma olmaz
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const start1 = parseDate(event1.startDate);
|
|
18
|
+
const end1 = parseDate(event1.endDate);
|
|
19
|
+
const start2 = parseDate(event2.startDate);
|
|
20
|
+
const end2 = parseDate(event2.endDate);
|
|
21
|
+
|
|
22
|
+
// Çakışma kontrolü: bir event'in başlangıcı diğerinin içinde mi?
|
|
23
|
+
return (start1 <= end2 && end1 >= start2);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* İki event'in saat bazlı çakışıp çakışmadığını kontrol eder
|
|
28
|
+
* @param {Object} event1 - İlk event
|
|
29
|
+
* @param {Object} event2 - İkinci event
|
|
30
|
+
* @returns {boolean} - Çakışma varsa true
|
|
31
|
+
*/
|
|
32
|
+
export const checkTimeBasedConflict = (event1, event2) => {
|
|
33
|
+
if (event1.resourceId !== event2.resourceId) {
|
|
34
|
+
return false; // Farklı resource'larda çakışma olmaz
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const start1 = parseDate(event1.startDate);
|
|
38
|
+
const end1 = parseDate(event1.endDate);
|
|
39
|
+
const start2 = parseDate(event2.startDate);
|
|
40
|
+
const end2 = parseDate(event2.endDate);
|
|
41
|
+
|
|
42
|
+
// Aynı gün mü kontrol et
|
|
43
|
+
if (start1.toDateString() !== start2.toDateString()) {
|
|
44
|
+
return false; // Farklı günlerde çakışma olmaz (günlük kullanım için)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Saat bazlı çakışma kontrolü
|
|
48
|
+
const time1 = getTimeFromDate(start1);
|
|
49
|
+
const time1End = getTimeFromDate(end1);
|
|
50
|
+
const time2 = getTimeFromDate(start2);
|
|
51
|
+
const time2End = getTimeFromDate(end2);
|
|
52
|
+
|
|
53
|
+
return (time1.totalMinutes < time2End.totalMinutes && time1End.totalMinutes > time2.totalMinutes);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Bir event listesinde çakışmaları bulur
|
|
58
|
+
* @param {Array} events - Event listesi
|
|
59
|
+
* @param {boolean} timeMode - Saat bazlı mod aktif mi
|
|
60
|
+
* @returns {Array} - Çakışma bilgileri [{event1, event2, conflictType}]
|
|
61
|
+
*/
|
|
62
|
+
export const detectConflicts = (events, timeMode = false) => {
|
|
63
|
+
const conflicts = [];
|
|
64
|
+
const checkConflict = timeMode ? checkTimeBasedConflict : checkDayBasedConflict;
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < events.length; i++) {
|
|
67
|
+
for (let j = i + 1; j < events.length; j++) {
|
|
68
|
+
if (checkConflict(events[i], events[j])) {
|
|
69
|
+
conflicts.push({
|
|
70
|
+
event1: events[i],
|
|
71
|
+
event2: events[j],
|
|
72
|
+
conflictType: timeMode ? 'time' : 'day',
|
|
73
|
+
resourceId: events[i].resourceId,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return conflicts;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Belirli bir resource için çakışmaları bulur
|
|
84
|
+
* @param {Array} events - Event listesi
|
|
85
|
+
* @param {string} resourceId - Resource ID
|
|
86
|
+
* @param {boolean} timeMode - Saat bazlı mod aktif mi
|
|
87
|
+
* @returns {Array} - Çakışma bilgileri
|
|
88
|
+
*/
|
|
89
|
+
export const detectResourceConflicts = (events, resourceId, timeMode = false) => {
|
|
90
|
+
const resourceEvents = events.filter(e => e.resourceId === resourceId);
|
|
91
|
+
return detectConflicts(resourceEvents, timeMode);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Bir event'in diğer event'lerle çakışıp çakışmadığını kontrol eder
|
|
96
|
+
* @param {Object} event - Kontrol edilecek event
|
|
97
|
+
* @param {Array} otherEvents - Diğer event'ler
|
|
98
|
+
* @param {boolean} timeMode - Saat bazlı mod aktif mi
|
|
99
|
+
* @returns {Array} - Çakışan event'ler
|
|
100
|
+
*/
|
|
101
|
+
export const findEventConflicts = (event, otherEvents, timeMode = false) => {
|
|
102
|
+
const checkConflict = timeMode ? checkTimeBasedConflict : checkDayBasedConflict;
|
|
103
|
+
return otherEvents.filter(e => e.id !== event.id && checkConflict(event, e));
|
|
104
|
+
};
|
|
105
|
+
|
package/src/utils/dateUtils.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
// src/utils/dateUtils.js
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* "dd/mm/yyyy" formatındaki bir tarih string'ini Date objesine dönüştürür.
|
|
5
|
-
* Eğer dateInput bir string değilse, direkt Date objesini döndürür.
|
|
6
|
-
* @param {string | Object | Date} dateInput - "dd/mm/yyyy" formatında tarih stringi veya {fullDate: Date, display: string} objesi veya Date objesi.
|
|
7
|
-
* @returns {Date} - Date objesi.
|
|
8
|
-
*/
|
|
9
|
-
export const parseDate = (dateInput) => {
|
|
10
|
-
if (dateInput instanceof Date) {
|
|
11
|
-
return dateInput;
|
|
12
|
-
}
|
|
13
|
-
if (typeof dateInput === 'string') {
|
|
14
|
-
const [day, month, year] = dateInput.split("/").map(Number);
|
|
15
|
-
return new Date(year, month - 1, day);
|
|
16
|
-
} else if (typeof dateInput === 'object' && dateInput.fullDate instanceof Date) {
|
|
17
|
-
return new Date(dateInput.fullDate.getTime() + dateInput.fullDate.getTimezoneOffset() * 60000);
|
|
18
|
-
} else {
|
|
19
|
-
console.error("parseDate received invalid input:", dateInput);
|
|
20
|
-
return new Date(); // veya hata fırlat
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Bir tarihin belirli bir aralık içinde olup olmadığını kontrol eder.
|
|
26
|
-
* @param {string | Object | Date} date - "dd/mm/yyyy" formatında tarih stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
27
|
-
* @param {string | Object | Date} startDate - "dd/mm/yyyy" formatında başlangıç tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
28
|
-
* @param {string | Object | Date} endDate - "dd/mm/yyyy" formatında bitiş tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
29
|
-
* @returns {boolean} - Tarih aralık içinde ise true, değilse false.
|
|
30
|
-
*/
|
|
31
|
-
export const isDateInRange = (date, startDate, endDate) => {
|
|
32
|
-
const d = parseDate(date);
|
|
33
|
-
const start = parseDate(startDate);
|
|
34
|
-
const end = parseDate(endDate);
|
|
35
|
-
return d >= start && d <= end;
|
|
36
|
-
};
|
|
1
|
+
// src/utils/dateUtils.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* "dd/mm/yyyy" formatındaki bir tarih string'ini Date objesine dönüştürür.
|
|
5
|
+
* Eğer dateInput bir string değilse, direkt Date objesini döndürür.
|
|
6
|
+
* @param {string | Object | Date} dateInput - "dd/mm/yyyy" formatında tarih stringi veya {fullDate: Date, display: string} objesi veya Date objesi.
|
|
7
|
+
* @returns {Date} - Date objesi.
|
|
8
|
+
*/
|
|
9
|
+
export const parseDate = (dateInput) => {
|
|
10
|
+
if (dateInput instanceof Date) {
|
|
11
|
+
return dateInput;
|
|
12
|
+
}
|
|
13
|
+
if (typeof dateInput === 'string') {
|
|
14
|
+
const [day, month, year] = dateInput.split("/").map(Number);
|
|
15
|
+
return new Date(year, month - 1, day);
|
|
16
|
+
} else if (typeof dateInput === 'object' && dateInput.fullDate instanceof Date) {
|
|
17
|
+
return new Date(dateInput.fullDate.getTime() + dateInput.fullDate.getTimezoneOffset() * 60000);
|
|
18
|
+
} else {
|
|
19
|
+
console.error("parseDate received invalid input:", dateInput);
|
|
20
|
+
return new Date(); // veya hata fırlat
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Bir tarihin belirli bir aralık içinde olup olmadığını kontrol eder.
|
|
26
|
+
* @param {string | Object | Date} date - "dd/mm/yyyy" formatında tarih stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
27
|
+
* @param {string | Object | Date} startDate - "dd/mm/yyyy" formatında başlangıç tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
28
|
+
* @param {string | Object | Date} endDate - "dd/mm/yyyy" formatında bitiş tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
29
|
+
* @returns {boolean} - Tarih aralık içinde ise true, değilse false.
|
|
30
|
+
*/
|
|
31
|
+
export const isDateInRange = (date, startDate, endDate) => {
|
|
32
|
+
const d = parseDate(date);
|
|
33
|
+
const start = parseDate(startDate);
|
|
34
|
+
const end = parseDate(endDate);
|
|
35
|
+
return d >= start && d <= end;
|
|
36
|
+
};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
const filterTimelineData = (dates, startDate, dayCount) => {
|
|
2
|
-
const startIndex = dates.findIndex(
|
|
3
|
-
(date) => date.fullDate.toISOString().split("T")[0] === startDate
|
|
4
|
-
);
|
|
5
|
-
|
|
6
|
-
if (startIndex === -1) {
|
|
7
|
-
console.warn("Seçilen başlangıç tarihi bulunamadı.");
|
|
8
|
-
return { filteredDates: [] };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const filteredDates = dates.slice(startIndex, startIndex + dayCount);
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
filteredDates,
|
|
15
|
-
startIndex,
|
|
16
|
-
endIndex: startIndex + dayCount - 1,
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default filterTimelineData;
|
|
1
|
+
const filterTimelineData = (dates, startDate, dayCount) => {
|
|
2
|
+
const startIndex = dates.findIndex(
|
|
3
|
+
(date) => date.fullDate.toISOString().split("T")[0] === startDate
|
|
4
|
+
);
|
|
5
|
+
|
|
6
|
+
if (startIndex === -1) {
|
|
7
|
+
console.warn("Seçilen başlangıç tarihi bulunamadı.");
|
|
8
|
+
return { filteredDates: [] };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const filteredDates = dates.slice(startIndex, startIndex + dayCount);
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
filteredDates,
|
|
15
|
+
startIndex,
|
|
16
|
+
endIndex: startIndex + dayCount - 1,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default filterTimelineData;
|
|
21
21
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// src/utils/filterUtils.js
|
|
2
|
+
|
|
3
|
+
import { parseDate } from './dateUtils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Event'leri başlığa göre filtreler
|
|
7
|
+
* @param {Array} events - Event listesi
|
|
8
|
+
* @param {string} searchTerm - Arama terimi
|
|
9
|
+
* @returns {Array} - Filtrelenmiş event listesi
|
|
10
|
+
*/
|
|
11
|
+
export const filterByTitle = (events, searchTerm) => {
|
|
12
|
+
if (!searchTerm || searchTerm.trim() === '') {
|
|
13
|
+
return events;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const term = searchTerm.toLowerCase().trim();
|
|
17
|
+
return events.filter(event =>
|
|
18
|
+
event.title && event.title.toLowerCase().includes(term)
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Event'leri tarih aralığına göre filtreler
|
|
24
|
+
* @param {Array} events - Event listesi
|
|
25
|
+
* @param {Date} startDate - Başlangıç tarihi
|
|
26
|
+
* @param {Date} endDate - Bitiş tarihi
|
|
27
|
+
* @returns {Array} - Filtrelenmiş event listesi
|
|
28
|
+
*/
|
|
29
|
+
export const filterByDateRange = (events, startDate, endDate) => {
|
|
30
|
+
if (!startDate && !endDate) {
|
|
31
|
+
return events;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return events.filter(event => {
|
|
35
|
+
const eventStart = parseDate(event.startDate);
|
|
36
|
+
const eventEnd = parseDate(event.endDate);
|
|
37
|
+
|
|
38
|
+
if (startDate && eventEnd < startDate) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (endDate && eventStart > endDate) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return true;
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Event'leri resource'a göre filtreler
|
|
51
|
+
* @param {Array} events - Event listesi
|
|
52
|
+
* @param {Array} resourceIds - Resource ID listesi
|
|
53
|
+
* @returns {Array} - Filtrelenmiş event listesi
|
|
54
|
+
*/
|
|
55
|
+
export const filterByResource = (events, resourceIds) => {
|
|
56
|
+
if (!resourceIds || resourceIds.length === 0) {
|
|
57
|
+
return events;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return events.filter(event => resourceIds.includes(event.resourceId));
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Event'leri status'a göre filtreler
|
|
65
|
+
* @param {Array} events - Event listesi
|
|
66
|
+
* @param {Array} statuses - Status listesi
|
|
67
|
+
* @returns {Array} - Filtrelenmiş event listesi
|
|
68
|
+
*/
|
|
69
|
+
export const filterByStatus = (events, statuses) => {
|
|
70
|
+
if (!statuses || statuses.length === 0) {
|
|
71
|
+
return events;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return events.filter(event =>
|
|
75
|
+
event.status && statuses.includes(event.status)
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Tüm filtreleri uygular
|
|
81
|
+
* @param {Array} events - Event listesi
|
|
82
|
+
* @param {Object} filters - Filtre objesi {searchTerm, startDate, endDate, resourceIds, statuses}
|
|
83
|
+
* @returns {Array} - Filtrelenmiş event listesi
|
|
84
|
+
*/
|
|
85
|
+
export const applyFilters = (events, filters) => {
|
|
86
|
+
let filtered = events;
|
|
87
|
+
|
|
88
|
+
if (filters.searchTerm) {
|
|
89
|
+
filtered = filterByTitle(filtered, filters.searchTerm);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (filters.startDate || filters.endDate) {
|
|
93
|
+
filtered = filterByDateRange(filtered, filters.startDate, filters.endDate);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (filters.resourceIds && filters.resourceIds.length > 0) {
|
|
97
|
+
filtered = filterByResource(filtered, filters.resourceIds);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (filters.statuses && filters.statuses.length > 0) {
|
|
101
|
+
filtered = filterByStatus(filtered, filters.statuses);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return filtered;
|
|
105
|
+
};
|
|
106
|
+
|