@bagelink/vue 1.2.15 → 1.2.20
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/components/calendar/CalendarTypes.d.ts +13 -0
- package/dist/components/calendar/CalendarTypes.d.ts.map +1 -0
- package/dist/components/calendar/Index.vue.d.ts +39 -507
- package/dist/components/calendar/Index.vue.d.ts.map +1 -1
- package/dist/components/calendar/utils.d.ts +31 -0
- package/dist/components/calendar/utils.d.ts.map +1 -0
- package/dist/components/calendar/views/AgendaView.vue.d.ts +16 -0
- package/dist/components/calendar/views/AgendaView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/DayView.vue.d.ts +50 -0
- package/dist/components/calendar/views/DayView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/MonthView.vue.d.ts +20 -0
- package/dist/components/calendar/views/MonthView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/WeekView.vue.d.ts +33 -0
- package/dist/components/calendar/views/WeekView.vue.d.ts.map +1 -0
- package/dist/components/form/BglMultiStepForm.vue.d.ts +63 -0
- package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -0
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DatePicker.vue.d.ts +3 -3
- package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/index.cjs +2241 -3891
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2242 -3892
- package/dist/style.css +567 -633
- package/dist/utils/BagelFormUtils.d.ts +4 -2
- package/dist/utils/BagelFormUtils.d.ts.map +1 -1
- package/dist/utils/calendar/EDate.d.ts +2 -0
- package/dist/utils/calendar/EDate.d.ts.map +1 -0
- package/dist/utils/calendar/Helpers.d.ts +19 -0
- package/dist/utils/calendar/Helpers.d.ts.map +1 -0
- package/dist/utils/calendar/constants.d.ts +3 -0
- package/dist/utils/calendar/constants.d.ts.map +1 -0
- package/dist/utils/calendar/dateUtils.d.ts +30 -0
- package/dist/utils/calendar/dateUtils.d.ts.map +1 -0
- package/dist/utils/calendar/event.interface.d.ts +32 -0
- package/dist/utils/calendar/event.interface.d.ts.map +1 -0
- package/dist/utils/calendar/time.d.ts +117 -0
- package/dist/utils/calendar/time.d.ts.map +1 -0
- package/dist/utils/calendar/types.d.ts +27 -0
- package/dist/utils/calendar/types.d.ts.map +1 -0
- package/dist/utils/calendar/typings.d.ts +87 -0
- package/dist/utils/calendar/typings.d.ts.map +1 -0
- package/dist/utils/calendar/week.d.ts +117 -0
- package/dist/utils/calendar/week.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/calendar/CalendarTypes.ts +13 -0
- package/src/components/calendar/Index.vue +124 -389
- package/src/components/calendar/utils.ts +70 -0
- package/src/components/calendar/views/AgendaView.vue +263 -0
- package/src/components/calendar/views/DayView.vue +373 -0
- package/src/components/calendar/views/MonthView.vue +313 -0
- package/src/components/calendar/views/WeekView.vue +431 -0
- package/src/components/form/BglMultiStepForm.vue +383 -69
- package/src/components/form/index.ts +1 -0
- package/src/components/form/inputs/CodeEditor/Index.vue +11 -0
- package/src/components/form/inputs/DateInput.vue +3 -3
- package/src/components/form/inputs/DatePicker.vue +35 -30
- package/src/components/form/inputs/SelectInput.vue +2 -0
- package/src/components/form/inputs/Upload/upload.types.d.ts +0 -1
- package/src/index.ts +2 -2
- package/src/styles/inputs.css +138 -137
- package/src/styles/layout.css +3 -2
- package/src/styles/mobilLayout.css +4 -2
- package/src/utils/BagelFormUtils.ts +6 -2
- package/src/utils/calendar/EDate.ts +0 -0
- package/src/{components/calendar/helpers → utils/calendar}/Helpers.ts +6 -6
- package/src/utils/calendar/constants.ts +2 -0
- package/src/utils/{timeAgo.ts → calendar/dateUtils.ts} +38 -1
- package/src/utils/calendar/event.interface.ts +33 -0
- package/src/{components/calendar/helpers/Time.ts → utils/calendar/time.ts} +15 -15
- package/src/utils/calendar/types.ts +27 -0
- package/src/{components/calendar/typings/config.interface.ts → utils/calendar/typings.ts} +13 -6
- package/src/utils/calendar/week.ts +588 -0
- package/src/components/calendar/assets/base.css +0 -60
- package/src/components/calendar/components/header/Header.vue +0 -153
- package/src/components/calendar/components/month/AgendaEventTile.vue +0 -135
- package/src/components/calendar/components/month/AgendaEvents.vue +0 -72
- package/src/components/calendar/components/month/Day.vue +0 -256
- package/src/components/calendar/components/month/Event.vue +0 -164
- package/src/components/calendar/components/month/Month.vue +0 -241
- package/src/components/calendar/components/month/WeekDay.vue +0 -15
- package/src/components/calendar/components/partials/EventFlyout.vue +0 -430
- package/src/components/calendar/components/week/Day.vue +0 -198
- package/src/components/calendar/components/week/DayEvent.vue +0 -584
- package/src/components/calendar/components/week/DayTimeline.vue +0 -80
- package/src/components/calendar/components/week/FullDayEvent.vue +0 -121
- package/src/components/calendar/components/week/Week.vue +0 -414
- package/src/components/calendar/components/week/WeekTimeline.vue +0 -101
- package/src/components/calendar/constants.ts +0 -13
- package/src/components/calendar/helpers/DayIntervals.ts +0 -48
- package/src/components/calendar/helpers/EDate.ts +0 -18
- package/src/components/calendar/helpers/Errors.ts +0 -69
- package/src/components/calendar/helpers/EventChange.ts +0 -88
- package/src/components/calendar/helpers/EventConcurrency.ts +0 -69
- package/src/components/calendar/helpers/EventFlyoutPosition.ts +0 -96
- package/src/components/calendar/helpers/EventPosition.ts +0 -154
- package/src/components/calendar/helpers/EventsFilter.ts +0 -50
- package/src/components/calendar/helpers/Week.ts +0 -37
- package/src/components/calendar/language/index.ts +0 -41
- package/src/components/calendar/language/keys.ts +0 -99
- package/src/components/calendar/models/Event.ts +0 -112
- package/src/components/calendar/styles/_mixins.css +0 -21
- package/src/components/calendar/styles/_variables.css +0 -47
- package/src/components/calendar/typings/interfaces/day.interface.ts +0 -10
- package/src/components/calendar/typings/interfaces/event.interface.ts +0 -32
- package/src/components/calendar/typings/interfaces/full-day-events-week.type.ts +0 -8
- package/src/components/calendar/typings/interfaces/period.interface.ts +0 -5
- package/src/components/calendar/typings/interfaces/time-modes.ts +0 -11
- package/src/components/calendar/typings/types.ts +0 -27
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { DAY_TIME_POINT } from '../typings/config.interface'
|
|
2
|
-
import { DAY_MODE } from '../typings/interfaces/time-modes'
|
|
3
|
-
import EDate from './EDate'
|
|
4
1
|
import Helpers from './Helpers'
|
|
2
|
+
import { DAY_MODE, DAY_TIME_POINT } from './typings'
|
|
5
3
|
|
|
6
4
|
export type calendarWeekType = Date[]
|
|
7
5
|
export type calendarMonthType = calendarWeekType[]
|
|
@@ -306,16 +304,14 @@ export default class Time {
|
|
|
306
304
|
}
|
|
307
305
|
|
|
308
306
|
dateIsToday(date: Date) {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
date: dateDate,
|
|
318
|
-
} = new EDate(date)
|
|
307
|
+
const today = new Date()
|
|
308
|
+
const yearToday = today.getFullYear()
|
|
309
|
+
const monthToday = today.getMonth()
|
|
310
|
+
const dateToday = today.getDate()
|
|
311
|
+
|
|
312
|
+
const dateYear = date.getFullYear()
|
|
313
|
+
const dateMonth = date.getMonth()
|
|
314
|
+
const dateDate = date.getDate()
|
|
319
315
|
|
|
320
316
|
return (
|
|
321
317
|
yearToday === dateYear
|
|
@@ -325,7 +321,10 @@ export default class Time {
|
|
|
325
321
|
}
|
|
326
322
|
|
|
327
323
|
dateIsInWeek(dateToCheck: Date, week: Date[]) {
|
|
328
|
-
const
|
|
324
|
+
const d = new Date(dateToCheck)
|
|
325
|
+
const date = d.getDate()
|
|
326
|
+
const month = d.getMonth()
|
|
327
|
+
const fullYear = d.getFullYear()
|
|
329
328
|
|
|
330
329
|
for (const weekDay of week) {
|
|
331
330
|
const dateIsSame = date === weekDay.getDate()
|
|
@@ -463,7 +462,8 @@ export default class Time {
|
|
|
463
462
|
}
|
|
464
463
|
|
|
465
464
|
isTrailingOrLeadingDate(date: Date, month: number) {
|
|
466
|
-
const
|
|
465
|
+
const d = new Date(date)
|
|
466
|
+
const dateMonth = d.getMonth()
|
|
467
467
|
|
|
468
468
|
return month !== dateMonth
|
|
469
469
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ModeType } from './typings'
|
|
2
|
+
|
|
3
|
+
export interface EventInterface {
|
|
4
|
+
id: string
|
|
5
|
+
title?: string
|
|
6
|
+
time: {
|
|
7
|
+
start: string
|
|
8
|
+
end: string
|
|
9
|
+
}
|
|
10
|
+
description?: string
|
|
11
|
+
topic?: string
|
|
12
|
+
location?: string
|
|
13
|
+
with?: string
|
|
14
|
+
colorScheme?: string
|
|
15
|
+
isEditable?: boolean
|
|
16
|
+
disableDnD?: ModeType[]
|
|
17
|
+
disableResize?: ModeType[]
|
|
18
|
+
isCustom?: boolean | ModeType[]
|
|
19
|
+
zIndex?: number
|
|
20
|
+
nOfPreviousConcurrentEvents?: number
|
|
21
|
+
totalConcurrentEvents?: number
|
|
22
|
+
timeJS?: {
|
|
23
|
+
start: Date
|
|
24
|
+
end: Date
|
|
25
|
+
}
|
|
26
|
+
originalEvent?: Omit<EventInterface, 'originalEvent'>
|
|
27
|
+
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface ModeType {
|
|
2
|
+
mode: 'day' | 'week' | 'month' | 'agenda'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export enum DAY_MODE {
|
|
6
|
+
REGULAR = 'regular',
|
|
7
|
+
SHORTENED = 'shortened',
|
|
8
|
+
FLEXIBLE = 'flexible',
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
export enum DAY_TIME_POINT {
|
|
5
12
|
MIDNIGHT = 0,
|
|
@@ -36,11 +43,11 @@ export interface ColorSchemes {
|
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
export type intervalLengthType = 15 | 30 | 60
|
|
46
|
+
export enum WEEK_START_DAY {
|
|
47
|
+
SUNDAY = 'sunday',
|
|
48
|
+
MONDAY = 'monday',
|
|
49
|
+
}
|
|
39
50
|
|
|
40
|
-
// Lets the implementer define:
|
|
41
|
-
// a) length in minutes, of the day intervals
|
|
42
|
-
// b) the height of each individual interval
|
|
43
|
-
// c) whether the intervals should appear graphically as clickable elements or not
|
|
44
51
|
export interface DayIntervalsType {
|
|
45
52
|
length?: intervalLengthType
|
|
46
53
|
height?: number
|
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import Helpers from './Helpers'
|
|
2
|
+
import { DAY_MODE, DAY_TIME_POINT } from './typings'
|
|
3
|
+
|
|
4
|
+
export type calendarWeekType = Date[]
|
|
5
|
+
export type calendarMonthType = calendarWeekType[]
|
|
6
|
+
export type calendarYearMonths = Date[]
|
|
7
|
+
|
|
8
|
+
export enum WEEK_START_DAY {
|
|
9
|
+
SUNDAY = 'sunday',
|
|
10
|
+
MONDAY = 'monday'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default class Time {
|
|
14
|
+
FIRST_DAY_OF_WEEK: WEEK_START_DAY
|
|
15
|
+
CALENDAR_LOCALE: string
|
|
16
|
+
ALL_HOURS: DAY_TIME_POINT[] = [
|
|
17
|
+
0,
|
|
18
|
+
100,
|
|
19
|
+
200,
|
|
20
|
+
300,
|
|
21
|
+
400,
|
|
22
|
+
500,
|
|
23
|
+
600,
|
|
24
|
+
700,
|
|
25
|
+
800,
|
|
26
|
+
900,
|
|
27
|
+
1000,
|
|
28
|
+
1100,
|
|
29
|
+
1200,
|
|
30
|
+
1300,
|
|
31
|
+
1400,
|
|
32
|
+
1500,
|
|
33
|
+
1600,
|
|
34
|
+
1700,
|
|
35
|
+
1800,
|
|
36
|
+
1900,
|
|
37
|
+
2000,
|
|
38
|
+
2100,
|
|
39
|
+
2200,
|
|
40
|
+
2300
|
|
41
|
+
]
|
|
42
|
+
DAY_START: DAY_TIME_POINT
|
|
43
|
+
DAY_END: DAY_TIME_POINT
|
|
44
|
+
HOURS_PER_DAY = 24
|
|
45
|
+
MS_PER_DAY: number
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
firstDayOfWeek: WEEK_START_DAY = WEEK_START_DAY.MONDAY,
|
|
49
|
+
locale: string | null = null,
|
|
50
|
+
dayBoundaries: { start: DAY_TIME_POINT, end: DAY_TIME_POINT } = { start: 0, end: 2400 }
|
|
51
|
+
) {
|
|
52
|
+
this.FIRST_DAY_OF_WEEK = firstDayOfWeek
|
|
53
|
+
this.CALENDAR_LOCALE = locale || Helpers.getBrowserNavigatorLocale()
|
|
54
|
+
this.DAY_START = dayBoundaries.start
|
|
55
|
+
this.DAY_END = dayBoundaries.end
|
|
56
|
+
this.HOURS_PER_DAY = (() => {
|
|
57
|
+
const dayEnd = Time.getHourFromTimePoints(this.DAY_END)
|
|
58
|
+
const dayStart = Time.getHourFromTimePoints(this.DAY_START)
|
|
59
|
+
|
|
60
|
+
if (dayEnd > dayStart) return dayEnd - dayStart
|
|
61
|
+
|
|
62
|
+
return this.HOURS_PER_DAY - dayStart + dayEnd
|
|
63
|
+
})()
|
|
64
|
+
this.MS_PER_DAY = 86400000
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get dayMode() {
|
|
68
|
+
if (this.DAY_START === 0 && this.DAY_END === 2400) return DAY_MODE.REGULAR
|
|
69
|
+
|
|
70
|
+
if (this.DAY_START >= this.DAY_END) return DAY_MODE.FLEXIBLE
|
|
71
|
+
|
|
72
|
+
return DAY_MODE.SHORTENED
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getDatesBetweenTwoDates(start: Date, end: Date): Date[] {
|
|
76
|
+
const arr = []
|
|
77
|
+
const dt = new Date(start)
|
|
78
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
79
|
+
while (dt <= end) {
|
|
80
|
+
arr.push(new Date(dt.getFullYear(), dt.getMonth(), dt.getDate()))
|
|
81
|
+
dt.setDate(dt.getDate() + 1)
|
|
82
|
+
}
|
|
83
|
+
return arr
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getCalendarWeekDateObjects(date: Date): calendarWeekType {
|
|
87
|
+
// If week starts on Sunday, we can get the first date of the week, by simply counting selectedDate.getDate() - selectedDate.getDay()
|
|
88
|
+
let subtractedDaysToGetFirstDate
|
|
89
|
+
if (this.FIRST_DAY_OF_WEEK === 'sunday') {
|
|
90
|
+
subtractedDaysToGetFirstDate = date.getDay()
|
|
91
|
+
}
|
|
92
|
+
// However, if week starts on Monday, we need to make sure Mondays are represented as 0, instead of Sundays
|
|
93
|
+
else {
|
|
94
|
+
subtractedDaysToGetFirstDate
|
|
95
|
+
= date.getDay() === 0 ? 6 : date.getDay() - 1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const dateOfFirstDayOfWeek = date.getDate() - subtractedDaysToGetFirstDate // First date of week is the date of the month - the day of the week
|
|
99
|
+
const firstDay = new Date(
|
|
100
|
+
date.getFullYear(),
|
|
101
|
+
date.getMonth(),
|
|
102
|
+
dateOfFirstDayOfWeek
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
return this.getDatesBetweenTwoDates(
|
|
106
|
+
firstDay,
|
|
107
|
+
new Date(
|
|
108
|
+
firstDay.getFullYear(),
|
|
109
|
+
firstDay.getMonth(),
|
|
110
|
+
firstDay.getDate() + 6
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Returns an array of the weeks that comprise a month
|
|
117
|
+
*
|
|
118
|
+
* @param {number} yyyy
|
|
119
|
+
* @param {number} mm - zero indexed (January === 0)
|
|
120
|
+
*/
|
|
121
|
+
getCalendarMonthSplitInWeeks(yyyy: number, mm: number): calendarMonthType {
|
|
122
|
+
const month: calendarMonthType = []
|
|
123
|
+
const selectedDate = new Date(yyyy, mm, 1)
|
|
124
|
+
|
|
125
|
+
// 1. Get the first date of the month, and push the full week of this date into the month list
|
|
126
|
+
const firstDateOfMonth = new Date(
|
|
127
|
+
selectedDate.getFullYear(),
|
|
128
|
+
selectedDate.getMonth(),
|
|
129
|
+
1
|
|
130
|
+
)
|
|
131
|
+
const firstWeekOfMonth = this.getCalendarWeekDateObjects(firstDateOfMonth)
|
|
132
|
+
month.push(firstWeekOfMonth)
|
|
133
|
+
|
|
134
|
+
// 2. Then enter a while-loop, which pushes weeks onto the month,
|
|
135
|
+
// until the first Monday is reached, that is not in the specified month
|
|
136
|
+
let isInMonth = true
|
|
137
|
+
let mondayOfWeekToPush = firstWeekOfMonth[0]
|
|
138
|
+
const specifiedMonth = selectedDate.getMonth()
|
|
139
|
+
|
|
140
|
+
while (isInMonth) {
|
|
141
|
+
const newMonday = new Date(
|
|
142
|
+
mondayOfWeekToPush.getFullYear(),
|
|
143
|
+
mondayOfWeekToPush.getMonth(),
|
|
144
|
+
mondayOfWeekToPush.getDate() + 7
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if (newMonday.getMonth() === specifiedMonth) {
|
|
148
|
+
month.push(this.getCalendarWeekDateObjects(newMonday))
|
|
149
|
+
mondayOfWeekToPush = newMonday
|
|
150
|
+
} else {
|
|
151
|
+
isInMonth = false
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return month
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Returns an array with the length of 12 dates,
|
|
160
|
+
* one date for the first day of each month of the year
|
|
161
|
+
*/
|
|
162
|
+
getCalendarYearMonths(year: number): calendarYearMonths {
|
|
163
|
+
const yearList: calendarYearMonths = []
|
|
164
|
+
let month = 0
|
|
165
|
+
|
|
166
|
+
while (month <= 11) {
|
|
167
|
+
yearList.push(new Date(year, month, 1))
|
|
168
|
+
month++
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return yearList
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
getHourAndMinutesFromTimePoints(timePoints: number) {
|
|
175
|
+
const time = timePoints.toString()
|
|
176
|
+
let hour = '0'
|
|
177
|
+
let minutes = '0'
|
|
178
|
+
|
|
179
|
+
if (time.length === 4) {
|
|
180
|
+
hour = time[0] + time[1]
|
|
181
|
+
minutes = time[2] + time[3]
|
|
182
|
+
} else if (time.length === 3) {
|
|
183
|
+
hour = time[0]
|
|
184
|
+
minutes = time[1] + time[2]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
hour: +hour,
|
|
189
|
+
minutes: +minutes,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Given timePoints (0, 100, 200 etc.), this function returns
|
|
195
|
+
* a localized string with the respective hour
|
|
196
|
+
* (in en-US for example: 0 => 12 AM, 1600 => 4 PM )
|
|
197
|
+
*/
|
|
198
|
+
getHourLocaleStringFromHourDigits(timePoints: number) {
|
|
199
|
+
const { hour, minutes } = this.getHourAndMinutesFromTimePoints(timePoints)
|
|
200
|
+
|
|
201
|
+
const hourLocaleString = new Date(
|
|
202
|
+
2100,
|
|
203
|
+
0,
|
|
204
|
+
1,
|
|
205
|
+
+hour,
|
|
206
|
+
+minutes,
|
|
207
|
+
0
|
|
208
|
+
).toLocaleTimeString(this.CALENDAR_LOCALE, {
|
|
209
|
+
hour: '2-digit',
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
if (hourLocaleString[0] === '0') return hourLocaleString.substring(1)
|
|
213
|
+
|
|
214
|
+
return hourLocaleString
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getLocalizedNameOfWeekday(
|
|
218
|
+
date: Date,
|
|
219
|
+
weekdayNameLength: 'long' | 'short' = 'short'
|
|
220
|
+
): string {
|
|
221
|
+
return date.toLocaleDateString(this.CALENDAR_LOCALE, {
|
|
222
|
+
weekday: weekdayNameLength,
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
getLocalizedNameOfMonth(
|
|
227
|
+
date: Date,
|
|
228
|
+
monthNameLength: 'long' | 'short' = 'short'
|
|
229
|
+
): string {
|
|
230
|
+
return date.toLocaleDateString(this.CALENDAR_LOCALE, {
|
|
231
|
+
month: monthNameLength,
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getLocalizedDateString(date: Date): string {
|
|
236
|
+
return date.toLocaleDateString(this.CALENDAR_LOCALE)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Takes a date object, and creates a time string from it, in the format of
|
|
241
|
+
* YYYY-MM-DD hh:mm
|
|
242
|
+
*/
|
|
243
|
+
getDateTimeStringFromDate(
|
|
244
|
+
date: Date,
|
|
245
|
+
timeIsStartOrEndOfDay?: 'start' | 'end'
|
|
246
|
+
): string {
|
|
247
|
+
const y = date.getFullYear()
|
|
248
|
+
const m = date.getMonth() + 1
|
|
249
|
+
const d = date.getDate()
|
|
250
|
+
const fullDate = `${y}-${m >= 10 ? m : `0${m}`}-${d >= 10 ? d : `0${d}`}`
|
|
251
|
+
|
|
252
|
+
if (!timeIsStartOrEndOfDay) {
|
|
253
|
+
const hour = date.getHours()
|
|
254
|
+
const minutes = date.getMinutes()
|
|
255
|
+
|
|
256
|
+
return `${fullDate} ${hour >= 10 ? hour : `0${hour}`}:${
|
|
257
|
+
minutes >= 10 ? minutes : `0${minutes}`
|
|
258
|
+
}`
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const fullTime = timeIsStartOrEndOfDay === 'start' ? '00:00' : '23:59'
|
|
262
|
+
|
|
263
|
+
return `${fullDate} ${fullTime}`
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
getLocalizedTime(dateTimeString: string) {
|
|
267
|
+
// Though only displaying time, the exact date is needed, because otherwise time will be displayed
|
|
268
|
+
// incorrectly on days when daylight saving time changes
|
|
269
|
+
const {
|
|
270
|
+
year,
|
|
271
|
+
month,
|
|
272
|
+
date,
|
|
273
|
+
hour,
|
|
274
|
+
minutes,
|
|
275
|
+
} = this.getAllVariablesFromDateTimeString(dateTimeString)
|
|
276
|
+
const d = new Date(year, month, date, hour, minutes)
|
|
277
|
+
|
|
278
|
+
return d.toLocaleTimeString(this.CALENDAR_LOCALE, {
|
|
279
|
+
hour: 'numeric',
|
|
280
|
+
minute: 'numeric',
|
|
281
|
+
})
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
getLocalizedHour(date: Date) {
|
|
285
|
+
return date.toLocaleTimeString(this.CALENDAR_LOCALE, { hour: '2-digit' })
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
getLocalizedTimeRange(start: string, end: string) {
|
|
289
|
+
return `${this.getLocalizedTime(start)} - ${this.getLocalizedTime(end)}`
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Returns numeric values for year, month, date, hour and minutes, given a dateTimeString
|
|
294
|
+
* All variables are Date-Object compatible, meaning "month" is zero-indexed
|
|
295
|
+
*/
|
|
296
|
+
getAllVariablesFromDateTimeString(dateTimeString: string) {
|
|
297
|
+
return {
|
|
298
|
+
year: +dateTimeString.substring(0, 4),
|
|
299
|
+
month: +dateTimeString.substring(5, 7) - 1,
|
|
300
|
+
date: +dateTimeString.substring(8, 10),
|
|
301
|
+
hour: this.hourFrom(dateTimeString),
|
|
302
|
+
minutes: this.minutesFrom(dateTimeString),
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
dateIsToday(date: Date) {
|
|
307
|
+
const today = new Date()
|
|
308
|
+
const yearToday = today.getFullYear()
|
|
309
|
+
const monthToday = today.getMonth()
|
|
310
|
+
const dateToday = today.getDate()
|
|
311
|
+
|
|
312
|
+
const dateYear = date.getFullYear()
|
|
313
|
+
const dateMonth = date.getMonth()
|
|
314
|
+
const dateDate = date.getDate()
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
yearToday === dateYear
|
|
318
|
+
&& monthToday === dateMonth
|
|
319
|
+
&& dateToday === dateDate
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
dateIsInWeek(dateToCheck: Date, week: Date[]) {
|
|
324
|
+
const d = new Date(dateToCheck)
|
|
325
|
+
const date = d.getDate()
|
|
326
|
+
const month = d.getMonth()
|
|
327
|
+
const fullYear = d.getFullYear()
|
|
328
|
+
|
|
329
|
+
for (const weekDay of week) {
|
|
330
|
+
const dateIsSame = date === weekDay.getDate()
|
|
331
|
+
const monthIsSame = month === weekDay.getMonth()
|
|
332
|
+
const yearIsSame = fullYear === weekDay.getFullYear()
|
|
333
|
+
|
|
334
|
+
if (dateIsSame && monthIsSame && yearIsSame) return true
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return false
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
getDateStringFromDate(date: Date) {
|
|
341
|
+
const yyyy = date.getFullYear()
|
|
342
|
+
const mm = (date.getMonth() + 1)
|
|
343
|
+
const dd = date.getDate()
|
|
344
|
+
|
|
345
|
+
return `${yyyy}-${mm >= 10 ? mm : `0${mm}`}-${dd >= 10 ? dd : `0${dd}`}`
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
addMinutesToDateTimeString(minutes: number, dateTimeString: string) {
|
|
349
|
+
const {
|
|
350
|
+
year: oldYear,
|
|
351
|
+
month: oldMonth,
|
|
352
|
+
date: oldDate,
|
|
353
|
+
hour: oldHour,
|
|
354
|
+
minutes: oldMinutes
|
|
355
|
+
} = this.getAllVariablesFromDateTimeString(dateTimeString)
|
|
356
|
+
|
|
357
|
+
const oldDateObject = new Date(oldYear, oldMonth, oldDate, oldHour, oldMinutes)
|
|
358
|
+
const newDateObject = new Date(oldDateObject.getTime() + (minutes * 60000))
|
|
359
|
+
|
|
360
|
+
return this.getDateTimeStringFromDate(newDateObject)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
addDaysToDateTimeString(days: number, dateTimeString: string) {
|
|
364
|
+
return this.addMinutesToDateTimeString((days * 1440), dateTimeString)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
dateStringsHaveEqualDates(dateTimeString1: string, dateTimeString2: string) {
|
|
368
|
+
const { year: year1, month: month1, date: date1 } = this.getAllVariablesFromDateTimeString(dateTimeString1)
|
|
369
|
+
const { year: year2, month: month2, date: date2 } = this.getAllVariablesFromDateTimeString(dateTimeString2)
|
|
370
|
+
|
|
371
|
+
return (year1 === year2) && (month1 === month2) && (date1 === date2)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
setDateToEndOfDay(date: Date) {
|
|
375
|
+
return new Date(
|
|
376
|
+
date.getFullYear(),
|
|
377
|
+
date.getMonth(),
|
|
378
|
+
date.getDate(),
|
|
379
|
+
23,
|
|
380
|
+
59,
|
|
381
|
+
59,
|
|
382
|
+
999
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
protected turnMinutesIntoPercentageOfHour(minutes: number): string {
|
|
387
|
+
const oneMinutePercentage = 100 / 60
|
|
388
|
+
const minutePoints = oneMinutePercentage * minutes
|
|
389
|
+
|
|
390
|
+
if (minutePoints < 10) return `0${minutePoints}`
|
|
391
|
+
|
|
392
|
+
return minutePoints.toString()
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Every hour between 'dayStart' and 'dayEnd' is 100, in this function referred to as 100 points
|
|
397
|
+
* If an event starts 30 minutes after 'dayStart', it should have 50 pointsIntoDay
|
|
398
|
+
* If a day consists of 4 hours (400 points), we then have to count
|
|
399
|
+
* (50 / 400) * 100 = 12.5 => event starts after 12.5 percent of the day
|
|
400
|
+
*
|
|
401
|
+
* Result is supposed to be a number between 0 and 100, and is used for setting the CSS- top- and height-attributes for events
|
|
402
|
+
*/
|
|
403
|
+
getPercentageOfDayFromDateTimeString(
|
|
404
|
+
dateTimeString: string,
|
|
405
|
+
dayStart: number,
|
|
406
|
+
dayEnd: number,
|
|
407
|
+
) {
|
|
408
|
+
const hour = this.hourFrom(dateTimeString)
|
|
409
|
+
const hourPoints = hour * 100
|
|
410
|
+
const minutes = +dateTimeString.substring(14, 16)
|
|
411
|
+
const minutesPoints = +this.turnMinutesIntoPercentageOfHour(+minutes)
|
|
412
|
+
|
|
413
|
+
if (dayEnd > dayStart) {
|
|
414
|
+
const pointsInDay = dayEnd - dayStart
|
|
415
|
+
const eventPoints = hourPoints + minutesPoints
|
|
416
|
+
const eventPointsIntoDay = eventPoints - dayStart
|
|
417
|
+
|
|
418
|
+
return (eventPointsIntoDay / pointsInDay) * 100
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const hourPointsInOriginalDay = DAY_TIME_POINT.TWELVE_AM - dayStart
|
|
422
|
+
const pointsInDay = hourPointsInOriginalDay + dayEnd
|
|
423
|
+
const eventPoints = hourPoints + minutesPoints
|
|
424
|
+
const pointsIntoDay = eventPoints >= dayStart ? eventPoints - dayStart : hourPointsInOriginalDay + eventPoints
|
|
425
|
+
|
|
426
|
+
return (pointsIntoDay / pointsInDay) * 100
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
getTimeFromClick(
|
|
430
|
+
clickOffsetY: number,
|
|
431
|
+
weekHeight: number,
|
|
432
|
+
): string {
|
|
433
|
+
if (weekHeight <= 0) throw new Error('weekHeight cannot be a negative number')
|
|
434
|
+
if (clickOffsetY < 0) throw new Error('clickOffsetY cannot be a negative number')
|
|
435
|
+
|
|
436
|
+
const dayStartHour = this.DAY_START / 100
|
|
437
|
+
const hourHeight = weekHeight / this.HOURS_PER_DAY
|
|
438
|
+
const minutes = Math.floor((clickOffsetY % hourHeight) / (hourHeight / 60))
|
|
439
|
+
|
|
440
|
+
if (this.DAY_END <= this.DAY_START) {
|
|
441
|
+
const dayEndHour = this.DAY_END / 100
|
|
442
|
+
const nightHeight = (dayEndHour) * hourHeight
|
|
443
|
+
const nightOffset = weekHeight - nightHeight
|
|
444
|
+
|
|
445
|
+
if (clickOffsetY > nightOffset) {
|
|
446
|
+
const hour = Math.floor((clickOffsetY - nightOffset) / hourHeight)
|
|
447
|
+
return `${this.doubleDigit(hour)}:${this.doubleDigit(minutes)}`
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const hour = Math.floor(clickOffsetY / hourHeight) + dayStartHour
|
|
452
|
+
|
|
453
|
+
return `${this.doubleDigit(hour)}:${this.doubleDigit(minutes)}`
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
setSegmentOfDateTimeString(dateTimeString: string, segments: { hour: number }) {
|
|
457
|
+
if (segments.hour < 0 || segments.hour > 23) throw new Error('Invalid hour')
|
|
458
|
+
const newHour = this.doubleDigit(segments.hour)
|
|
459
|
+
dateTimeString = dateTimeString.replace(/\d{2}:/, `${newHour}:`)
|
|
460
|
+
|
|
461
|
+
return dateTimeString
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
isTrailingOrLeadingDate(date: Date, month: number) {
|
|
465
|
+
const d = new Date(date)
|
|
466
|
+
const dateMonth = d.getMonth()
|
|
467
|
+
|
|
468
|
+
return month !== dateMonth
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
static getTimePointsFromHour(boundary: number) {
|
|
472
|
+
if (boundary < 0 || boundary > 24 || boundary % 1 !== 0) {
|
|
473
|
+
throw new Error('Invalid day boundary')
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (boundary === 0) return boundary
|
|
477
|
+
|
|
478
|
+
return boundary * 100
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
static getHourFromTimePoints(timePoints: number) {
|
|
482
|
+
if (timePoints < 0 || timePoints > 2400 || timePoints % 100 !== 0) {
|
|
483
|
+
throw new Error('Invalid time points')
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (timePoints === 0) return timePoints
|
|
487
|
+
|
|
488
|
+
return timePoints / 100
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
getTimelineHours(): DAY_TIME_POINT[] {
|
|
492
|
+
if (this.dayMode !== DAY_MODE.FLEXIBLE) {
|
|
493
|
+
return this.ALL_HOURS.filter((hour) => {
|
|
494
|
+
return hour >= this.DAY_START && hour < this.DAY_END
|
|
495
|
+
})
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return [
|
|
499
|
+
...this.ALL_HOURS.filter(hour => hour >= this.DAY_START),
|
|
500
|
+
...this.ALL_HOURS.filter(hour => hour < this.DAY_END)
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
dateStringFrom(dateTimeString: string) {
|
|
505
|
+
return dateTimeString.substring(0, 10)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
timeStringFrom(dateTimeString: string) {
|
|
509
|
+
return dateTimeString.substring(11, 16)
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
hourFrom(dateTimeString: string) {
|
|
513
|
+
return +dateTimeString.substring(11, 13)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
minutesFrom(dateTimeString: string) {
|
|
517
|
+
return +dateTimeString.substring(14, 16)
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
areDaysConsecutive(dayOne: string, dayTwo: string) {
|
|
521
|
+
const dayOnePlusOneDay = this.dateStringFrom(this.addDaysToDateTimeString(1, dayOne))
|
|
522
|
+
|
|
523
|
+
return dayOnePlusOneDay === this.dateStringFrom(dayTwo)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
setHourInDateTimeString(dateTimeString: string, hour: number) {
|
|
527
|
+
const hourString = this.doubleDigit(hour)
|
|
528
|
+
dateTimeString = dateTimeString.replace(/\d{2}:/, `${hourString}:`)
|
|
529
|
+
|
|
530
|
+
return dateTimeString
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
setMinutesInDateTimeString(dateTimeString: string, minutes: number) {
|
|
534
|
+
const minutesString = this.doubleDigit(minutes)
|
|
535
|
+
dateTimeString = dateTimeString.replace(/:\d{2}/, `:${minutesString}`)
|
|
536
|
+
|
|
537
|
+
return dateTimeString
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
getDateTimeStringDayBoundariesFrom(dateString: string): { start: string, end: string } {
|
|
541
|
+
if (this.DAY_END <= this.DAY_START) {
|
|
542
|
+
const nextDay = this.addDaysToDateTimeString(1, dateString)
|
|
543
|
+
const endOfDay = this.setHourInDateTimeString(nextDay, this.getHourAndMinutesFromTimePoints(this.DAY_END).hour)
|
|
544
|
+
const startOfDay = this.setHourInDateTimeString(dateString, this.getHourAndMinutesFromTimePoints(this.DAY_START).hour)
|
|
545
|
+
|
|
546
|
+
return { start: startOfDay, end: endOfDay }
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const startOfDay = this.setHourInDateTimeString(dateString, this.getHourAndMinutesFromTimePoints(this.DAY_START).hour)
|
|
550
|
+
let endOfDay
|
|
551
|
+
if (this.DAY_END === DAY_TIME_POINT.TWELVE_AM) {
|
|
552
|
+
endOfDay = this.setHourInDateTimeString(dateString, 23)
|
|
553
|
+
endOfDay = this.setMinutesInDateTimeString(endOfDay, 59)
|
|
554
|
+
} else {
|
|
555
|
+
endOfDay = this.setHourInDateTimeString(dateString, this.getHourAndMinutesFromTimePoints(this.DAY_END).hour)
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return { start: startOfDay, end: endOfDay }
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
doubleDigit(number: number) {
|
|
562
|
+
if (number < 0 || number > 60) throw new Error('Invalid number. This is not a valid hour or minute')
|
|
563
|
+
|
|
564
|
+
return number < 10 ? `0${number}` : String(number)
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export class TimeBuilder {
|
|
569
|
+
private weekStartsOn: WEEK_START_DAY = WEEK_START_DAY.MONDAY
|
|
570
|
+
private locale: string | null = null
|
|
571
|
+
private dayBoundaries: { start: DAY_TIME_POINT, end: DAY_TIME_POINT } = { start: 0, end: 2400 }
|
|
572
|
+
|
|
573
|
+
build() {
|
|
574
|
+
return new Time(this.weekStartsOn, this.locale, this.dayBoundaries)
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
withDayBoundaries(dayBoundaries: { start: DAY_TIME_POINT, end: DAY_TIME_POINT }) {
|
|
578
|
+
this.dayBoundaries = dayBoundaries
|
|
579
|
+
|
|
580
|
+
return this
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
withLocale(locale: string) {
|
|
584
|
+
this.locale = locale
|
|
585
|
+
|
|
586
|
+
return this
|
|
587
|
+
}
|
|
588
|
+
}
|