Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Header with month and year in resourceTimelineMonth #386

Open
Sandbird opened this issue Nov 28, 2024 · 14 comments
Open

Header with month and year in resourceTimelineMonth #386

Sandbird opened this issue Nov 28, 2024 · 14 comments

Comments

@Sandbird
Copy link

I tried to implement something like this in the Header.svelte of resource-timeline, but failed epically. How hard would it be to implement something like this? I think it would be a nice feature instead of the centered title it has now.
(I am using a duration: {month: 3}, which is why I am asking. Easier on the eye when you scroll)

image

@vkurko
Copy link
Owner

vkurko commented Dec 4, 2024

Hello. Sorry, I don't have a quick answer right now. I'll think about the implementation.

@TommyU-mg
Copy link

TommyU-mg commented Dec 5, 2024

Hello,
I forked the repo and implemented this feature. It is not completely ready but you can have a look at it if you want.
I added the option to display timline over a year and a quarter, while displaying month and year in header.
you can easily change the 4 month timeframe to 3 months just by modifying one line of code.
https://github.com/Tommy975/calendar-timeline
header_calendar_timeline

@Sandbird
Copy link
Author

Sandbird commented Dec 5, 2024

Hi.
I do appreciate the implementation, and it does work perfectly for 1 day duration,
image

However, I am using "slotDuration: {seconds: 43200}" (basically splitting a day into x2 12h sets) and when i do that, nothing shows up on the header:
image

I am guessing something is going on with _dayTimes:
image

and i've been following through the code but cant figure out what goes wrong

@Tommy975
Copy link

Tommy975 commented Dec 5, 2024

I made a quick correction but it kind of break the layout for weekly timeline, (no hours) but you just have to play with the css a bit to make it appear again (change the header height). As i said it is a quick fix that might suits your particular needs but i'll have to take a more closer look at it for it to be fully functional.
calendar_timeline_header_12h

I'll try to make a more permanent fix during the weekend. Here how it could look with a modified header height:
calendar_timeline_header_12h_modified_header_height

@Sandbird
Copy link
Author

Sandbird commented Dec 5, 2024

Oh nice, thank you. I'll take a look at it first thing tomorrow morning and report back!

@Sandbird
Copy link
Author

Sandbird commented Dec 6, 2024

It is perfect! Thank you so much!
image

Just one small suggestion, in the 'viewMonths' function (core\index.js), pass the locale variable so it grabs the default value set in calendar options.

image

@Tommy975
Copy link

Tommy975 commented Dec 6, 2024

I have included your suggestion to my last push. Also I wouldn't mind you sharing your css for the events :).

@Sandbird
Copy link
Author

Sandbird commented Dec 7, 2024

It's the least I can do :) I've created a codepen for it. Also added comments in the css to explain what goes where.
The eventContent function handles all the magic. If you don’t need the popup, you can simply remove the props.desc part.
https://codepen.io/sandbird/pen/WbewwRy

(Resizing the events behaves strangely in codepen for some reason. It works fine as an html file)

@Sandbird
Copy link
Author

Sandbird commented Dec 7, 2024

I just noticed that there is something wrong with the 'viewMonths' function. It doesn't create the proper month set. For example look at January in the screenshot.
My guess is due to the datetimes sent by the calendar itself. I've also struggled with start/end/startStr/endStr values.

image
image

For now, I recreated the array, but it kept pushing just 1 date entry to a 4th month array (Febr. in my case), which I decided to just delete any arrays that are not full month sets. 'Hacky' way I know, but I just cant handle this whole UTC+2 different start/end dates anymore.

const greekMonths = {
    "Ιανουάριος": 0,  // January
    "Φεβρουάριος": 1, // February
    "Μάρτιος": 2,     // March
    "Απρίλιος": 3,    // April
    "Μάιος": 4,       // May
    "Ιούνιος": 5,     // June
    "Ιούλιος": 6,     // July
    "Αύγουστος": 7,   // August
    "Σεπτέμβριος": 8, // September
    "Οκτώβριος": 9,   // October
    "Νοέμβριος": 10,  // November
    "Δεκέμβριος": 11  // December
};

function viewMonths(state) {
	return derived([state._activeRange, state.hiddenDays, state.locale], ([$_activeRange, $hiddenDays, $locale]) => {
		let groupedDates = {};
		let date = (cloneDate($_activeRange.start));
		let end = (cloneDate($_activeRange.end));

		while (date < end) {
			if (!$hiddenDays.includes(date.getUTCDay())) {
				const monthKey = ucFirst(date.toLocaleString($locale, { month: 'long', year: 'numeric' }));

				// Initialize the array for the month if it doesn't exist
				if (!groupedDates[(monthKey)] ) {
					groupedDates[(monthKey)] = [];
				}

				// Push the current date into the month's array
				groupedDates[monthKey].push(cloneDate(date));
			}
			addDay(date);
		}

		// Iterate over the object
		for (const key in groupedDates) {
			let [month, year] = key.split(" ");

			// Get the numeric month index from the Greek month name
			let monthIndex = greekMonths[month];

			// Get the total number of days in this month
			let totalDaysInMonth = new Date(year, monthIndex + 1, 0).getDate();
			// If the number of dates in the array is less than the total number of days in that month, remove the month
			if (groupedDates[key].length !== totalDaysInMonth) {
				delete groupedDates[(key)];
			}
		}
		return groupedDates;
	});
}

Edit: Something is happening with the borders as well on header. I've brought 6 months of data and the vertical lines dont line up with the calendar grid towards the end.

@TommyU-mg
Copy link

for the borders, i will push the corrected css. and i'll ad a commented version of viewMonths try it instead of the current one and tell me if it works for you.

@Sandbird
Copy link
Author

Sandbird commented Dec 9, 2024

Yeah, I think it works great now with the column matching. I've added a whole year and all lines align perfectly.
The 'groupedDates' array is still messed up though (orange). As you can see the January array has been pushed by one day, so although it says 31 days, the 1st value is the last day of December, so it's cutting down the last day of January.
Also, something that I just noticed, the height of the rows on the grid, doesnt match up the tree height on the side. Probably due to .ec-resource { max-height: 33px !important;} plus a few other changes that were added in the initial change...still trying to figure them out
image

@Sandbird
Copy link
Author

Sandbird commented Dec 10, 2024

The misalignment was fixed by removing the article class and chaning the height to min-height in packages\core\src\styles\timeline.scss
image

Also disable this in \packages\core\src\styles\index.scss

image

@Sandbird
Copy link
Author

I’ve completed all the fixes, and everything is working perfectly now. The cell alignment issue has been resolved, and the header looks great.

Instead of using the event-calendar.css, I made the necessary adjustments through an overwrite css,. You can find it here: link.

So in the end, using your existing event-calendar.js file along with the following updated viewMonths function in \packages\core\src\storage\stores.js, the calendar now populates all months correctly in the arrays, ensuring no dates are missing.

export function viewMonths(state) {
	return derived([state._activeRange, state.hiddenDays, state.locale], ([$_activeRange, $hiddenDays, $locale]) => {

        let groupedDates = {};
        let date = (cloneDate($_activeRange.start));
        let end = (cloneDate($_activeRange.end));

        while (date < end) {
            if (!$hiddenDays.includes(date.getUTCDay())) {
                const monthKey = ucFirst(date.toLocaleString($locale, { month: 'long', year: 'numeric' }));

                // Initialize the array for the month if it doesn't exist
                if (!groupedDates[(monthKey)] ) {
                    groupedDates[(monthKey)] = [];
                }

                // Push the current date into the month's array
                groupedDates[monthKey].push(cloneDate(date));
            }
            addDay(date);
        }
	return groupedDates;
	});
}

(I separated the css changes into a standalone file, so that any future updates can be made exclusively within the js file.)

@TommyU-mg
Copy link

TommyU-mg commented Dec 11, 2024

There was already a similar version of viewMonths commented out in the code:

the one i am using wich works for me:

export function viewMonths(state) {
    return derived([state._activeRange, state.hiddenDays, state.locale], ([$_activeRange, $hiddenDays, $local]) => {
        let groupedDates = {};
        let date = setMidnight(cloneDate($_activeRange.start));
        let end = setMidnight(cloneDate($_activeRange.end));
        addDay(date);
        let counter = 0;
        while (date < end) {
            if (!$hiddenDays.includes(date.getUTCDay())) {
                const monthKey = ucFirst(date.toLocaleString($local, { month: 'long', year: 'numeric' }));

                // Initialize the array for the month if it doesn't exist
                if (!groupedDates[(monthKey)] ) {
                    counter = 0
                    groupedDates[(monthKey)] = [];
                }

                // Push the current date into the month's array
                if( counter == 0){
                    groupedDates[(monthKey)].push(cloneDate(subtractDay(date)));
                } else {
                    let tempDate =  cloneDate(date);
                    let nextDateMonthKey = ucFirst(addDay(tempDate).toLocaleString($local, { month: 'long', year: 'numeric' }));
                    
                    if ( nextDateMonthKey == monthKey ) 
                        groupedDates[(monthKey)].push(cloneDate(date));
                }
            }
            addDay(date);
            counter++;
        }
        return groupedDates;
    });
} 

The commented out (same as yours except for the setMidnight method):

// export function viewMonths(state) {
//     return derived([state._activeRange, state.hiddenDays, state.locale], ([$_activeRange, $hiddenDays, $local]) => {
//         let groupedDates = {};
//         let date = setMidnight(cloneDate($_activeRange.start));
//         let end = setMidnight(cloneDate($_activeRange.end));

//         while (date < end) {
//             if (!$hiddenDays.includes(date.getUTCDay())) {
//                 const monthKey = ucFirst(date.toLocaleString($local, { month: 'long', year: 'numeric' }));

//                 // Initialize the array for the month if it doesn't exist
//                 if (!groupedDates[(monthKey)] ) {
//                     groupedDates[(monthKey)] = [];
//                 }

//                 // Push the current date into the month's array
//                 groupedDates[(monthKey)].push(cloneDate(date));

//             }
//             addDay(date);
//             // counter++;
//         }
//         return groupedDates;
//     });
// } 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

the second version is the one making more sense but I have no idea why it is not working for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants