Last Sync: 2026-01-01 23:10 (Mobile)

This commit is contained in:
2026-01-01 23:10:48 +09:00
parent 401f536b3b
commit efefcb9046
2719 changed files with 0 additions and 254620 deletions

View File

@@ -1,219 +0,0 @@
# Taskido: Obsidian-Tasks-Timeline
## [Click here!](https://github.com/702573N/Obsidian-Tasks-Timeline)
<p align="center"><img width="400" alt="Semi_Transparent" src="https://user-images.githubusercontent.com/59178587/210307060-5ed916ee-819d-46b1-9a5e-efdd15728957.png"></p>
---
# Obsidian-Tasks-Calendar
#### A custom view build with [Obsidian-Dataview](https://github.com/blacksmithgu/obsidian-dataview) to display tasks from [Obsidian-Tasks](https://github.com/obsidian-tasks-group/obsidian-tasks) and from your daily notes in a highly customisable calendar with a wide variety of views
![light](https://user-images.githubusercontent.com/59178587/203789595-ede6138f-2c29-4148-b52f-874ab3ea43f7.png)
## Story
All Obsidian and Task Plugin users love the program. What has been set up with the Task Plugin is just great and helps so many people to organize their work. However, just listing tasks according to certain criteria is sometimes a bit boring. To get a quick visual impression of one's workday/workweek/workmonth, a calendar view would be ideal. To be honest, I'm too stupid to program my own plugins for Obsidian, but I know some Javascript, so I programmed this Dataview snippet. I hope to offer many people a good addition to the Task Plugin and hope for an integration into the Task Plugin someday. But I'm sure there are better programmers out there, who can make my code, which is probably horrible for professionals, much better.
## Setup
1. Install "Dataview Plugin" from the external plugins
2. Create a new folder called "tasksCalendar" or any other name and paste the files "view.js" and "view.css" into it
![Tree Demo](https://user-images.githubusercontent.com/59178587/203789303-4474847e-ab84-4f33-8665-c17ca887ec79.png)
3. Create a new note or edit an existing one and add the following code line:
````
```dataviewjs
await dv.view("tasksCalendar", {pages: "", view: "month", firstDayOfWeek: "1", options: "style1"})
```
````
If you paste the main files (js/css) into another folder then "tasksCalendar", you have to replace the name between the first quotation marks.
4. There are 4 different variables to set path/location as "pages", calendar view style as "view", first day of the week (0 or 1) as "firstDayOfWeek" and some style classes as "options"
---
## Required parameters
### pages:
For help and instruction take a look here [Dataview Help](https://blacksmithgu.github.io/obsidian-dataview/api/code-reference/#dvpagessource)
```
pages: ""
```
Get all tasks from all notes in obsidian.
```
pages: '"Task Management/Work"'
```
Set a custom folder to get tasks from.
The dv.pages command is the same and works exactly the same like in dataview-plugin.
```
pages: "dv.pages().file.tasks.where(t => t.tags.includes('#Pierre'))"
pages: "dv.pages().file.tasks.where(t=>!t.checked && t.header.subpath != 'Log')"
pages: "dv.pages().file.where(f=>f.tags.includes('#ToDo') || f.tags.includes('#Task')).where(f=>f.folder != 'Inbox').tasks"
```
It is also possible to define complex queries. These must start with `dv.pages` and output tasks as a result.
### view:
```
view: "list"
view: "month"
view: "week"
```
With the view parameter you can set the default calendar view.
### firstDayOfWeek:
```
firstDayOfWeek: "1"
firstDayOfWeek: "0"
```
Set monday (1) or sunday (0) as first day of week
### options:
```
options: "style1"
```
You have multiple options to personalize your Tasks-Calendar. The absolutelely must have is to set a custom week view style (style1, style2, ...) as your default week view style. However, you can switch between the individual styles at any time in the calendar itself by clicking the week view button again if this view is active.
<img width="1982" alt="Style-switcher" src="https://user-images.githubusercontent.com/59178587/203786071-eb97d99d-507b-4a92-9812-ba5cf6fd66ad.png">
But that's not all. With the options parameter you can hide things you don't need or like, get a mini version of the calendar and many more...
```
options: "noIcons"
```
Hide the task icons in front of each task.
```
options: "noProcess"
```
By default the Tasks-Calendar show up tasks with a start- and a due-date on all days between these two like a calendar app displays all-day events across all days from the first to the last day. If you don't like this, you can turn it off with the `noProcess` option.
```
options: "noDailyNote"
```
Hide daily notes inside calendar
Some users do not use the Task plugin, but work mainly with daily notes. To enable these users to use the functionality of this calendar, all tasks from daily notes are displayed on the respective date of the daily note. As some task plugin users may also work with daily notes, some may find it annoying to see them in the calendar as well between all Task plugin stuff. With the option `noDailyNote` you can hide all tasks (without any Task plugin date syntax) from your calendar.
```
options: "noCellNameEvent"
```
By default you can click on each cell name to jump directly into the daily note. If no daily note with this date exist, a new one will be created. This is nice for hardcore daily note users, but for others it could be annoying. To prevent unintentional execution you can disable the cell name click-events with the option `noCellNameEvent`.
```
options: "mini"
```
Reduces the calendar width, height and font sizes to a more compact format. This can be used to embed the calendar into a complex sidebar in Obsidian.
On mobile devices, the font size is automatically reduced (on some views) because the limited screen size.
```
options: "noWeekNr"
```
Hide the week number in front of each week-wrapper inside the month calendar. After deactivation, it is unfortunately no longer possible to jump directly to a desired week.
```
options: "noFilename"
```
Hides the task header line with the note file name
```
options: "lineClamp1"
options: "lineClamp2"
options: "lineClamp3"
options: "noLineClamp"
```
Set a line clamp from 1-3 inside your displayed tasks. By default 1 line is set. Alternative you can disable line clamp and show full task description text.
```
options: "noLayer"
```
The back layer of the grid with the month or week information can be hidden with this.
```
options: "noOverdueDays"
```
You can use this option to hide the overdue days flag on overdue tasks.
### Optional parameters
#### dailyNoteFolder:
```
dailyNoteFolder: "MyCustomFolder"
dailyNoteFolder: "Inbox/Daily Notes/Work"
```
This parameter must only be specified if this is to be used. Here you can define a custom folder path for the daily notes if they should not be saved in the default folder for new files. Of course, folder structures with several levels can also be defined here. This paramter
#### dailyNoteFormat:
```
dailyNoteFormat: "YYYY, MMMM DD - dddd"
dailyNoteFormat: "YYYY-[W]ww"
```
This parameter must only be specified if this is to be used. Without this parameter the default format "YYYY-MM-DD" is used to identify your daily notes. You can set a custom format with a limited base set of characters: Y M D [W] ww d . , - : (SPACE)
#### startPosition:
Month: 2022 - December
```
view: "month"
startPosition: "2022-12"
```
Week: 2022 - W50
```
view: "week"
startPosition: "2022-50"
```
This parameter is optional and can be used to set a custom month or week to give focus after load. The default format on month view is `YYYY-MM`and on week view `YYYY-ww`. The first 4 digits represents the year and the last 1-2 digits represents the month or the week. Both must be separated with a minus character.
#### globalTaskFilter:
```
globalTaskFilter: "#task"
```
This parameter must only be specified if this is to be used. Set a global task filter to hide from task text/description inside tasks-calendar.
#### css:
```
css: ".tasksCalendar.style4[view='week'] .grid { height: 300px !important }"
```
Now you can write custom css rules inside a css parameter. Please use the developer console to identify the elements classes! Each style string should start with .tasksCalendar to avoid css conflicts!
---
## Note colors and icon
In each note file you can define custom "color" and "icon" to show up in the calendar. To do so, you only need to add the following metadata to the first line of your note. By default the note-color is used for the dimmed background and as text-color. If you would like to give your tasks a completely different color then the note-color itself, then use the textColor meta.
```
---
color: "#bf5af2"
textColor: "#000000"
icon: "❤️"
---
```
The color should be hex in quotation marks to work properly. This color is set for text and as semi-transparent background. The icon itself is placed in front of the task filename header.
![Note Color Demo](https://user-images.githubusercontent.com/59178587/203788233-555edbc4-915c-499c-bdf4-87c6030bfd55.png)
---
## Filter
On the upper left corner of each calendar-view is a filter-icon to show or hide all done and cancelled tasks. The default-filter is set by options. If you have `filter` inside your options parameter, the filter is enabled by default.
![Filter Demo](https://user-images.githubusercontent.com/59178587/203787018-483bf485-3ce5-43b4-99ae-2a3a8efbf690.png)
---
## Statistic and focus
On the upper right corner is statistic button which opens a detailed list of all your tasks for the currently selected month/week. By selecting a task type you can focusing this tasks and dimm out all others. This way you can find the tasks you are looking for more easily.
Through a meaningful icon and a counter, you can quickly get an overview of incompleted tasks within the selected month/week without opening the pop-up window.
![Focus Demo](https://user-images.githubusercontent.com/59178587/203786131-6ddf1389-8b66-4f3c-9d7a-121c5fe38540.png)

View File

@@ -1,219 +0,0 @@
# Taskido: Obsidian-Tasks-Timeline
## [Click here!](https://github.com/702573N/Obsidian-Tasks-Timeline)
<p align="center"><img width="400" alt="Semi_Transparent" src="https://user-images.githubusercontent.com/59178587/210307060-5ed916ee-819d-46b1-9a5e-efdd15728957.png"></p>
---
# Obsidian-Tasks-Calendar
#### A custom view build with [Obsidian-Dataview](https://github.com/blacksmithgu/obsidian-dataview) to display tasks from [Obsidian-Tasks](https://github.com/obsidian-tasks-group/obsidian-tasks) and from your daily notes in a highly customisable calendar with a wide variety of views
![light](https://user-images.githubusercontent.com/59178587/203789595-ede6138f-2c29-4148-b52f-874ab3ea43f7.png)
## Story
All Obsidian and Task Plugin users love the program. What has been set up with the Task Plugin is just great and helps so many people to organize their work. However, just listing tasks according to certain criteria is sometimes a bit boring. To get a quick visual impression of one's workday/workweek/workmonth, a calendar view would be ideal. To be honest, I'm too stupid to program my own plugins for Obsidian, but I know some Javascript, so I programmed this Dataview snippet. I hope to offer many people a good addition to the Task Plugin and hope for an integration into the Task Plugin someday. But I'm sure there are better programmers out there, who can make my code, which is probably horrible for professionals, much better.
## Setup
1. Install "Dataview Plugin" from the external plugins
2. Create a new folder called "tasksCalendar" or any other name and paste the files "view.js" and "view.css" into it
![Tree Demo](https://user-images.githubusercontent.com/59178587/203789303-4474847e-ab84-4f33-8665-c17ca887ec79.png)
3. Create a new note or edit an existing one and add the following code line:
````
```dataviewjs
await dv.view("tasksCalendar", {pages: "", view: "month", firstDayOfWeek: "1", options: "style1"})
```
````
If you paste the main files (js/css) into another folder then "tasksCalendar", you have to replace the name between the first quotation marks.
4. There are 4 different variables to set path/location as "pages", calendar view style as "view", first day of the week (0 or 1) as "firstDayOfWeek" and some style classes as "options"
---
## Required parameters
### pages:
For help and instruction take a look here [Dataview Help](https://blacksmithgu.github.io/obsidian-dataview/api/code-reference/#dvpagessource)
```
pages: ""
```
Get all tasks from all notes in obsidian.
```
pages: '"Task Management/Work"'
```
Set a custom folder to get tasks from.
The dv.pages command is the same and works exactly the same like in dataview-plugin.
```
pages: "dv.pages().file.tasks.where(t => t.tags.includes('#Pierre'))"
pages: "dv.pages().file.tasks.where(t=>!t.checked && t.header.subpath != 'Log')"
pages: "dv.pages().file.where(f=>f.tags.includes('#ToDo') || f.tags.includes('#Task')).where(f=>f.folder != 'Inbox').tasks"
```
It is also possible to define complex queries. These must start with `dv.pages` and output tasks as a result.
### view:
```
view: "list"
view: "month"
view: "week"
```
With the view parameter you can set the default calendar view.
### firstDayOfWeek:
```
firstDayOfWeek: "1"
firstDayOfWeek: "0"
```
Set monday (1) or sunday (0) as first day of week
### options:
```
options: "style1"
```
You have multiple options to personalize your Tasks-Calendar. The absolutelely must have is to set a custom week view style (style1, style2, ...) as your default week view style. However, you can switch between the individual styles at any time in the calendar itself by clicking the week view button again if this view is active.
<img width="1982" alt="Style-switcher" src="https://user-images.githubusercontent.com/59178587/203786071-eb97d99d-507b-4a92-9812-ba5cf6fd66ad.png">
But that's not all. With the options parameter you can hide things you don't need or like, get a mini version of the calendar and many more...
```
options: "noIcons"
```
Hide the task icons in front of each task.
```
options: "noProcess"
```
By default the Tasks-Calendar show up tasks with a start- and a due-date on all days between these two like a calendar app displays all-day events across all days from the first to the last day. If you don't like this, you can turn it off with the `noProcess` option.
```
options: "noDailyNote"
```
Hide daily notes inside calendar
Some users do not use the Task plugin, but work mainly with daily notes. To enable these users to use the functionality of this calendar, all tasks from daily notes are displayed on the respective date of the daily note. As some task plugin users may also work with daily notes, some may find it annoying to see them in the calendar as well between all Task plugin stuff. With the option `noDailyNote` you can hide all tasks (without any Task plugin date syntax) from your calendar.
```
options: "noCellNameEvent"
```
By default you can click on each cell name to jump directly into the daily note. If no daily note with this date exist, a new one will be created. This is nice for hardcore daily note users, but for others it could be annoying. To prevent unintentional execution you can disable the cell name click-events with the option `noCellNameEvent`.
```
options: "mini"
```
Reduces the calendar width, height and font sizes to a more compact format. This can be used to embed the calendar into a complex sidebar in Obsidian.
On mobile devices, the font size is automatically reduced (on some views) because the limited screen size.
```
options: "noWeekNr"
```
Hide the week number in front of each week-wrapper inside the month calendar. After deactivation, it is unfortunately no longer possible to jump directly to a desired week.
```
options: "noFilename"
```
Hides the task header line with the note file name
```
options: "lineClamp1"
options: "lineClamp2"
options: "lineClamp3"
options: "noLineClamp"
```
Set a line clamp from 1-3 inside your displayed tasks. By default 1 line is set. Alternative you can disable line clamp and show full task description text.
```
options: "noLayer"
```
The back layer of the grid with the month or week information can be hidden with this.
```
options: "noOverdueDays"
```
You can use this option to hide the overdue days flag on overdue tasks.
### Optional parameters
#### dailyNoteFolder:
```
dailyNoteFolder: "MyCustomFolder"
dailyNoteFolder: "Inbox/Daily Notes/Work"
```
This parameter must only be specified if this is to be used. Here you can define a custom folder path for the daily notes if they should not be saved in the default folder for new files. Of course, folder structures with several levels can also be defined here. This paramter
#### dailyNoteFormat:
```
dailyNoteFormat: "YYYY, MMMM DD - dddd"
dailyNoteFormat: "YYYY-[W]ww"
```
This parameter must only be specified if this is to be used. Without this parameter the default format "YYYY-MM-DD" is used to identify your daily notes. You can set a custom format with a limited base set of characters: Y M D [W] ww d . , - : (SPACE)
#### startPosition:
Month: 2022 - December
```
view: "month"
startPosition: "2022-12"
```
Week: 2022 - W50
```
view: "week"
startPosition: "2022-50"
```
This parameter is optional and can be used to set a custom month or week to give focus after load. The default format on month view is `YYYY-MM`and on week view `YYYY-ww`. The first 4 digits represents the year and the last 1-2 digits represents the month or the week. Both must be separated with a minus character.
#### globalTaskFilter:
```
globalTaskFilter: "#task"
```
This parameter must only be specified if this is to be used. Set a global task filter to hide from task text/description inside tasks-calendar.
#### css:
```
css: ".tasksCalendar.style4[view='week'] .grid { height: 300px !important }"
```
Now you can write custom css rules inside a css parameter. Please use the developer console to identify the elements classes! Each style string should start with .tasksCalendar to avoid css conflicts!
---
## Note colors and icon
In each note file you can define custom "color" and "icon" to show up in the calendar. To do so, you only need to add the following metadata to the first line of your note. By default the note-color is used for the dimmed background and as text-color. If you would like to give your tasks a completely different color then the note-color itself, then use the textColor meta.
```
---
color: "#bf5af2"
textColor: "#000000"
icon: "❤️"
---
```
The color should be hex in quotation marks to work properly. This color is set for text and as semi-transparent background. The icon itself is placed in front of the task filename header.
![Note Color Demo](https://user-images.githubusercontent.com/59178587/203788233-555edbc4-915c-499c-bdf4-87c6030bfd55.png)
---
## Filter
On the upper left corner of each calendar-view is a filter-icon to show or hide all done and cancelled tasks. The default-filter is set by options. If you have `filter` inside your options parameter, the filter is enabled by default.
![Filter Demo](https://user-images.githubusercontent.com/59178587/203787018-483bf485-3ce5-43b4-99ae-2a3a8efbf690.png)
---
## Statistic and focus
On the upper right corner is statistic button which opens a detailed list of all your tasks for the currently selected month/week. By selecting a task type you can focusing this tasks and dimm out all others. This way you can find the tasks you are looking for more easily.
Through a meaningful icon and a counter, you can quickly get an overview of incompleted tasks within the selected month/week without opening the pop-up window.
![Focus Demo](https://user-images.githubusercontent.com/59178587/203786131-6ddf1389-8b66-4f3c-9d7a-121c5fe38540.png)

View File

@@ -1,10 +0,0 @@
---
cssclasses:
- dashboard
---
```dataviewjs
await dv.view("tasksCalendar", {pages: "", view: "week", firstDayOfWeek: "1", options: "style1"})
```

View File

@@ -1,10 +0,0 @@
---
cssclasses:
- dashboard
---
```dataviewjs
await dv.view("tasksCalendar", {pages: "", view: "week", firstDayOfWeek: "1", options: "style1"})
```

View File

@@ -1,722 +0,0 @@
.tasksCalendar span {
display: contents;
}
.tasksCalendar .buttons {
cursor: default;
width: 100%;
height: 30px;
display: flex;
flex-wrap: nowrap;
flex-direction: row;
margin-bottom: 4px;
}
.tasksCalendar[view='list'] button.listView,
.tasksCalendar[view='week'] button.weekView,
.tasksCalendar[view='month'] button.monthView,
.tasksCalendar.filter button.filter {
background: var(--background-modifier-active-hover);
}
body:not(.is-mobile) .tasksCalendar button.listView:hover,
body:not(.is-mobile) .tasksCalendar button.weekView:hover,
body:not(.is-mobile) .tasksCalendar button.monthView:hover,
body:not(.is-mobile) .tasksCalendar button.previous:hover,
body:not(.is-mobile) .tasksCalendar button.next:hover,
body:not(.is-mobile) .tasksCalendar button.current:hover,
body:not(.is-mobile) .tasksCalendar button.filter:hover,
body:not(.is-mobile) .tasksCalendar button.statistic:hover {
background: var(--background-modifier-hover);
}
.tasksCalendar[view='list'] button.listView svg,
.tasksCalendar[view='month'] button.monthView svg,
.tasksCalendar[view='week'] button.weekView svg,
.tasksCalendar.filter button.filter svg {
stroke: var(--icon-color-active) !important;
}
.tasksCalendar button {
background-color: transparent;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 5px;
color: var(--icon-color);
height: 30px;
box-shadow: none;
border: 1px solid var(--nav-item-background-active);
font-weight: normal;
font-size: 14px;
background: var(--background-secondary);
padding: 4px 6px;
outline: none;
user-select: none;
white-space: nowrap;
flex: 0;
}
.tasksCalendar button:nth-child(2),
.tasksCalendar button:nth-child(3),
.tasksCalendar button:nth-child(6) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: 0.5px solid var(--nav-item-background-active);
margin-right: 0;
}
.tasksCalendar button:nth-child(3),
.tasksCalendar button:nth-child(4),
.tasksCalendar button:nth-child(7) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left: 0.5px solid var(--nav-item-background-active);
margin-left: 0;
}
.tasksCalendar .current {
margin: 0 4px;
display: inline;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.tasksCalendar .current span:first-child {
font-weight: bold;
color: var(--icon-color);
}
.tasksCalendar .current span:last-child {
font-weight: normal;
color: var(--icon-color-active);
}
.tasksCalendar button:nth-child(1) {
margin-right: 4px;
}
.tasksCalendar button:nth-child(8) {
margin-left: 4px;
}
.tasksCalendar svg {
height: var(--icon-size);
width: var(--icon-size);
stroke-width: var(--icon-stroke);
}
.tasksCalendar .statisticPopup,
.tasksCalendar .weekViewContext {
display: none;
border-radius: 5px;
font-size: 10px;
border: 1px solid var(--nav-item-background-active);
position: absolute;
height: auto;
width: 150px;
width: auto;
background: var(--icon-color);
margin: 0 !important;
list-style: none;
padding: 2px !important;
z-index: 99;
box-shadow: 0px 0px 10px 0px var(--nav-item-background-active);
background: var(--background-secondary);
}
.tasksCalendar .statisticPopup {
right: 0;
}
.tasksCalendar .weekViewContext {
left: 65px;
}
.tasksCalendar .statisticPopup:before,
.tasksCalendar .weekViewContext:before {
content: "";
width: 0px;
height: 0px;
-webkit-transform:rotate(360deg);
border-style: solid;
border-width: 0 10px 10px 10px;
border-color: transparent transparent var(--background-secondary) transparent;
position: absolute;
}
.tasksCalendar .statisticPopup:before {
top: -10px;
right: 5px;
}
.tasksCalendar .weekViewContext:before {
top: -10px;
left: 5px;
}
.tasksCalendar .statisticPopup.active,
.tasksCalendar .weekViewContext.active {
display: block;
}
.tasksCalendar .statisticPopup li,
.tasksCalendar .weekViewContext li {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
height: auto;
font-size: 14px;
list-style: none;
color: var(--text-normal);
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
}
.tasksCalendar .statisticPopup li.active,
.tasksCalendar .weekViewContext li.active {
background: var(--background-modifier-active-hover);
color: var(--icon-color-active) !important;
}
body:not(.is-mobile) .tasksCalendar .statisticPopup li:not(.active):hover,
body:not(.is-mobile) .tasksCalendar .weekViewContext li:not(.active):hover {
background: var(--background-modifier-hover);
}
.tasksCalendar .statisticPopup li.break,
.tasksCalendar .weekViewContext li.break {
height: 1px !important;
background: var(--nav-item-background-active);
margin: 2px 5px !important;
border-radius: 0 !important;
padding: 0 !important;
}
.tasksCalendar .statisticPopup > div,
.tasksCalendar .weekViewContext > div {
height: 13px;
margin: auto 0;
}
.tasksCalendar button.statistic {
position: relative;
}
.tasksCalendar button.statistic svg {
stroke: var(--icon-color);
}
.tasksCalendar button.statistic[data-percentage="100"]:after {
display: none !important;
}
.tasksCalendar button.statistic:after {
content: attr(data-remaining);
position: absolute;
height: 14px;
width: 14px;
top: -8px;
right: -8px;
border-radius: 50%;
text-align: center;
line-height: 14px;
font-size: 9px;
font-weight: bold;
border: 1px solid var(--nav-item-background-active);
overflow: hidden;
color: var(--icon-color);
background: var(--background-secondary);
}
.tasksCalendar .weekViewContext .liIcon {
display: grid !important;
height: 18px;
width: 18px;
margin-right: 5px;
padding: 2px;
}
.tasksCalendar .weekViewContext .liIcon .box {
background: var(--icon-color);
z-index: 1;
display: grid;
overflow: hidden;
margin: 0.5px;
border-radius: 1px;
}
.tasksCalendar .weekViewContext li.active .liIcon .box {
background: var(--icon-color-active) !important;
}
.tasksCalendar .grid {
overflow: hidden;
cursor: default;
width: 100%;
height: 75vH;
}
.tasksCalendar .list {
overflow-x: hidden;
overflow-y: auto;
cursor: default;
width: 100%;
height: 75vH;
}
.tasksCalendar .cell {
z-index: 1;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 1fr;
overflow: hidden;
margin: 1px 0;
}
.tasksCalendar .cellContent {
overflow-x: hidden;
overflow-y: auto;
align-content: start;
padding: 1px 0;
}
.tasksCalendar .cellContent::-webkit-scrollbar {
display: none;
}
.tasksCalendar .cellName {
display: block;
font-weight: normal;
padding: 0 2px;
color: var(--text-normal);
flex-shrink: 0;
flex-grow: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
text-align: left;
margin: 0;
font-size: 14px;
opacity: 0.8;
}
body:not(.is-mobile) .tasksCalendar .cellName:hover {
opacity: 1;
}
.tasksCalendar .task {
overflow: hidden;
padding: 1px;
background: var(--task-background);
border-radius: 3px;
overflow: hidden;
margin: 1px 1px 2px 1px;
font-size: 14px;
opacity: 0.8;
display: block;
}
body.theme-dark .tasksCalendar .task { color: var(--light-task-text-color); }
body.theme-light .tasksCalendar .task { color: var(--dark-task-text-color); }
body.theme-dark .tasksCalendar .task .note { color: var(--light-task-text-color); }
body.theme-light .tasksCalendar .task .note { color: var(--dark-task-text-color); }
body:not(.is-mobile) .tasksCalendar .task:hover {
opacity: 1;
}
.tasksCalendar .task.hide {
opacity: 0.2;
}
.tasksCalendar .task .inner {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-decoration: none;
word-break: break-all !important;
-webkit-hyphens: none !important;
line-height: 1.3;
text-decoration: none !important;
border-radius: 3px;
overflow: hidden;
}
.tasksCalendar a {
text-decoration: none !important;
}
.tasksCalendar .task .note {
display: block;
width: 100%;
font-size: 9px;
background: var(--task-background);
padding: 1px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.tasksCalendar .task .icon {
display: inline;
width: 18px;
height: 18px;
text-align: center;
margin-right: 3px;
}
.tasksCalendar .task .description {
display: inline;
padding: 1px;
}
.tasksCalendar .task .description:before {
display: inline;
content: attr(data-relative);
margin-right: 3px;
border-radius: 3px;
margin-right: 3px;
padding: 0 3px;
font-size: 9px;
vertical-align: middle;
}
.tasksCalendar .task.overdue .description:before {
color: white;
background: #ff443a;
}
.tasksCalendar .task:not(.overdue) .description:before {
display: none;
background: black;
color: white;
}
.tasksCalendar .task.dailyNote .description:before,
.tasksCalendar .task.done .description:before,
.tasksCalendar .task.cancelled .description:before {
display: none !important;
}
.tasksCalendar .task.cancelled .note,
.tasksCalendar .task.done .note {
background: var(--nav-item-background-active) !important;
color: var(--text-faint) !important;
}
.tasksCalendar .task.cancelled .description,
.tasksCalendar .task.done .description {
text-decoration: line-through !important;
color: var(--text-faint) !important;
}
.tasksCalendar .task.cancelled,
.tasksCalendar .task.done {
background: none !important;
}
.tasksCalendar .task.overdue .inner {
background: repeating-linear-gradient(45deg, var(--task-background), var(--task-background) 5px, transparent 5px, transparent 10px) !important;
}
/* Today & Weekends */
.tasksCalendar .cell.today .cellName {
font-weight: bold;
color: var(--text-normal);
opacity: 1;
}
.tasksCalendar .cell[data-weekday="0"].today .cellName {
font-weight: bold;
color: var(--icon-color-active);
opacity: 1;
}
.tasksCalendar[view='month'] .cell.today {
background: var(--background-modifier-active-hover) !important;
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25) !important;
border-radius: 5px;
}
.tasksCalendar[view='week'] .cell.today {
background: var(--background-modifier-active-hover) !important;
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25) !important;
}
.tasksCalendar .cell[data-weekday="0"] .cellName,
.tasksCalendar .gridHead[data-weekday="0"] {
color: var(--icon-color-active);
}
/* Month View */
.tasksCalendar[view='month'] .grid {
display: grid;
gap: 4px;
grid-template-rows: 20px 1fr !important;
grid-template-columns: 1fr !important;
}
.tasksCalendar[view='month'] .gridHeads {
display: grid;
grid-template-columns: 20px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important;
width: 100%;
height: 20px;
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
}
.tasksCalendar[view='month'] .gridHead {
display: inline;
box-sizing: border-box;
overflow: hidden;
text-align: center;
font-weight: bold;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0;
font-size: 14px;
height: 20px;
line-height: 20px;
font-size: 10px;
}
.tasksCalendar[view='month'] .wrappers {
display: grid;
grid-template-rows: repeat(6, calc(100% / 6));
grid-template-columns: 1fr !important;
min-height: 0;
height: calc(100% - 20px);
gap: 4px 4px;
}
.tasksCalendar[view='month'] .wrappers,
.tasksCalendar[view='week'] .grid {
position: relative;
}
.tasksCalendar[view='month'] .wrappers:before,
.tasksCalendar[view='week'] .grid:before,
.tasksCalendar[view='list'] .list:before {
z-index: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 120px;
font-weight: bold;
color: var(--background-modifier-active-hover);
}
.tasksCalendar[view='month'] .wrappers:before,
.tasksCalendar[view='list'] .list:before {
content: attr(data-month);
}
.tasksCalendar[view='week'] .grid:before {
content: attr(data-week);
}
.tasksCalendar[view='month'] .wrapper {
z-index: 1;
display: grid;
grid-template-rows: 1fr !important;
grid-template-columns: 22px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important;
width: 100%;
height: 100%;
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
overflow: hidden;
}
.tasksCalendar[view='month'] .wrapperButton {
display: flex;
writing-mode: vertical-lr;
transform: rotate(180deg);
background: none;
text-align: center;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: normal;
color: var(--text-normal);
color: var(--icon-color-active);
cursor: pointer;
width: 100%;
overflow: hidden;
/* background: var(--background-primary); */
background: var(--background-secondary);
}
.tasksCalendar[view='month'] .wrapperButton:hover {
background: var(--background-modifier-hover);
}
.tasksCalendar[view='month'] .cell {
margin: 0;
}
.tasksCalendar[view='month'] .prevMonth,
.tasksCalendar[view='month'] .nextMonth {
background: var(--background-secondary);
}
/* Week view */
.tasksCalendar[view='week'] .grid {
display: grid;
gap: 2px 4px;
}
.tasksCalendar[view='week'] .cell {
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
overflow: hidden;
}
/* List View */
.tasksCalendar[view='list'] .list {
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
}
.tasksCalendar[view='list'] .list .task,
.tasksCalendar[view='list'] .list .task.done,
.tasksCalendar[view='list'] .list .task .note,
.tasksCalendar[view='list'] .list .task.done .note{
background: transparent !important;
}
.tasksCalendar[view='list'] .list .task .inner {
display: flex !important;
flex-direction: row;
flex-wrap: nowrap;
padding: 0 10px;
white-space: nowrap;
}
.tasksCalendar[view='list'] .list .task .note {
display: inline-block;
width: 150px;
flex-shrink: 0;
flex-grow: 0;
}
.tasksCalendar[view='list'] .list .task .description {
width: 100%;
flex-shrink: 1;
flex-grow: 1;
}
.tasksCalendar[view='list'] .list .task.done .note,
.tasksCalendar[view='list'] .list .task.done .description,
.tasksCalendar[view='list'] .list .task.cancelled .note,
.tasksCalendar[view='list'] .list .task.cancelled .description {
color: var(--text-faint) !important;
}
.tasksCalendar[view='list'] .list .task .note,
.tasksCalendar[view='list'] .list .task .description {
color: var(--task-color) !important;
line-clamp: 0 !important;
white-space: nowrap !important;
text-overflow: ellipsis;
overflow: hidden;
font-size: 14px;
}
.tasksCalendar summary::marker,
.tasksCalendar summary::-webkit-details-marker {
display: none !important;
content: "" !important;
}
.tasksCalendar[view='list'] details.today {
background: var(--background-modifier-active-hover);
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25);
}
.tasksCalendar[view='list'] details.today summary {
font-weight: bold;
background: none;
}
.tasksCalendar[view='list'] details.today .content {
margin: 3px;
}
.tasksCalendar[view='list'] details {
display: block;
margin: 5px;
border-radius: 5px;
overflow: hidden;
/*background: var(--background-secondary);*/
border: 1px solid var(--nav-item-background-active);
}
.tasksCalendar[view='list'] summary {
background: var(--background-secondary);
padding: 0 10px;
border-radius: 5px;
}
.tasksCalendar[view='list'] summary span.weekNr {
font-size: 11px;
color: var(--text-faint);
}
/* Style classes */
.tasksCalendar[view='week'].style1 .grid, .iconStyle1 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(6, 1fr); }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(1), .iconStyle1 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(2), .iconStyle1 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(3), .iconStyle1 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(4), .iconStyle1 .box:nth-child(4) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(5), .iconStyle1 .box:nth-child(5) { grid-area: 3 / 3 / 5 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(6), .iconStyle1 .box:nth-child(6) { grid-area: 5 / 3 / 6 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(7), .iconStyle1 .box:nth-child(7) { grid-area: 6 / 3 / 7 / 5; }
.tasksCalendar[view='week'].style2 .grid, .iconStyle2 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(6, 1fr); }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(1), .iconStyle2 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(3), .iconStyle2 .box:nth-child(3) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(5), .iconStyle2 .box:nth-child(5) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(2), .iconStyle2 .box:nth-child(2) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(4), .iconStyle2 .box:nth-child(4) { grid-area: 3 / 3 / 5 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(6), .iconStyle2 .box:nth-child(6) { grid-area: 5 / 3 / 6 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(7), .iconStyle2 .box:nth-child(7) { grid-area: 6 / 3 / 7 / 5; }
.tasksCalendar[view='week'].style3 .grid, .iconStyle3 { grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; grid-template-columns: 1fr; }
.tasksCalendar[view='week'].style4 .grid, .iconStyle4 { grid-template-rows: 1fr; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; }
.tasksCalendar[view='week'].style5 .grid, .iconStyle5 { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(10, 1fr); }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(1), .iconStyle5 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(2), .iconStyle5 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(3), .iconStyle5 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(4), .iconStyle5 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(5), .iconStyle5 .box:nth-child(5) { grid-area: 9 / 1 / 11 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(6), .iconStyle5 .box:nth-child(6) { grid-area: 1 / 2 / 6 / 3; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(7), .iconStyle5 .box:nth-child(7) { grid-area: 6 / 2 / 11 / 3; }
.tasksCalendar[view='week'].style6 .grid, .iconStyle6 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(10, 1fr); }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(1), .iconStyle6 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(2), .iconStyle6 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(3), .iconStyle6 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(4), .iconStyle6 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(5), .iconStyle6 .box:nth-child(5) { grid-area: 9 / 1 / 11 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(6), .iconStyle6 .box:nth-child(6) { grid-area: 1 / 3 / 6 / 4; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(7), .iconStyle6 .box:nth-child(7) { grid-area: 6 / 3 / 11 / 4; }
.tasksCalendar[view='week'].style7 .grid, .iconStyle7 { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(8, 1fr); }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(1), .iconStyle7 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(2), .iconStyle7 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(3), .iconStyle7 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(4), .iconStyle7 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(5), .iconStyle7 .box:nth-child(5) { grid-area: 1 / 2 / 3 / 3; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(6), .iconStyle7 .box:nth-child(6) { grid-area: 3 / 2 / 6 / 3; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(7), .iconStyle7 .box:nth-child(7) { grid-area: 6 / 2 / 9 / 3; }
.tasksCalendar[view='week'].style8 .grid, .iconStyle8 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(5, 1fr); }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(1), .iconStyle8 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(2), .iconStyle8 .box:nth-child(2) { grid-area: 1 / 2 / 3 / 3; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(3), .iconStyle8 .box:nth-child(3) { grid-area: 1 / 3 / 3 / 4; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(4), .iconStyle8 .box:nth-child(4) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(5), .iconStyle8 .box:nth-child(5) { grid-area: 3 / 2 / 5 / 3; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(6), .iconStyle8 .box:nth-child(6) { grid-area: 3 / 3 / 5 / 4; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(7), .iconStyle8 .box:nth-child(7) { grid-area: 5 / 1 / 6 / 4; }
.tasksCalendar[view='week'].style9 .grid, .iconStyle9 { grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(3, 1fr); }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(1), .iconStyle9 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(2), .iconStyle9 .box:nth-child(2) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(3), .iconStyle9 .box:nth-child(3) { grid-area: 1 / 5 / 3 / 7; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(4), .iconStyle9 .box:nth-child(4) { grid-area: 1 / 7 / 3 / 9; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(5), .iconStyle9 .box:nth-child(5) { grid-area: 1 / 9 / 3 / 11; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(6), .iconStyle9 .box:nth-child(6) { grid-area: 3 / 1 / 4 / 6; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(7), .iconStyle9 .box:nth-child(7) { grid-area: 3 / 6 / 4 / 11; }
.tasksCalendar[view='week'].style10 .grid, .iconStyle10 { grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(3, 1fr); }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(1), .iconStyle10 .box:nth-child(1) { grid-area: 1 / 1 / 4 / 3; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(2), .iconStyle10 .box:nth-child(2) { grid-area: 1 / 3 / 4 / 5; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(3), .iconStyle10 .box:nth-child(3) { grid-area: 1 / 5 / 4 / 7; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(4), .iconStyle10 .box:nth-child(4) { grid-area: 1 / 7 / 3 / 9; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(5), .iconStyle10 .box:nth-child(5) { grid-area: 1 / 9 / 3 / 11; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(6), .iconStyle10 .box:nth-child(6) { grid-area: 3 / 7 / 4 / 9; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(7), .iconStyle10 .box:nth-child(7) { grid-area: 3 / 9 / 4 / 11; }
.tasksCalendar[view='week'].style11 .grid, .iconStyle11 { grid-template-rows: 1fr; grid-template-columns: 1fr 1fr 1fr 1fr 1fr; }
.tasksCalendar[view='week'].style11 .grid { height: 300px }
.tasksCalendar[view='week'].style11 .cell[data-weekday="0"], .iconStyle11 { display: none !important }
.tasksCalendar[view='week'].style11 .cell[data-weekday="6"], .iconStyle11 { display: none !important }
/* Options classes */
.tasksCalendar.noIcons .task .icon { display: none !important; }
.tasksCalendar:not(.noFilename) .task.noNoteIcon .icon { display: none !important; }
.tasksCalendar.noFilename .task .note { display: none !important; }
.tasksCalendar.filter .task.done, .tasksCalendar.filter .task.cancelled { display: none !important; }
.tasksCalendar.filter #statisticDone { pointer-events: none !important; color: var(--text-faint) !important; }
.tasksCalendar.noScheduled .task.scheduled { display: none !important; }
.tasksCalendar.noStart .task.start { display: none !important; }
.tasksCalendar.noDue .task.due { display: none !important; }
.tasksCalendar.noDone .task.done { display: none !important; }
.tasksCalendar.noProcess .task.process { display: none !important; }
.tasksCalendar.noRecurrence .task.recurrence { display: none !important; }
.tasksCalendar.noOverdue .task.overdue { display: none !important; }
.tasksCalendar.noDailyNote .task.dailyNote { display: none !important; }
.tasksCalendar.noCellNameEvent .cellName { pointer-events: none !important; }
.tasksCalendar.noLayer .grid .wrappers:before,
.tasksCalendar.noLayer .grid:before,
.tasksCalendar.noLayer .list:before { display: none !important;}
.tasksCalendar.focusDone .task { opacity: 0.25 !important; }
.tasksCalendar.focusDone .task.done { opacity: 1 !important; }
.tasksCalendar.focusDue .task { opacity: 0.25 !important; }
.tasksCalendar.focusDue .task.due { opacity: 1 !important; }
.tasksCalendar.focusOverdue .task { opacity: 0.25 !important; }
.tasksCalendar.focusOverdue .task.overdue { opacity: 1 !important; }
.tasksCalendar.focusStart .task { opacity: 0.25 !important; }
.tasksCalendar.focusStart .task.start { opacity: 1 !important; }
.tasksCalendar.focusScheduled .task { opacity: 0.25 !important; }
.tasksCalendar.focusScheduled .task.scheduled { opacity: 1 !important; }
.tasksCalendar.focusRecurrence .task { opacity: 0.25 !important; }
.tasksCalendar.focusRecurrence .task.recurrence { opacity: 1 !important; }
.tasksCalendar.focusDailyNote .task { opacity: 0.25 !important; }
.tasksCalendar.focusDailyNote .task.dailyNote { opacity: 1 !important; }
.tasksCalendar.mini { max-width: 500px !important; margin: 0 auto; }
.tasksCalendar.mini .grid { height: 400px !important; }
.tasksCalendar.mini .gridHead,
.tasksCalendar.mini .cellName,
.tasksCalendar.mini .task,
.tasksCalendar.mini .wrapperButton { font-size: 9px !important; }
.tasksCalendar.mini .wrappers:before,
.tasksCalendar.mini .grid:before { font-size: 70px !important; }
.tasksCalendar.mini .statisticPopup li,
.tasksCalendar.mini .weekViewContext li { font-size: 9px !important; }
.tasksCalendar.noWeekNr .wrapperButton { visibility: hidden !important; width: 0 !important; }
.tasksCalendar.noWeekNr .gridHead:first-child { visibility: hidden !important; width: 0 !important; }
.tasksCalendar.noWeekNr .wrapper { grid-template-columns: 0px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important; }
.tasksCalendar.noWeekNr .gridHeads { grid-template-columns: 0px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important; }
.tasksCalendar.noWeekNr .list .weekNr { display: none !important; }
.tasksCalendar.lineClamp1 .task .inner { -webkit-line-clamp: 1 !important; white-space: nowrap !important; }
.tasksCalendar.lineClamp2 .task .inner { -webkit-line-clamp: 2 !important; }
.tasksCalendar.lineClamp3 .task .inner { -webkit-line-clamp: 3 !important; }
.tasksCalendar.noLineClamp .task .inner { display: block !important; }
.tasksCalendar.noOverdueFlag .task .description:before { display: none !important; }
/* Mobile View */
body.is-mobile .tasksCalendar .gridHead, body.is-mobile .tasksCalendar .cellName, body.is-mobile .tasksCalendar .task { font-size: 9px; }
body.is-mobile .tasksCalendar[view='week']:not(.style4) .cellName,
body.is-mobile .tasksCalendar[view='week']:not(.style4) .task { font-size: 13px !important; }
body.is-mobile .tasksCalendar .statisticPopup li { font-size: 13px !important; }

View File

@@ -1,702 +0,0 @@
let {pages, view, firstDayOfWeek, globalTaskFilter, dailyNoteFolder, dailyNoteFormat, startPosition, upcomingDays, css, options} = input;
// Error Handling
if (!pages && pages!="") { dv.span('> [!ERROR] Missing pages parameter\n> \n> Please set the pages parameter like\n> \n> `pages: ""`'); return false };
if (!options.includes("style")) { dv.span('> [!ERROR] Missing style parameter\n> \n> Please set a style inside options parameter like\n> \n> `options: "style1"`'); return false };
if (!view) { dv.span('> [!ERROR] Missing view parameter\n> \n> Please set a default view inside view parameter like\n> \n> `view: "month"`'); return false };
if (firstDayOfWeek) {
if (firstDayOfWeek.match(/[|\\0123456]/g) == null) {
dv.span('> [!ERROR] Wrong value inside firstDayOfWeek parameter\n> \n> Please choose a number between 0 and 6');
return false
};
} else {
dv.span('> [!ERROR] Missing firstDayOfWeek parameter\n> \n> Please set the first day of the week inside firstDayOfWeek parameter like\n> \n> `firstDayOfWeek: "1"`');
return false
};
if (startPosition) { if (!startPosition.match(/\d{4}\-\d{1,2}/gm)) { dv.span('> [!ERROR] Wrong startPosition format\n> \n> Please set a startPosition with the following format\n> \n> Month: `YYYY-MM` | Week: `YYYY-ww`'); return false }};
if (dailyNoteFormat) { if (dailyNoteFormat.match(/[|\\YMDWwd.,-: \[\]]/g).length != dailyNoteFormat.length) { dv.span('> [!ERROR] The `dailyNoteFormat` contains invalid characters'); return false }};
// Get, Set, Eval Pages
if (pages == "") {
var tasks = dv.pages().file.tasks;
} else if (typeof pages === "string" && pages.startsWith("dv.pages")) {
var tasks = eval(pages);
} else if (typeof pages && pages.every(p => p.task)) {
var tasks = pages;
} else {
var tasks = dv.pages(pages).file.tasks;
}
// Variables
var done, doneWithoutCompletionDate, due, recurrence, overdue, start, scheduled, process, cancelled, dailyNote, dailyNoteRegEx;
if (!dailyNoteFormat) { dailyNoteFormat = "YYYY-MM-DD" };
var dailyNoteRegEx = momentToRegex(dailyNoteFormat)
var tToday = moment().format("YYYY-MM-DD");
var tMonth = moment().format("M");
var tDay = moment().format("d");
var tYear = moment().format("YYYY");
var tid = (new Date()).getTime();
if (startPosition) { var selectedMonth = moment(startPosition, "YYYY-MM").date(1); var selectedList = moment(startPosition, "YYYY-MM").date(1); var selectedWeek = moment(startPosition, "YYYY-ww").startOf("week") } else { var selectedMonth = moment(startPosition).date(1); var selectedWeek = moment(startPosition).startOf("week"); var selectedList = moment(startPosition).date(1); };
var selectedDate = eval("selected"+capitalize(view));
var arrowLeftIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>';
var arrowRightIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>';
var filterIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg>';
var monthIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="M8 14h.01"></path><path d="M12 14h.01"></path><path d="M16 14h.01"></path><path d="M8 18h.01"></path><path d="M12 18h.01"></path><path d="M16 18h.01"></path></svg>';
var weekIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="M17 14h-6"></path><path d="M13 18H7"></path><path d="M7 14h.01"></path><path d="M17 18h.01"></path></svg>';
var listIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>';
var calendarClockIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"></path><path d="M16 2v4"></path><path d="M8 2v4"></path><path d="M3 10h5"></path><path d="M17.5 17.5 16 16.25V14"></path><path d="M22 16a6 6 0 1 1-12 0 6 6 0 0 1 12 0Z"></path></svg>';
var calendarCheckIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="m9 16 2 2 4-4"></path></svg>';
var calendarHeartIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h7"></path><path d="M16 2v4"></path><path d="M8 2v4"></path><path d="M3 10h18"></path><path d="M21.29 14.7a2.43 2.43 0 0 0-2.65-.52c-.3.12-.57.3-.8.53l-.34.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L17.5 22l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"></path></svg>';
var cellTemplate = "<div class='cell {{class}}' data-weekday='{{weekday}}'><a class='internal-link cellName' href='{{dailyNote}}'>{{cellName}}</a><div class='cellContent'>{{cellContent}}</div></div>";
var taskTemplate = "<a class='internal-link' href='{{taskPath}}'><div class='task {{class}}' style='{{style}}' title='{{title}}'><div class='inner'><div class='note'>{{note}}</div><div class='icon'>{{icon}}</div><div class='description' data-relative='{{relative}}'>{{taskContent}}</div></div></div></a>";
const rootNode = dv.el("div", "", {cls: "tasksCalendar "+options, attr: {id: "tasksCalendar"+tid, view: view, style: 'position:relative;-webkit-user-select:none!important'}});
if (css) { var style = document.createElement("style"); style.innerHTML = css; rootNode.append(style) };
var taskDoneIcon = "✅";
var taskDueIcon = "📅";
var taskScheduledIcon = "⏳";
var taskRecurrenceIcon = "🔁";
var taskOverdueIcon = "⚠️";
var taskProcessIcon = "⏺️";
var taskCancelledIcon = "🚫";
var taskStartIcon = "🛫";
var taskDailyNoteIcon = "📄";
// Initialze
getMeta(tasks);
setButtons();
setStatisticPopUp();
setWeekViewContext();
eval("get"+capitalize(view))(tasks, selectedDate);
function getMeta(tasks) {
for (i=0;i<tasks.length;i++) {
var taskText = tasks[i].text;
var taskFile = getFilename(tasks[i].path);
var dailyNoteMatch = taskFile.match(eval(dailyNoteRegEx));
var dailyTaskMatch = taskText.match(/(\d{4}\-\d{2}\-\d{2})/);
if (dailyNoteMatch) {
if(!dailyTaskMatch) {
tasks[i].dailyNote = moment(dailyNoteMatch[1], dailyNoteFormat).format("YYYY-MM-DD")
};
};
var dueMatch = taskText.match(/\📅\W(\d{4}\-\d{2}\-\d{2})/);
if (dueMatch) {
tasks[i].due = dueMatch[1];
tasks[i].text = tasks[i].text.replace(dueMatch[0], "");
};
var startMatch = taskText.match(/\🛫\W(\d{4}\-\d{2}\-\d{2})/);
if (startMatch) {
tasks[i].start = startMatch[1];
tasks[i].text = tasks[i].text.replace(startMatch[0], "");
};
var scheduledMatch = taskText.match(/\⏳\W(\d{4}\-\d{2}\-\d{2})/);
if (scheduledMatch) {
tasks[i].scheduled = scheduledMatch[1];
tasks[i].text = tasks[i].text.replace(scheduledMatch[0], "");
};
var completionMatch = taskText.match(/\✅\W(\d{4}\-\d{2}\-\d{2})/);
if (completionMatch) {
tasks[i].completion = completionMatch[1];
tasks[i].text = tasks[i].text.replace(completionMatch[0], "");
};
var repeatMatch = taskText.includes("🔁");
if (repeatMatch) {
tasks[i].recurrence = true;
tasks[i].text = tasks[i].text.substring(0, taskText.indexOf("🔁"))
};
var lowMatch = taskText.includes("🔽");
if (lowMatch) {
tasks[i].priority = "D";
};
var mediumMatch = taskText.includes("🔼");
if (mediumMatch) {
tasks[i].priority = "B";
};
var highMatch = taskText.includes("⏫");
if (highMatch) {
tasks[i].priority = "A";
};
if (!lowMatch && !mediumMatch && !highMatch) {
tasks[i].priority = "C";
}
if (globalTaskFilter) {
tasks[i].text = tasks[i].text.replaceAll(globalTaskFilter,"");
} else {
tasks[i].text = tasks[i].text.replaceAll("#task","");
};
tasks[i].text = tasks[i].text.replaceAll("[[","");
tasks[i].text = tasks[i].text.replaceAll("]]","");
tasks[i].text = tasks[i].text.replace(/\[.*?\]/gm,"");
};
};
function getFilename(path) {
var filename = path.match(/^(?:.*\/)?([^\/]+?|)(?=(?:\.[^\/.]*)?$)/)[1];
return filename;
};
function capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
};
function getMetaFromNote(task, metaName) {
var meta = dv.pages('"'+task.link.path+'"')[metaName][0];
if (meta) { return meta } else { return "" };
}
function transColor(color, percent) {
var num = parseInt(color.replace("#",""),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, B = (num >> 8 & 0x00FF) + amt, G = (num & 0x0000FF) + amt;
return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (B<255?B<1?0:B:255)*0x100 + (G<255?G<1?0:G:255)).toString(16).slice(1);
};
function momentToRegex(momentFormat) {
momentFormat = momentFormat.replaceAll(".", "\\.");
momentFormat = momentFormat.replaceAll(",", "\\,");
momentFormat = momentFormat.replaceAll("-", "\\-");
momentFormat = momentFormat.replaceAll(":", "\\:");
momentFormat = momentFormat.replaceAll(" ", "\\s");
momentFormat = momentFormat.replace("dddd", "\\w{1,}");
momentFormat = momentFormat.replace("ddd", "\\w{1,3}");
momentFormat = momentFormat.replace("dd", "\\w{2}");
momentFormat = momentFormat.replace("d", "\\d{1}");
momentFormat = momentFormat.replace("YYYY", "\\d{4}");
momentFormat = momentFormat.replace("YY", "\\d{2}");
momentFormat = momentFormat.replace("MMMM", "\\w{1,}");
momentFormat = momentFormat.replace("MMM", "\\w{3}");
momentFormat = momentFormat.replace("MM", "\\d{2}");
momentFormat = momentFormat.replace("DDDD", "\\d{3}");
momentFormat = momentFormat.replace("DDD", "\\d{1,3}");
momentFormat = momentFormat.replace("DD", "\\d{2}");
momentFormat = momentFormat.replace("D", "\\d{1,2}");
momentFormat = momentFormat.replace("ww", "\\d{1,2}");
regEx = "/^(" + momentFormat + ")$/";
return regEx;
};
function getTasks(date) {
done = tasks.filter(t=>t.completed && t.checked && t.completion && moment(t.completion.toString()).isSame(date)).sort(t=>t.completion);
doneWithoutCompletionDate = tasks.filter(t=>t.completed && t.checked && !t.completion && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
done = done.concat(doneWithoutCompletionDate);
due = tasks.filter(t=>!t.completed && !t.checked && !t.recurrence && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
recurrence = tasks.filter(t=>!t.completed && !t.checked && t.recurrence && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
overdue = tasks.filter(t=>!t.completed && !t.checked && t.due && moment(t.due.toString()).isBefore(date)).sort(t=>t.due);
start = tasks.filter(t=>!t.completed && !t.checked && t.start && moment(t.start.toString()).isSame(date)).sort(t=>t.start);
scheduled = tasks.filter(t=>!t.completed && !t.checked && t.scheduled && moment(t.scheduled.toString()).isSame(date)).sort(t=>t.scheduled);
process = tasks.filter(t=>!t.completed && !t.checked && t.due && t.start && moment(t.due.toString()).isAfter(date) && moment(t.start.toString()).isBefore(date) );
cancelled = tasks.filter(t=>!t.completed && t.checked && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
dailyNote = tasks.filter(t=>!t.completed && !t.checked && t.dailyNote && moment(t.dailyNote.toString()).isSame(date)).sort(t=>t.dailyNote);
};
function setTask(obj, cls) {
var lighter = 25;
var darker = -40;
var noteColor = getMetaFromNote(obj, "color");
var textColor = getMetaFromNote(obj, "textColor");
var noteIcon = getMetaFromNote(obj, "icon");
var taskText = obj.text.replace("'", "&apos;");
var taskPath = obj.link.path.replace("'", "&apos;");
var taskIcon = eval("task"+capitalize(cls)+"Icon");
if (obj.due) { var relative = moment(obj.due).fromNow() } else { var relative = "" };
var noteFilename = getFilename(taskPath);
if (noteIcon) { noteFilename = noteIcon+"&nbsp;"+noteFilename } else { noteFilename = taskIcon+"&nbsp;"+noteFilename; cls += " noNoteIcon" };
var taskSubpath = obj.header.subpath;
var taskLine = taskSubpath ? taskPath+"#"+taskSubpath : taskPath;
if (noteColor && textColor) {
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+textColor+";--light-task-text-color:"+textColor;
} else if (noteColor && !textColor){
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+transColor(noteColor, darker)+";--light-task-text-color:"+transColor(noteColor, lighter);
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+transColor(noteColor, darker)+";--light-task-text-color:"+transColor(noteColor, lighter);
} else if (!noteColor && textColor ){
var style = "--task-background:#7D7D7D33;--task-color:#7D7D7D;--dark-task-text-color:"+transColor(textColor, darker)+";--light-task-text-color:"+transColor(textColor, lighter);
} else {
var style = "--task-background:#7D7D7D33;--task-color:#7D7D7D;--dark-task-text-color:"+transColor("#7D7D7D", darker)+";--light-task-text-color:"+transColor("#7D7D7D", lighter);
};
var newTask = taskTemplate.replace("{{taskContent}}", taskText).replace("{{class}}", cls).replace("{{taskPath}}", taskLine).replace("{{due}}","done").replaceAll("{{style}}",style).replace("{{title}}", noteFilename + ": " + taskText).replace("{{note}}",noteFilename).replace("{{icon}}",taskIcon).replace("{{relative}}",relative);
return newTask;
};
function setTaskContentContainer(currentDate) {
var cellContent = "";
function compareFn(a, b) {
if (a.priority.toUpperCase() < b.priority.toUpperCase()) {
return -1;
};
if (a.priority.toUpperCase() > b.priority.toUpperCase()) {
return 1;
};
if (a.priority == b.priority) {
if (a.text.toUpperCase() < b.text.toUpperCase()) {
return -1;
};
if (a.text.toUpperCase() > b.text.toUpperCase()) {
return 1;
};
return 0;
};
};
function showTasks(tasksToShow, type) {
const sorted = [...tasksToShow].sort(compareFn);
for (var t = 0; t < sorted.length; t++) {
cellContent += setTask(sorted[t], type)
};
};
if (tToday == currentDate) {
showTasks(overdue, "overdue");
};
showTasks(due, "due");
showTasks(recurrence, "recurrence");
showTasks(start, "start");
showTasks(scheduled, "scheduled");
showTasks(process, "process");
showTasks(dailyNote, "dailyNote");
showTasks(done, "done");
showTasks(cancelled, "cancelled");
return cellContent;
};
function setButtons() {
var buttons = "<button class='filter'>"+filterIcon+"</button><button class='listView' title='List'>"+listIcon+"</button><button class='monthView' title='Month'>"+monthIcon+"</button><button class='weekView' title='Week'>"+weekIcon+"</button><button class='current'></button><button class='previous'>"+arrowLeftIcon+"</button><button class='next'>"+arrowRightIcon+"</button><button class='statistic' percentage=''></button>";
rootNode.querySelector("span").appendChild(dv.el("div", buttons, {cls: "buttons", attr: {}}));
setButtonEvents();
};
function setButtonEvents() {
rootNode.querySelectorAll('button').forEach(btn => btn.addEventListener('click', (() => {
var activeView = rootNode.getAttribute("view");
if ( btn.className == "previous" ) {
if (activeView == "month") {
selectedDate = moment(selectedDate).subtract(1, "months");
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment(selectedDate).subtract(7, "days").startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment(selectedDate).subtract(1, "months");
getList(tasks, selectedDate);
}
} else if ( btn.className == "current") {
if (activeView == "month") {
selectedDate = moment().date(1);
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment().startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment().date(1);
getList(tasks, selectedDate);
};
} else if ( btn.className == "next" ) {
if (activeView == "month") {
selectedDate = moment(selectedDate).add(1, "months");
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment(selectedDate).add(7, "days").startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment(selectedDate).add(1, "months");
getList(tasks, selectedDate);
};
} else if ( btn.className == "filter" ) {
rootNode.classList.toggle("filter");
rootNode.querySelector('#statisticDone').classList.remove("active");
rootNode.classList.remove("focusDone");
} else if ( btn.className == "monthView" ) {
if ( moment().format("ww-YYYY") == moment(selectedDate).format("ww-YYYY") ) {
selectedDate = moment().date(1);
} else {
selectedDate = moment(selectedDate).date(1);
};
getMonth(tasks, selectedDate);
} else if ( btn.className == "listView" ) {
if ( moment().format("ww-YYYY") == moment(selectedDate).format("ww-YYYY") ) {
selectedDate = moment().date(1);
} else {
selectedDate = moment(selectedDate).date(1);
};
getList(tasks, selectedDate);
} else if ( btn.className == "weekView" ) {
if (rootNode.getAttribute("view") == "week") {
var leftPos = rootNode.querySelector("button.weekView").offsetLeft;
rootNode.querySelector(".weekViewContext").style.left = leftPos+"px";
rootNode.querySelector(".weekViewContext").classList.toggle("active");
if (rootNode.querySelector(".weekViewContext").classList.contains("active")) {
var closeContextListener = function() {
rootNode.querySelector(".weekViewContext").classList.remove("active");
rootNode.removeEventListener("click", closeContextListener, false);
};
setTimeout(function() {
rootNode.addEventListener("click", closeContextListener, false);
}, 100);
};
} else {
if (moment().format("MM-YYYY") != moment(selectedDate).format("MM-YYYY")) {
selectedDate = moment(selectedDate).startOf("month").startOf("week");
} else {
selectedDate = moment().startOf("week");
};
getWeek(tasks, selectedDate);
};
} else if ( btn.className == "statistic" ) {
rootNode.querySelector(".statisticPopup").classList.toggle("active");
};
btn.blur();
})));
rootNode.addEventListener('contextmenu', function(event) {
event.preventDefault();
});
};
function setWrapperEvents() {
rootNode.querySelectorAll('.wrapperButton').forEach(wBtn => wBtn.addEventListener('click', (() => {
var week = wBtn.getAttribute("data-week");
var year = wBtn.getAttribute("data-year");
selectedDate = moment(moment(year).add(week, "weeks")).startOf("week");
rootNode.querySelector(`#tasksCalendar${tid} .grid`).remove();
getWeek(tasks, selectedDate);
})));
};
function setStatisticPopUpEvents() {
rootNode.querySelectorAll('.statisticPopup li').forEach(li => li.addEventListener('click', (() => {
var group = li.getAttribute("data-group");
const liElements = rootNode.querySelectorAll('.statisticPopup li');
if (li.classList.contains("active")) {
const liElements = rootNode.querySelectorAll('.statisticPopup li');
for (const liElement of liElements) {
liElement.classList.remove('active');
};
rootNode.classList.remove("focus"+capitalize(group));
} else {
for (const liElement of liElements) {
liElement.classList.remove('active');
};
li.classList.add("active");
rootNode.classList.remove.apply(rootNode.classList, Array.from(rootNode.classList).filter(v=>v.startsWith("focus")));
rootNode.classList.add("focus"+capitalize(group));
};
})));
};
function setStatisticPopUp() {
var statistic = "<li id='statisticDone' data-group='done'></li>";
statistic += "<li id='statisticDue' data-group='due'></li>";
statistic += "<li id='statisticOverdue' data-group='overdue'></li>";
statistic += "<li class='break'></li>";
statistic += "<li id='statisticStart' data-group='start'></li>";
statistic += "<li id='statisticScheduled' data-group='scheduled'></li>";
statistic += "<li id='statisticRecurrence' data-group='recurrence'></li>";
statistic += "<li class='break'></li>";
statistic += "<li id='statisticDailyNote' data-group='dailyNote'></li>";
rootNode.querySelector("span").appendChild(dv.el("ul", statistic, {cls: "statisticPopup"}));
setStatisticPopUpEvents();
};
function setWeekViewContextEvents() {
rootNode.querySelectorAll('.weekViewContext li').forEach(li => li.addEventListener('click', (() => {
var selectedStyle = li.getAttribute("data-style");
const liElements = rootNode.querySelectorAll('.weekViewContext li');
if (!li.classList.contains("active")) {
for (const liElement of liElements) {
liElement.classList.remove('active');
};
li.classList.add("active");
rootNode.classList.remove.apply(rootNode.classList, Array.from(rootNode.classList).filter(v=>v.startsWith("style")));
rootNode.classList.add(selectedStyle);
};
rootNode.querySelector(".weekViewContext").classList.toggle("active");
})));
};
function setWeekViewContext() {
var activeStyle = Array.from(rootNode.classList).filter(v=>v.startsWith("style"));
var liElements = "";
var styles = 11;
for (i=1;i<styles+1;i++) {
var liIcon = "<div class='liIcon iconStyle"+i+"'><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div></div>";
liElements += "<li data-style='style"+i+"'>"+liIcon+"Style "+i+"</li>";
};
rootNode.querySelector("span").appendChild(dv.el("ul", liElements, {cls: "weekViewContext"}));
rootNode.querySelector(".weekViewContext li[data-style="+activeStyle+"]").classList.add("active");
setWeekViewContextEvents();
};
function setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter) {
var taskCounter = parseInt(dueCounter+doneCounter+overdueCounter);
var tasksRemaining = taskCounter - doneCounter;
var percentage = Math.round(100/(dueCounter+doneCounter+overdueCounter)*doneCounter);
percentage = isNaN(percentage) ? 100 : percentage;
if (dueCounter == 0 && doneCounter == 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarHeartIcon;
} else if (tasksRemaining > 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarClockIcon;
} else if (dueCounter == 0 && doneCounter != 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarCheckIcon;
};
if (tasksRemaining > 99) {tasksRemaining = "⚠️"};
rootNode.querySelector("button.statistic").setAttribute("data-percentage", percentage);
rootNode.querySelector("button.statistic").setAttribute("data-remaining", tasksRemaining);
rootNode.querySelector("#statisticDone").innerText = "✅ Done: " + doneCounter + "/" + taskCounter;
rootNode.querySelector("#statisticDue").innerText = "📅 Due: " + dueCounter;
rootNode.querySelector("#statisticOverdue").innerText = "⚠️ Overdue: " + overdueCounter;
rootNode.querySelector("#statisticStart").innerText = "🛫 Start: " + startCounter;
rootNode.querySelector("#statisticScheduled").innerText = "⏳ Scheduled: " + scheduledCounter;
rootNode.querySelector("#statisticRecurrence").innerText = "🔁 Recurrence: " + recurrenceCounter;
rootNode.querySelector("#statisticDailyNote").innerText = "📄 Daily Notes: " + dailyNoteCounter;
};
function removeExistingView() {
if (rootNode.querySelector(`#tasksCalendar${tid} .grid`)) {
rootNode.querySelector(`#tasksCalendar${tid} .grid`).remove();
} else if (rootNode.querySelector(`#tasksCalendar${tid} .list`)) {
rootNode.querySelector(`#tasksCalendar${tid} .list`).remove();
};
};
function getMonth(tasks, month) {
removeExistingView();
var currentTitle = "<span>"+moment(month).format("MMMM")+"</span><span> "+moment(month).format("YYYY")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle;
var gridContent = "";
var firstDayOfMonth = moment(month).format("d");
var firstDateOfMonth = moment(month).startOf("month").format("D");
var lastDateOfMonth = moment(month).endOf("month").format("D");
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
// Move First Week Of Month To Second Week In Month View
if (firstDayOfMonth == 0) { firstDayOfMonth = 7};
// Set Grid Heads
var gridHeads = "";
for (h=0-firstDayOfMonth+parseInt(firstDayOfWeek);h<7-firstDayOfMonth+parseInt(firstDayOfWeek);h++) {
var weekDayNr = moment(month).add(h, "days").format("d");
var weekDayName = moment(month).add(h, "days").format("ddd");
if ( tDay == weekDayNr && tMonth == moment(month).format("M") && tYear == moment(month).format("YYYY") ) {
gridHeads += "<div class='gridHead today' data-weekday='" + weekDayNr + "'>" + weekDayName + "</div>";
} else {
gridHeads += "<div class='gridHead' data-weekday='" + weekDayNr + "'>" + weekDayName + "</div>";
};
};
// Set Wrappers
var wrappers = "";
var starts = 0-firstDayOfMonth+parseInt(firstDayOfWeek);
for (w=1; w<7; w++) {
var wrapper = "";
var weekNr = "";
var yearNr = "";
var monthName = moment(month).format("MMM").replace(".","").substring(0,3);
for (i=starts;i<starts+7;i++) {
if (i==starts) {
weekNr = moment(month).add(i, "days").format("w");
yearNr = moment(month).add(i, "days").format("YYYY");
};
var currentDate = moment(month).add(i, "days").format("YYYY-MM-DD");
var currentDate1 = moment(month).add(i, "days").format("YYYY-MM-DD(ddd)");
if (!dailyNoteFolder) {var dailyNotePath = currentDate1} else {var dailyNotePath = dailyNoteFolder+"/"+currentDate1};
var weekDay = moment(month).add(i, "days").format("d");
var shortDayName = moment(month).add(i, "days").format("D");
var longDayName = moment(month).add(i, "days").format("D. MMM");
var shortWeekday = moment(month).add(i, "days").format("ddd");
// Filter Tasks
getTasks(currentDate);
// Count Events Only From Selected Month
if (moment(month).format("MM") == moment(month).add(i, "days").format("MM")) {
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
// Get Overdue Count From Today
if (moment().format("YYYY-MM-DD") == moment(month).add(i, "days").format("YYYY-MM-DD")) {
overdueCounter = overdue.length;
};
};
// Set New Content Container
var cellContent = setTaskContentContainer(currentDate);
// Set Cell Name And Weekday
if ( moment(month).add(i, "days").format("D") == 1 ) {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
cell = cell.replace("{{class}}", "{{class}} newMonth");
} else {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", shortDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
};
// Set prevMonth, currentMonth, nextMonth
if (i < 0) {
cell = cell.replace("{{class}}", "prevMonth");
} else if (i >= 0 && i < lastDateOfMonth && tToday !== currentDate) {
cell = cell.replace("{{class}}", "currentMonth");
} else if ( i >= 0 && i< lastDateOfMonth && tToday == currentDate) {
cell = cell.replace("{{class}}", "currentMonth today");
} else if (i >= lastDateOfMonth) {
cell = cell.replace("{{class}}", "nextMonth");
};
wrapper += cell;
};
wrappers += "<div class='wrapper'><div class='wrapperButton' data-week='"+weekNr+"' data-year='"+yearNr+"'>W"+weekNr+"</div>"+wrapper+"</div>";
starts += 7;
};
gridContent += "<div class='gridHeads'><div class='gridHead'></div>"+gridHeads+"</div>";
gridContent += "<div class='wrappers' data-month='"+monthName+"'>"+wrappers+"</div>";
rootNode.querySelector("span").appendChild(dv.el("div", gridContent, {cls: "grid"}));
setWrapperEvents();
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "month");
};
function getWeek(tasks, week) {
removeExistingView();
var currentTitle = "<span>"+moment(week).format("YYYY")+"</span><span> "+moment(week).format("[W]w")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle
var gridContent = "";
var currentWeekday = moment(week).format("d");
var weekNr = moment(week).format("[W]w");
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
for (i=0-currentWeekday+parseInt(firstDayOfWeek);i<7-currentWeekday+parseInt(firstDayOfWeek);i++) {
var currentDate = moment(week).add(i, "days").format("YYYY-MM-DD");
if (!dailyNoteFolder) {var dailyNotePath = currentDate} else {var dailyNotePath = dailyNoteFolder+"/"+currentDate};
var weekDay = moment(week).add(i, "days").format("d");
var dayName = moment(currentDate).format("ddd D.");
var longDayName = moment(currentDate).format("ddd, D. MMM");
// Filter Tasks
getTasks(currentDate);
// Count Events From Selected Week
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
if (moment().format("YYYY-MM-DD") == moment(week).add(i, "days").format("YYYY-MM-DD")) {
overdueCounter = overdue.length;
};
// Set New Content Container
var cellContent = setTaskContentContainer(currentDate);
// Set Cell Name And Weekday
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
// Set Cell Name And Weekday
if ( moment(week).add(i, "days").format("D") == 1 ) {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
} else {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", dayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
};
// Set Today, Before Today, After Today
if (currentDate < tToday) {
cell = cell.replace("{{class}}", "beforeToday");
} else if (currentDate == tToday) {
cell = cell.replace("{{class}}", "today");
} else if (currentDate > tToday) {
cell = cell.replace("{{class}}", "afterToday");
};
gridContent += cell;
};
rootNode.querySelector("span").appendChild(dv.el("div", gridContent, {cls: "grid", attr:{'data-week': weekNr}}));
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "week");
};
function getList(tasks, month) {
removeExistingView();
var currentTitle = "<span>"+moment(month).format("MMMM")+"</span><span> "+moment(month).format("YYYY")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle;
var listContent = "";
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
// Loop Days From Current Month
for (i=0;i<moment(month).endOf('month').format("D");i++) {
var currentDate = moment(month).startOf('month').add(i, "days").format("YYYY-MM-DD");
var monthName = moment(month).format("MMM").replace(".","").substring(0,3);
// Filter Tasks
getTasks(currentDate);
// Count Events
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
if (moment().format("YYYY-MM-DD") == currentDate) {
overdueCounter = overdue.length;
var overdueDetails = "<details open class='overdue'><summary>Overdue</summary>" + setTaskContentContainer(currentDate) + "</details>";
var todayDetails = "<details open class='today'><summary>Today</summary>" + setTaskContentContainer(currentDate) + "</details>";
// Upcoming
if (!upcomingDays) { upcomingDays = "7" };
var upcomingContent = "";
for (t=1;t<parseInt(upcomingDays)+1;t++) {
var next = moment(currentDate).add(t, "days").format("YYYY-MM-DD");
getTasks(next);
upcomingContent += setTaskContentContainer(next);
};
var upcomingDetails = "<details open class='upcoming'><summary>Upcoming</summary>" + upcomingContent + "</details>";
listContent += "<details open class='today'><summary><span>" + moment(currentDate).format("dddd, D") + "</span><span class='weekNr'> " + moment(currentDate).format("[W]w") + "</span></summary><div class='content'>" + overdueDetails + todayDetails + upcomingDetails + "</div></details>"
} else {
listContent += "<details open><summary><span>" + moment(currentDate).format("dddd, D") + "</span><span class='weekNr'> " + moment(currentDate).format("[W]w") + "</span></summary><div class='content'>" + setTaskContentContainer(currentDate) + "</div></details>"
};
};
rootNode.querySelector("span").appendChild(dv.el("div", listContent, {cls: "list", attr:{"data-month": monthName}}));
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "list");
// Scroll To Today If Selected Month Is Current Month
if ( moment().format("YYYY-MM") == moment(month).format("YYYY-MM") ) {
var listElement = rootNode.querySelector(".list");
var todayElement = rootNode.querySelector(".today")
var scrollPos = todayElement.offsetTop - todayElement.offsetHeight + 85;
listElement.scrollTo(0, scrollPos);
};
};

View File

@@ -1,722 +0,0 @@
.tasksCalendar span {
display: contents;
}
.tasksCalendar .buttons {
cursor: default;
width: 100%;
height: 30px;
display: flex;
flex-wrap: nowrap;
flex-direction: row;
margin-bottom: 4px;
}
.tasksCalendar[view='list'] button.listView,
.tasksCalendar[view='week'] button.weekView,
.tasksCalendar[view='month'] button.monthView,
.tasksCalendar.filter button.filter {
background: var(--background-modifier-active-hover);
}
body:not(.is-mobile) .tasksCalendar button.listView:hover,
body:not(.is-mobile) .tasksCalendar button.weekView:hover,
body:not(.is-mobile) .tasksCalendar button.monthView:hover,
body:not(.is-mobile) .tasksCalendar button.previous:hover,
body:not(.is-mobile) .tasksCalendar button.next:hover,
body:not(.is-mobile) .tasksCalendar button.current:hover,
body:not(.is-mobile) .tasksCalendar button.filter:hover,
body:not(.is-mobile) .tasksCalendar button.statistic:hover {
background: var(--background-modifier-hover);
}
.tasksCalendar[view='list'] button.listView svg,
.tasksCalendar[view='month'] button.monthView svg,
.tasksCalendar[view='week'] button.weekView svg,
.tasksCalendar.filter button.filter svg {
stroke: var(--icon-color-active) !important;
}
.tasksCalendar button {
background-color: transparent;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 5px;
color: var(--icon-color);
height: 30px;
box-shadow: none;
border: 1px solid var(--nav-item-background-active);
font-weight: normal;
font-size: 14px;
background: var(--background-secondary);
padding: 4px 6px;
outline: none;
user-select: none;
white-space: nowrap;
flex: 0;
}
.tasksCalendar button:nth-child(2),
.tasksCalendar button:nth-child(3),
.tasksCalendar button:nth-child(6) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: 0.5px solid var(--nav-item-background-active);
margin-right: 0;
}
.tasksCalendar button:nth-child(3),
.tasksCalendar button:nth-child(4),
.tasksCalendar button:nth-child(7) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left: 0.5px solid var(--nav-item-background-active);
margin-left: 0;
}
.tasksCalendar .current {
margin: 0 4px;
display: inline;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.tasksCalendar .current span:first-child {
font-weight: bold;
color: var(--icon-color);
}
.tasksCalendar .current span:last-child {
font-weight: normal;
color: var(--icon-color-active);
}
.tasksCalendar button:nth-child(1) {
margin-right: 4px;
}
.tasksCalendar button:nth-child(8) {
margin-left: 4px;
}
.tasksCalendar svg {
height: var(--icon-size);
width: var(--icon-size);
stroke-width: var(--icon-stroke);
}
.tasksCalendar .statisticPopup,
.tasksCalendar .weekViewContext {
display: none;
border-radius: 5px;
font-size: 10px;
border: 1px solid var(--nav-item-background-active);
position: absolute;
height: auto;
width: 150px;
width: auto;
background: var(--icon-color);
margin: 0 !important;
list-style: none;
padding: 2px !important;
z-index: 99;
box-shadow: 0px 0px 10px 0px var(--nav-item-background-active);
background: var(--background-secondary);
}
.tasksCalendar .statisticPopup {
right: 0;
}
.tasksCalendar .weekViewContext {
left: 65px;
}
.tasksCalendar .statisticPopup:before,
.tasksCalendar .weekViewContext:before {
content: "";
width: 0px;
height: 0px;
-webkit-transform:rotate(360deg);
border-style: solid;
border-width: 0 10px 10px 10px;
border-color: transparent transparent var(--background-secondary) transparent;
position: absolute;
}
.tasksCalendar .statisticPopup:before {
top: -10px;
right: 5px;
}
.tasksCalendar .weekViewContext:before {
top: -10px;
left: 5px;
}
.tasksCalendar .statisticPopup.active,
.tasksCalendar .weekViewContext.active {
display: block;
}
.tasksCalendar .statisticPopup li,
.tasksCalendar .weekViewContext li {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
height: auto;
font-size: 14px;
list-style: none;
color: var(--text-normal);
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
}
.tasksCalendar .statisticPopup li.active,
.tasksCalendar .weekViewContext li.active {
background: var(--background-modifier-active-hover);
color: var(--icon-color-active) !important;
}
body:not(.is-mobile) .tasksCalendar .statisticPopup li:not(.active):hover,
body:not(.is-mobile) .tasksCalendar .weekViewContext li:not(.active):hover {
background: var(--background-modifier-hover);
}
.tasksCalendar .statisticPopup li.break,
.tasksCalendar .weekViewContext li.break {
height: 1px !important;
background: var(--nav-item-background-active);
margin: 2px 5px !important;
border-radius: 0 !important;
padding: 0 !important;
}
.tasksCalendar .statisticPopup > div,
.tasksCalendar .weekViewContext > div {
height: 13px;
margin: auto 0;
}
.tasksCalendar button.statistic {
position: relative;
}
.tasksCalendar button.statistic svg {
stroke: var(--icon-color);
}
.tasksCalendar button.statistic[data-percentage="100"]:after {
display: none !important;
}
.tasksCalendar button.statistic:after {
content: attr(data-remaining);
position: absolute;
height: 14px;
width: 14px;
top: -8px;
right: -8px;
border-radius: 50%;
text-align: center;
line-height: 14px;
font-size: 9px;
font-weight: bold;
border: 1px solid var(--nav-item-background-active);
overflow: hidden;
color: var(--icon-color);
background: var(--background-secondary);
}
.tasksCalendar .weekViewContext .liIcon {
display: grid !important;
height: 18px;
width: 18px;
margin-right: 5px;
padding: 2px;
}
.tasksCalendar .weekViewContext .liIcon .box {
background: var(--icon-color);
z-index: 1;
display: grid;
overflow: hidden;
margin: 0.5px;
border-radius: 1px;
}
.tasksCalendar .weekViewContext li.active .liIcon .box {
background: var(--icon-color-active) !important;
}
.tasksCalendar .grid {
overflow: hidden;
cursor: default;
width: 100%;
height: 75vH;
}
.tasksCalendar .list {
overflow-x: hidden;
overflow-y: auto;
cursor: default;
width: 100%;
height: 75vH;
}
.tasksCalendar .cell {
z-index: 1;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 1fr;
overflow: hidden;
margin: 1px 0;
}
.tasksCalendar .cellContent {
overflow-x: hidden;
overflow-y: auto;
align-content: start;
padding: 1px 0;
}
.tasksCalendar .cellContent::-webkit-scrollbar {
display: none;
}
.tasksCalendar .cellName {
display: block;
font-weight: normal;
padding: 0 2px;
color: var(--text-normal);
flex-shrink: 0;
flex-grow: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
text-align: left;
margin: 0;
font-size: 14px;
opacity: 0.8;
}
body:not(.is-mobile) .tasksCalendar .cellName:hover {
opacity: 1;
}
.tasksCalendar .task {
overflow: hidden;
padding: 1px;
background: var(--task-background);
border-radius: 3px;
overflow: hidden;
margin: 1px 1px 2px 1px;
font-size: 14px;
opacity: 0.8;
display: block;
}
body.theme-dark .tasksCalendar .task { color: var(--light-task-text-color); }
body.theme-light .tasksCalendar .task { color: var(--dark-task-text-color); }
body.theme-dark .tasksCalendar .task .note { color: var(--light-task-text-color); }
body.theme-light .tasksCalendar .task .note { color: var(--dark-task-text-color); }
body:not(.is-mobile) .tasksCalendar .task:hover {
opacity: 1;
}
.tasksCalendar .task.hide {
opacity: 0.2;
}
.tasksCalendar .task .inner {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-decoration: none;
word-break: break-all !important;
-webkit-hyphens: none !important;
line-height: 1.3;
text-decoration: none !important;
border-radius: 3px;
overflow: hidden;
}
.tasksCalendar a {
text-decoration: none !important;
}
.tasksCalendar .task .note {
display: block;
width: 100%;
font-size: 9px;
background: var(--task-background);
padding: 1px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.tasksCalendar .task .icon {
display: inline;
width: 18px;
height: 18px;
text-align: center;
margin-right: 3px;
}
.tasksCalendar .task .description {
display: inline;
padding: 1px;
}
.tasksCalendar .task .description:before {
display: inline;
content: attr(data-relative);
margin-right: 3px;
border-radius: 3px;
margin-right: 3px;
padding: 0 3px;
font-size: 9px;
vertical-align: middle;
}
.tasksCalendar .task.overdue .description:before {
color: white;
background: #ff443a;
}
.tasksCalendar .task:not(.overdue) .description:before {
display: none;
background: black;
color: white;
}
.tasksCalendar .task.dailyNote .description:before,
.tasksCalendar .task.done .description:before,
.tasksCalendar .task.cancelled .description:before {
display: none !important;
}
.tasksCalendar .task.cancelled .note,
.tasksCalendar .task.done .note {
background: var(--nav-item-background-active) !important;
color: var(--text-faint) !important;
}
.tasksCalendar .task.cancelled .description,
.tasksCalendar .task.done .description {
text-decoration: line-through !important;
color: var(--text-faint) !important;
}
.tasksCalendar .task.cancelled,
.tasksCalendar .task.done {
background: none !important;
}
.tasksCalendar .task.overdue .inner {
background: repeating-linear-gradient(45deg, var(--task-background), var(--task-background) 5px, transparent 5px, transparent 10px) !important;
}
/* Today & Weekends */
.tasksCalendar .cell.today .cellName {
font-weight: bold;
color: var(--text-normal);
opacity: 1;
}
.tasksCalendar .cell[data-weekday="0"].today .cellName {
font-weight: bold;
color: var(--icon-color-active);
opacity: 1;
}
.tasksCalendar[view='month'] .cell.today {
background: var(--background-modifier-active-hover) !important;
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25) !important;
border-radius: 5px;
}
.tasksCalendar[view='week'] .cell.today {
background: var(--background-modifier-active-hover) !important;
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25) !important;
}
.tasksCalendar .cell[data-weekday="0"] .cellName,
.tasksCalendar .gridHead[data-weekday="0"] {
color: var(--icon-color-active);
}
/* Month View */
.tasksCalendar[view='month'] .grid {
display: grid;
gap: 4px;
grid-template-rows: 20px 1fr !important;
grid-template-columns: 1fr !important;
}
.tasksCalendar[view='month'] .gridHeads {
display: grid;
grid-template-columns: 20px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important;
width: 100%;
height: 20px;
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
}
.tasksCalendar[view='month'] .gridHead {
display: inline;
box-sizing: border-box;
overflow: hidden;
text-align: center;
font-weight: bold;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0;
font-size: 14px;
height: 20px;
line-height: 20px;
font-size: 10px;
}
.tasksCalendar[view='month'] .wrappers {
display: grid;
grid-template-rows: repeat(6, calc(100% / 6));
grid-template-columns: 1fr !important;
min-height: 0;
height: calc(100% - 20px);
gap: 4px 4px;
}
.tasksCalendar[view='month'] .wrappers,
.tasksCalendar[view='week'] .grid {
position: relative;
}
.tasksCalendar[view='month'] .wrappers:before,
.tasksCalendar[view='week'] .grid:before,
.tasksCalendar[view='list'] .list:before {
z-index: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 120px;
font-weight: bold;
color: var(--background-modifier-active-hover);
}
.tasksCalendar[view='month'] .wrappers:before,
.tasksCalendar[view='list'] .list:before {
content: attr(data-month);
}
.tasksCalendar[view='week'] .grid:before {
content: attr(data-week);
}
.tasksCalendar[view='month'] .wrapper {
z-index: 1;
display: grid;
grid-template-rows: 1fr !important;
grid-template-columns: 22px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important;
width: 100%;
height: 100%;
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
overflow: hidden;
}
.tasksCalendar[view='month'] .wrapperButton {
display: flex;
writing-mode: vertical-lr;
transform: rotate(180deg);
background: none;
text-align: center;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: normal;
color: var(--text-normal);
color: var(--icon-color-active);
cursor: pointer;
width: 100%;
overflow: hidden;
/* background: var(--background-primary); */
background: var(--background-secondary);
}
.tasksCalendar[view='month'] .wrapperButton:hover {
background: var(--background-modifier-hover);
}
.tasksCalendar[view='month'] .cell {
margin: 0;
}
.tasksCalendar[view='month'] .prevMonth,
.tasksCalendar[view='month'] .nextMonth {
background: var(--background-secondary);
}
/* Week view */
.tasksCalendar[view='week'] .grid {
display: grid;
gap: 2px 4px;
}
.tasksCalendar[view='week'] .cell {
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
overflow: hidden;
}
/* List View */
.tasksCalendar[view='list'] .list {
border: 1px solid var(--nav-item-background-active);
border-radius: 5px;
}
.tasksCalendar[view='list'] .list .task,
.tasksCalendar[view='list'] .list .task.done,
.tasksCalendar[view='list'] .list .task .note,
.tasksCalendar[view='list'] .list .task.done .note{
background: transparent !important;
}
.tasksCalendar[view='list'] .list .task .inner {
display: flex !important;
flex-direction: row;
flex-wrap: nowrap;
padding: 0 10px;
white-space: nowrap;
}
.tasksCalendar[view='list'] .list .task .note {
display: inline-block;
width: 150px;
flex-shrink: 0;
flex-grow: 0;
}
.tasksCalendar[view='list'] .list .task .description {
width: 100%;
flex-shrink: 1;
flex-grow: 1;
}
.tasksCalendar[view='list'] .list .task.done .note,
.tasksCalendar[view='list'] .list .task.done .description,
.tasksCalendar[view='list'] .list .task.cancelled .note,
.tasksCalendar[view='list'] .list .task.cancelled .description {
color: var(--text-faint) !important;
}
.tasksCalendar[view='list'] .list .task .note,
.tasksCalendar[view='list'] .list .task .description {
color: var(--task-color) !important;
line-clamp: 0 !important;
white-space: nowrap !important;
text-overflow: ellipsis;
overflow: hidden;
font-size: 14px;
}
.tasksCalendar summary::marker,
.tasksCalendar summary::-webkit-details-marker {
display: none !important;
content: "" !important;
}
.tasksCalendar[view='list'] details.today {
background: var(--background-modifier-active-hover);
border: 1px solid hsla(var(--interactive-accent-hsl), 0.25);
}
.tasksCalendar[view='list'] details.today summary {
font-weight: bold;
background: none;
}
.tasksCalendar[view='list'] details.today .content {
margin: 3px;
}
.tasksCalendar[view='list'] details {
display: block;
margin: 5px;
border-radius: 5px;
overflow: hidden;
/*background: var(--background-secondary);*/
border: 1px solid var(--nav-item-background-active);
}
.tasksCalendar[view='list'] summary {
background: var(--background-secondary);
padding: 0 10px;
border-radius: 5px;
}
.tasksCalendar[view='list'] summary span.weekNr {
font-size: 11px;
color: var(--text-faint);
}
/* Style classes */
.tasksCalendar[view='week'].style1 .grid, .iconStyle1 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(6, 1fr); }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(1), .iconStyle1 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(2), .iconStyle1 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(3), .iconStyle1 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(4), .iconStyle1 .box:nth-child(4) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(5), .iconStyle1 .box:nth-child(5) { grid-area: 3 / 3 / 5 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(6), .iconStyle1 .box:nth-child(6) { grid-area: 5 / 3 / 6 / 5; }
.tasksCalendar[view='week'].style1 .grid .cell:nth-child(7), .iconStyle1 .box:nth-child(7) { grid-area: 6 / 3 / 7 / 5; }
.tasksCalendar[view='week'].style2 .grid, .iconStyle2 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(6, 1fr); }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(1), .iconStyle2 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(3), .iconStyle2 .box:nth-child(3) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(5), .iconStyle2 .box:nth-child(5) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(2), .iconStyle2 .box:nth-child(2) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(4), .iconStyle2 .box:nth-child(4) { grid-area: 3 / 3 / 5 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(6), .iconStyle2 .box:nth-child(6) { grid-area: 5 / 3 / 6 / 5; }
.tasksCalendar[view='week'].style2 .grid .cell:nth-child(7), .iconStyle2 .box:nth-child(7) { grid-area: 6 / 3 / 7 / 5; }
.tasksCalendar[view='week'].style3 .grid, .iconStyle3 { grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; grid-template-columns: 1fr; }
.tasksCalendar[view='week'].style4 .grid, .iconStyle4 { grid-template-rows: 1fr; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; }
.tasksCalendar[view='week'].style5 .grid, .iconStyle5 { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(10, 1fr); }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(1), .iconStyle5 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(2), .iconStyle5 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(3), .iconStyle5 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(4), .iconStyle5 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(5), .iconStyle5 .box:nth-child(5) { grid-area: 9 / 1 / 11 / 2; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(6), .iconStyle5 .box:nth-child(6) { grid-area: 1 / 2 / 6 / 3; }
.tasksCalendar[view='week'].style5 .grid .cell:nth-child(7), .iconStyle5 .box:nth-child(7) { grid-area: 6 / 2 / 11 / 3; }
.tasksCalendar[view='week'].style6 .grid, .iconStyle6 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(10, 1fr); }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(1), .iconStyle6 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(2), .iconStyle6 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(3), .iconStyle6 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(4), .iconStyle6 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(5), .iconStyle6 .box:nth-child(5) { grid-area: 9 / 1 / 11 / 3; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(6), .iconStyle6 .box:nth-child(6) { grid-area: 1 / 3 / 6 / 4; }
.tasksCalendar[view='week'].style6 .grid .cell:nth-child(7), .iconStyle6 .box:nth-child(7) { grid-area: 6 / 3 / 11 / 4; }
.tasksCalendar[view='week'].style7 .grid, .iconStyle7 { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(8, 1fr); }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(1), .iconStyle7 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(2), .iconStyle7 .box:nth-child(2) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(3), .iconStyle7 .box:nth-child(3) { grid-area: 5 / 1 / 7 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(4), .iconStyle7 .box:nth-child(4) { grid-area: 7 / 1 / 9 / 2; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(5), .iconStyle7 .box:nth-child(5) { grid-area: 1 / 2 / 3 / 3; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(6), .iconStyle7 .box:nth-child(6) { grid-area: 3 / 2 / 6 / 3; }
.tasksCalendar[view='week'].style7 .grid .cell:nth-child(7), .iconStyle7 .box:nth-child(7) { grid-area: 6 / 2 / 9 / 3; }
.tasksCalendar[view='week'].style8 .grid, .iconStyle8 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(5, 1fr); }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(1), .iconStyle8 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 2; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(2), .iconStyle8 .box:nth-child(2) { grid-area: 1 / 2 / 3 / 3; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(3), .iconStyle8 .box:nth-child(3) { grid-area: 1 / 3 / 3 / 4; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(4), .iconStyle8 .box:nth-child(4) { grid-area: 3 / 1 / 5 / 2; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(5), .iconStyle8 .box:nth-child(5) { grid-area: 3 / 2 / 5 / 3; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(6), .iconStyle8 .box:nth-child(6) { grid-area: 3 / 3 / 5 / 4; }
.tasksCalendar[view='week'].style8 .grid .cell:nth-child(7), .iconStyle8 .box:nth-child(7) { grid-area: 5 / 1 / 6 / 4; }
.tasksCalendar[view='week'].style9 .grid, .iconStyle9 { grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(3, 1fr); }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(1), .iconStyle9 .box:nth-child(1) { grid-area: 1 / 1 / 3 / 3; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(2), .iconStyle9 .box:nth-child(2) { grid-area: 1 / 3 / 3 / 5; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(3), .iconStyle9 .box:nth-child(3) { grid-area: 1 / 5 / 3 / 7; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(4), .iconStyle9 .box:nth-child(4) { grid-area: 1 / 7 / 3 / 9; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(5), .iconStyle9 .box:nth-child(5) { grid-area: 1 / 9 / 3 / 11; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(6), .iconStyle9 .box:nth-child(6) { grid-area: 3 / 1 / 4 / 6; }
.tasksCalendar[view='week'].style9 .grid .cell:nth-child(7), .iconStyle9 .box:nth-child(7) { grid-area: 3 / 6 / 4 / 11; }
.tasksCalendar[view='week'].style10 .grid, .iconStyle10 { grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(3, 1fr); }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(1), .iconStyle10 .box:nth-child(1) { grid-area: 1 / 1 / 4 / 3; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(2), .iconStyle10 .box:nth-child(2) { grid-area: 1 / 3 / 4 / 5; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(3), .iconStyle10 .box:nth-child(3) { grid-area: 1 / 5 / 4 / 7; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(4), .iconStyle10 .box:nth-child(4) { grid-area: 1 / 7 / 3 / 9; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(5), .iconStyle10 .box:nth-child(5) { grid-area: 1 / 9 / 3 / 11; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(6), .iconStyle10 .box:nth-child(6) { grid-area: 3 / 7 / 4 / 9; }
.tasksCalendar[view='week'].style10 .grid .cell:nth-child(7), .iconStyle10 .box:nth-child(7) { grid-area: 3 / 9 / 4 / 11; }
.tasksCalendar[view='week'].style11 .grid, .iconStyle11 { grid-template-rows: 1fr; grid-template-columns: 1fr 1fr 1fr 1fr 1fr; }
.tasksCalendar[view='week'].style11 .grid { height: 300px }
.tasksCalendar[view='week'].style11 .cell[data-weekday="0"], .iconStyle11 { display: none !important }
.tasksCalendar[view='week'].style11 .cell[data-weekday="6"], .iconStyle11 { display: none !important }
/* Options classes */
.tasksCalendar.noIcons .task .icon { display: none !important; }
.tasksCalendar:not(.noFilename) .task.noNoteIcon .icon { display: none !important; }
.tasksCalendar.noFilename .task .note { display: none !important; }
.tasksCalendar.filter .task.done, .tasksCalendar.filter .task.cancelled { display: none !important; }
.tasksCalendar.filter #statisticDone { pointer-events: none !important; color: var(--text-faint) !important; }
.tasksCalendar.noScheduled .task.scheduled { display: none !important; }
.tasksCalendar.noStart .task.start { display: none !important; }
.tasksCalendar.noDue .task.due { display: none !important; }
.tasksCalendar.noDone .task.done { display: none !important; }
.tasksCalendar.noProcess .task.process { display: none !important; }
.tasksCalendar.noRecurrence .task.recurrence { display: none !important; }
.tasksCalendar.noOverdue .task.overdue { display: none !important; }
.tasksCalendar.noDailyNote .task.dailyNote { display: none !important; }
.tasksCalendar.noCellNameEvent .cellName { pointer-events: none !important; }
.tasksCalendar.noLayer .grid .wrappers:before,
.tasksCalendar.noLayer .grid:before,
.tasksCalendar.noLayer .list:before { display: none !important;}
.tasksCalendar.focusDone .task { opacity: 0.25 !important; }
.tasksCalendar.focusDone .task.done { opacity: 1 !important; }
.tasksCalendar.focusDue .task { opacity: 0.25 !important; }
.tasksCalendar.focusDue .task.due { opacity: 1 !important; }
.tasksCalendar.focusOverdue .task { opacity: 0.25 !important; }
.tasksCalendar.focusOverdue .task.overdue { opacity: 1 !important; }
.tasksCalendar.focusStart .task { opacity: 0.25 !important; }
.tasksCalendar.focusStart .task.start { opacity: 1 !important; }
.tasksCalendar.focusScheduled .task { opacity: 0.25 !important; }
.tasksCalendar.focusScheduled .task.scheduled { opacity: 1 !important; }
.tasksCalendar.focusRecurrence .task { opacity: 0.25 !important; }
.tasksCalendar.focusRecurrence .task.recurrence { opacity: 1 !important; }
.tasksCalendar.focusDailyNote .task { opacity: 0.25 !important; }
.tasksCalendar.focusDailyNote .task.dailyNote { opacity: 1 !important; }
.tasksCalendar.mini { max-width: 500px !important; margin: 0 auto; }
.tasksCalendar.mini .grid { height: 400px !important; }
.tasksCalendar.mini .gridHead,
.tasksCalendar.mini .cellName,
.tasksCalendar.mini .task,
.tasksCalendar.mini .wrapperButton { font-size: 9px !important; }
.tasksCalendar.mini .wrappers:before,
.tasksCalendar.mini .grid:before { font-size: 70px !important; }
.tasksCalendar.mini .statisticPopup li,
.tasksCalendar.mini .weekViewContext li { font-size: 9px !important; }
.tasksCalendar.noWeekNr .wrapperButton { visibility: hidden !important; width: 0 !important; }
.tasksCalendar.noWeekNr .gridHead:first-child { visibility: hidden !important; width: 0 !important; }
.tasksCalendar.noWeekNr .wrapper { grid-template-columns: 0px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important; }
.tasksCalendar.noWeekNr .gridHeads { grid-template-columns: 0px 1fr 1fr 1fr 1fr 1fr 1fr 1fr !important; }
.tasksCalendar.noWeekNr .list .weekNr { display: none !important; }
.tasksCalendar.lineClamp1 .task .inner { -webkit-line-clamp: 1 !important; white-space: nowrap !important; }
.tasksCalendar.lineClamp2 .task .inner { -webkit-line-clamp: 2 !important; }
.tasksCalendar.lineClamp3 .task .inner { -webkit-line-clamp: 3 !important; }
.tasksCalendar.noLineClamp .task .inner { display: block !important; }
.tasksCalendar.noOverdueFlag .task .description:before { display: none !important; }
/* Mobile View */
body.is-mobile .tasksCalendar .gridHead, body.is-mobile .tasksCalendar .cellName, body.is-mobile .tasksCalendar .task { font-size: 9px; }
body.is-mobile .tasksCalendar[view='week']:not(.style4) .cellName,
body.is-mobile .tasksCalendar[view='week']:not(.style4) .task { font-size: 13px !important; }
body.is-mobile .tasksCalendar .statisticPopup li { font-size: 13px !important; }

View File

@@ -1,702 +0,0 @@
let {pages, view, firstDayOfWeek, globalTaskFilter, dailyNoteFolder, dailyNoteFormat, startPosition, upcomingDays, css, options} = input;
// Error Handling
if (!pages && pages!="") { dv.span('> [!ERROR] Missing pages parameter\n> \n> Please set the pages parameter like\n> \n> `pages: ""`'); return false };
if (!options.includes("style")) { dv.span('> [!ERROR] Missing style parameter\n> \n> Please set a style inside options parameter like\n> \n> `options: "style1"`'); return false };
if (!view) { dv.span('> [!ERROR] Missing view parameter\n> \n> Please set a default view inside view parameter like\n> \n> `view: "month"`'); return false };
if (firstDayOfWeek) {
if (firstDayOfWeek.match(/[|\\0123456]/g) == null) {
dv.span('> [!ERROR] Wrong value inside firstDayOfWeek parameter\n> \n> Please choose a number between 0 and 6');
return false
};
} else {
dv.span('> [!ERROR] Missing firstDayOfWeek parameter\n> \n> Please set the first day of the week inside firstDayOfWeek parameter like\n> \n> `firstDayOfWeek: "1"`');
return false
};
if (startPosition) { if (!startPosition.match(/\d{4}\-\d{1,2}/gm)) { dv.span('> [!ERROR] Wrong startPosition format\n> \n> Please set a startPosition with the following format\n> \n> Month: `YYYY-MM` | Week: `YYYY-ww`'); return false }};
if (dailyNoteFormat) { if (dailyNoteFormat.match(/[|\\YMDWwd.,-: \[\]]/g).length != dailyNoteFormat.length) { dv.span('> [!ERROR] The `dailyNoteFormat` contains invalid characters'); return false }};
// Get, Set, Eval Pages
if (pages == "") {
var tasks = dv.pages().file.tasks;
} else if (typeof pages === "string" && pages.startsWith("dv.pages")) {
var tasks = eval(pages);
} else if (typeof pages && pages.every(p => p.task)) {
var tasks = pages;
} else {
var tasks = dv.pages(pages).file.tasks;
}
// Variables
var done, doneWithoutCompletionDate, due, recurrence, overdue, start, scheduled, process, cancelled, dailyNote, dailyNoteRegEx;
if (!dailyNoteFormat) { dailyNoteFormat = "YYYY-MM-DD" };
var dailyNoteRegEx = momentToRegex(dailyNoteFormat)
var tToday = moment().format("YYYY-MM-DD");
var tMonth = moment().format("M");
var tDay = moment().format("d");
var tYear = moment().format("YYYY");
var tid = (new Date()).getTime();
if (startPosition) { var selectedMonth = moment(startPosition, "YYYY-MM").date(1); var selectedList = moment(startPosition, "YYYY-MM").date(1); var selectedWeek = moment(startPosition, "YYYY-ww").startOf("week") } else { var selectedMonth = moment(startPosition).date(1); var selectedWeek = moment(startPosition).startOf("week"); var selectedList = moment(startPosition).date(1); };
var selectedDate = eval("selected"+capitalize(view));
var arrowLeftIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>';
var arrowRightIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>';
var filterIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg>';
var monthIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="M8 14h.01"></path><path d="M12 14h.01"></path><path d="M16 14h.01"></path><path d="M8 18h.01"></path><path d="M12 18h.01"></path><path d="M16 18h.01"></path></svg>';
var weekIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="M17 14h-6"></path><path d="M13 18H7"></path><path d="M7 14h.01"></path><path d="M17 18h.01"></path></svg>';
var listIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>';
var calendarClockIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"></path><path d="M16 2v4"></path><path d="M8 2v4"></path><path d="M3 10h5"></path><path d="M17.5 17.5 16 16.25V14"></path><path d="M22 16a6 6 0 1 1-12 0 6 6 0 0 1 12 0Z"></path></svg>';
var calendarCheckIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line><path d="m9 16 2 2 4-4"></path></svg>';
var calendarHeartIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h7"></path><path d="M16 2v4"></path><path d="M8 2v4"></path><path d="M3 10h18"></path><path d="M21.29 14.7a2.43 2.43 0 0 0-2.65-.52c-.3.12-.57.3-.8.53l-.34.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L17.5 22l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"></path></svg>';
var cellTemplate = "<div class='cell {{class}}' data-weekday='{{weekday}}'><a class='internal-link cellName' href='{{dailyNote}}'>{{cellName}}</a><div class='cellContent'>{{cellContent}}</div></div>";
var taskTemplate = "<a class='internal-link' href='{{taskPath}}'><div class='task {{class}}' style='{{style}}' title='{{title}}'><div class='inner'><div class='note'>{{note}}</div><div class='icon'>{{icon}}</div><div class='description' data-relative='{{relative}}'>{{taskContent}}</div></div></div></a>";
const rootNode = dv.el("div", "", {cls: "tasksCalendar "+options, attr: {id: "tasksCalendar"+tid, view: view, style: 'position:relative;-webkit-user-select:none!important'}});
if (css) { var style = document.createElement("style"); style.innerHTML = css; rootNode.append(style) };
var taskDoneIcon = "✅";
var taskDueIcon = "📅";
var taskScheduledIcon = "⏳";
var taskRecurrenceIcon = "🔁";
var taskOverdueIcon = "⚠️";
var taskProcessIcon = "⏺️";
var taskCancelledIcon = "🚫";
var taskStartIcon = "🛫";
var taskDailyNoteIcon = "📄";
// Initialze
getMeta(tasks);
setButtons();
setStatisticPopUp();
setWeekViewContext();
eval("get"+capitalize(view))(tasks, selectedDate);
function getMeta(tasks) {
for (i=0;i<tasks.length;i++) {
var taskText = tasks[i].text;
var taskFile = getFilename(tasks[i].path);
var dailyNoteMatch = taskFile.match(eval(dailyNoteRegEx));
var dailyTaskMatch = taskText.match(/(\d{4}\-\d{2}\-\d{2})/);
if (dailyNoteMatch) {
if(!dailyTaskMatch) {
tasks[i].dailyNote = moment(dailyNoteMatch[1], dailyNoteFormat).format("YYYY-MM-DD")
};
};
var dueMatch = taskText.match(/\📅\W(\d{4}\-\d{2}\-\d{2})/);
if (dueMatch) {
tasks[i].due = dueMatch[1];
tasks[i].text = tasks[i].text.replace(dueMatch[0], "");
};
var startMatch = taskText.match(/\🛫\W(\d{4}\-\d{2}\-\d{2})/);
if (startMatch) {
tasks[i].start = startMatch[1];
tasks[i].text = tasks[i].text.replace(startMatch[0], "");
};
var scheduledMatch = taskText.match(/\⏳\W(\d{4}\-\d{2}\-\d{2})/);
if (scheduledMatch) {
tasks[i].scheduled = scheduledMatch[1];
tasks[i].text = tasks[i].text.replace(scheduledMatch[0], "");
};
var completionMatch = taskText.match(/\✅\W(\d{4}\-\d{2}\-\d{2})/);
if (completionMatch) {
tasks[i].completion = completionMatch[1];
tasks[i].text = tasks[i].text.replace(completionMatch[0], "");
};
var repeatMatch = taskText.includes("🔁");
if (repeatMatch) {
tasks[i].recurrence = true;
tasks[i].text = tasks[i].text.substring(0, taskText.indexOf("🔁"))
};
var lowMatch = taskText.includes("🔽");
if (lowMatch) {
tasks[i].priority = "D";
};
var mediumMatch = taskText.includes("🔼");
if (mediumMatch) {
tasks[i].priority = "B";
};
var highMatch = taskText.includes("⏫");
if (highMatch) {
tasks[i].priority = "A";
};
if (!lowMatch && !mediumMatch && !highMatch) {
tasks[i].priority = "C";
}
if (globalTaskFilter) {
tasks[i].text = tasks[i].text.replaceAll(globalTaskFilter,"");
} else {
tasks[i].text = tasks[i].text.replaceAll("#task","");
};
tasks[i].text = tasks[i].text.replaceAll("[[","");
tasks[i].text = tasks[i].text.replaceAll("]]","");
tasks[i].text = tasks[i].text.replace(/\[.*?\]/gm,"");
};
};
function getFilename(path) {
var filename = path.match(/^(?:.*\/)?([^\/]+?|)(?=(?:\.[^\/.]*)?$)/)[1];
return filename;
};
function capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
};
function getMetaFromNote(task, metaName) {
var meta = dv.pages('"'+task.link.path+'"')[metaName][0];
if (meta) { return meta } else { return "" };
}
function transColor(color, percent) {
var num = parseInt(color.replace("#",""),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, B = (num >> 8 & 0x00FF) + amt, G = (num & 0x0000FF) + amt;
return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (B<255?B<1?0:B:255)*0x100 + (G<255?G<1?0:G:255)).toString(16).slice(1);
};
function momentToRegex(momentFormat) {
momentFormat = momentFormat.replaceAll(".", "\\.");
momentFormat = momentFormat.replaceAll(",", "\\,");
momentFormat = momentFormat.replaceAll("-", "\\-");
momentFormat = momentFormat.replaceAll(":", "\\:");
momentFormat = momentFormat.replaceAll(" ", "\\s");
momentFormat = momentFormat.replace("dddd", "\\w{1,}");
momentFormat = momentFormat.replace("ddd", "\\w{1,3}");
momentFormat = momentFormat.replace("dd", "\\w{2}");
momentFormat = momentFormat.replace("d", "\\d{1}");
momentFormat = momentFormat.replace("YYYY", "\\d{4}");
momentFormat = momentFormat.replace("YY", "\\d{2}");
momentFormat = momentFormat.replace("MMMM", "\\w{1,}");
momentFormat = momentFormat.replace("MMM", "\\w{3}");
momentFormat = momentFormat.replace("MM", "\\d{2}");
momentFormat = momentFormat.replace("DDDD", "\\d{3}");
momentFormat = momentFormat.replace("DDD", "\\d{1,3}");
momentFormat = momentFormat.replace("DD", "\\d{2}");
momentFormat = momentFormat.replace("D", "\\d{1,2}");
momentFormat = momentFormat.replace("ww", "\\d{1,2}");
regEx = "/^(" + momentFormat + ")$/";
return regEx;
};
function getTasks(date) {
done = tasks.filter(t=>t.completed && t.checked && t.completion && moment(t.completion.toString()).isSame(date)).sort(t=>t.completion);
doneWithoutCompletionDate = tasks.filter(t=>t.completed && t.checked && !t.completion && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
done = done.concat(doneWithoutCompletionDate);
due = tasks.filter(t=>!t.completed && !t.checked && !t.recurrence && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
recurrence = tasks.filter(t=>!t.completed && !t.checked && t.recurrence && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
overdue = tasks.filter(t=>!t.completed && !t.checked && t.due && moment(t.due.toString()).isBefore(date)).sort(t=>t.due);
start = tasks.filter(t=>!t.completed && !t.checked && t.start && moment(t.start.toString()).isSame(date)).sort(t=>t.start);
scheduled = tasks.filter(t=>!t.completed && !t.checked && t.scheduled && moment(t.scheduled.toString()).isSame(date)).sort(t=>t.scheduled);
process = tasks.filter(t=>!t.completed && !t.checked && t.due && t.start && moment(t.due.toString()).isAfter(date) && moment(t.start.toString()).isBefore(date) );
cancelled = tasks.filter(t=>!t.completed && t.checked && t.due && moment(t.due.toString()).isSame(date)).sort(t=>t.due);
dailyNote = tasks.filter(t=>!t.completed && !t.checked && t.dailyNote && moment(t.dailyNote.toString()).isSame(date)).sort(t=>t.dailyNote);
};
function setTask(obj, cls) {
var lighter = 25;
var darker = -40;
var noteColor = getMetaFromNote(obj, "color");
var textColor = getMetaFromNote(obj, "textColor");
var noteIcon = getMetaFromNote(obj, "icon");
var taskText = obj.text.replace("'", "&apos;");
var taskPath = obj.link.path.replace("'", "&apos;");
var taskIcon = eval("task"+capitalize(cls)+"Icon");
if (obj.due) { var relative = moment(obj.due).fromNow() } else { var relative = "" };
var noteFilename = getFilename(taskPath);
if (noteIcon) { noteFilename = noteIcon+"&nbsp;"+noteFilename } else { noteFilename = taskIcon+"&nbsp;"+noteFilename; cls += " noNoteIcon" };
var taskSubpath = obj.header.subpath;
var taskLine = taskSubpath ? taskPath+"#"+taskSubpath : taskPath;
if (noteColor && textColor) {
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+textColor+";--light-task-text-color:"+textColor;
} else if (noteColor && !textColor){
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+transColor(noteColor, darker)+";--light-task-text-color:"+transColor(noteColor, lighter);
var style = "--task-background:"+noteColor+"33;--task-color:"+noteColor+";--dark-task-text-color:"+transColor(noteColor, darker)+";--light-task-text-color:"+transColor(noteColor, lighter);
} else if (!noteColor && textColor ){
var style = "--task-background:#7D7D7D33;--task-color:#7D7D7D;--dark-task-text-color:"+transColor(textColor, darker)+";--light-task-text-color:"+transColor(textColor, lighter);
} else {
var style = "--task-background:#7D7D7D33;--task-color:#7D7D7D;--dark-task-text-color:"+transColor("#7D7D7D", darker)+";--light-task-text-color:"+transColor("#7D7D7D", lighter);
};
var newTask = taskTemplate.replace("{{taskContent}}", taskText).replace("{{class}}", cls).replace("{{taskPath}}", taskLine).replace("{{due}}","done").replaceAll("{{style}}",style).replace("{{title}}", noteFilename + ": " + taskText).replace("{{note}}",noteFilename).replace("{{icon}}",taskIcon).replace("{{relative}}",relative);
return newTask;
};
function setTaskContentContainer(currentDate) {
var cellContent = "";
function compareFn(a, b) {
if (a.priority.toUpperCase() < b.priority.toUpperCase()) {
return -1;
};
if (a.priority.toUpperCase() > b.priority.toUpperCase()) {
return 1;
};
if (a.priority == b.priority) {
if (a.text.toUpperCase() < b.text.toUpperCase()) {
return -1;
};
if (a.text.toUpperCase() > b.text.toUpperCase()) {
return 1;
};
return 0;
};
};
function showTasks(tasksToShow, type) {
const sorted = [...tasksToShow].sort(compareFn);
for (var t = 0; t < sorted.length; t++) {
cellContent += setTask(sorted[t], type)
};
};
if (tToday == currentDate) {
showTasks(overdue, "overdue");
};
showTasks(due, "due");
showTasks(recurrence, "recurrence");
showTasks(start, "start");
showTasks(scheduled, "scheduled");
showTasks(process, "process");
showTasks(dailyNote, "dailyNote");
showTasks(done, "done");
showTasks(cancelled, "cancelled");
return cellContent;
};
function setButtons() {
var buttons = "<button class='filter'>"+filterIcon+"</button><button class='listView' title='List'>"+listIcon+"</button><button class='monthView' title='Month'>"+monthIcon+"</button><button class='weekView' title='Week'>"+weekIcon+"</button><button class='current'></button><button class='previous'>"+arrowLeftIcon+"</button><button class='next'>"+arrowRightIcon+"</button><button class='statistic' percentage=''></button>";
rootNode.querySelector("span").appendChild(dv.el("div", buttons, {cls: "buttons", attr: {}}));
setButtonEvents();
};
function setButtonEvents() {
rootNode.querySelectorAll('button').forEach(btn => btn.addEventListener('click', (() => {
var activeView = rootNode.getAttribute("view");
if ( btn.className == "previous" ) {
if (activeView == "month") {
selectedDate = moment(selectedDate).subtract(1, "months");
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment(selectedDate).subtract(7, "days").startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment(selectedDate).subtract(1, "months");
getList(tasks, selectedDate);
}
} else if ( btn.className == "current") {
if (activeView == "month") {
selectedDate = moment().date(1);
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment().startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment().date(1);
getList(tasks, selectedDate);
};
} else if ( btn.className == "next" ) {
if (activeView == "month") {
selectedDate = moment(selectedDate).add(1, "months");
getMonth(tasks, selectedDate);
} else if (activeView == "week") {
selectedDate = moment(selectedDate).add(7, "days").startOf("week");
getWeek(tasks, selectedDate);
} else if (activeView == "list") {
selectedDate = moment(selectedDate).add(1, "months");
getList(tasks, selectedDate);
};
} else if ( btn.className == "filter" ) {
rootNode.classList.toggle("filter");
rootNode.querySelector('#statisticDone').classList.remove("active");
rootNode.classList.remove("focusDone");
} else if ( btn.className == "monthView" ) {
if ( moment().format("ww-YYYY") == moment(selectedDate).format("ww-YYYY") ) {
selectedDate = moment().date(1);
} else {
selectedDate = moment(selectedDate).date(1);
};
getMonth(tasks, selectedDate);
} else if ( btn.className == "listView" ) {
if ( moment().format("ww-YYYY") == moment(selectedDate).format("ww-YYYY") ) {
selectedDate = moment().date(1);
} else {
selectedDate = moment(selectedDate).date(1);
};
getList(tasks, selectedDate);
} else if ( btn.className == "weekView" ) {
if (rootNode.getAttribute("view") == "week") {
var leftPos = rootNode.querySelector("button.weekView").offsetLeft;
rootNode.querySelector(".weekViewContext").style.left = leftPos+"px";
rootNode.querySelector(".weekViewContext").classList.toggle("active");
if (rootNode.querySelector(".weekViewContext").classList.contains("active")) {
var closeContextListener = function() {
rootNode.querySelector(".weekViewContext").classList.remove("active");
rootNode.removeEventListener("click", closeContextListener, false);
};
setTimeout(function() {
rootNode.addEventListener("click", closeContextListener, false);
}, 100);
};
} else {
if (moment().format("MM-YYYY") != moment(selectedDate).format("MM-YYYY")) {
selectedDate = moment(selectedDate).startOf("month").startOf("week");
} else {
selectedDate = moment().startOf("week");
};
getWeek(tasks, selectedDate);
};
} else if ( btn.className == "statistic" ) {
rootNode.querySelector(".statisticPopup").classList.toggle("active");
};
btn.blur();
})));
rootNode.addEventListener('contextmenu', function(event) {
event.preventDefault();
});
};
function setWrapperEvents() {
rootNode.querySelectorAll('.wrapperButton').forEach(wBtn => wBtn.addEventListener('click', (() => {
var week = wBtn.getAttribute("data-week");
var year = wBtn.getAttribute("data-year");
selectedDate = moment(moment(year).add(week, "weeks")).startOf("week");
rootNode.querySelector(`#tasksCalendar${tid} .grid`).remove();
getWeek(tasks, selectedDate);
})));
};
function setStatisticPopUpEvents() {
rootNode.querySelectorAll('.statisticPopup li').forEach(li => li.addEventListener('click', (() => {
var group = li.getAttribute("data-group");
const liElements = rootNode.querySelectorAll('.statisticPopup li');
if (li.classList.contains("active")) {
const liElements = rootNode.querySelectorAll('.statisticPopup li');
for (const liElement of liElements) {
liElement.classList.remove('active');
};
rootNode.classList.remove("focus"+capitalize(group));
} else {
for (const liElement of liElements) {
liElement.classList.remove('active');
};
li.classList.add("active");
rootNode.classList.remove.apply(rootNode.classList, Array.from(rootNode.classList).filter(v=>v.startsWith("focus")));
rootNode.classList.add("focus"+capitalize(group));
};
})));
};
function setStatisticPopUp() {
var statistic = "<li id='statisticDone' data-group='done'></li>";
statistic += "<li id='statisticDue' data-group='due'></li>";
statistic += "<li id='statisticOverdue' data-group='overdue'></li>";
statistic += "<li class='break'></li>";
statistic += "<li id='statisticStart' data-group='start'></li>";
statistic += "<li id='statisticScheduled' data-group='scheduled'></li>";
statistic += "<li id='statisticRecurrence' data-group='recurrence'></li>";
statistic += "<li class='break'></li>";
statistic += "<li id='statisticDailyNote' data-group='dailyNote'></li>";
rootNode.querySelector("span").appendChild(dv.el("ul", statistic, {cls: "statisticPopup"}));
setStatisticPopUpEvents();
};
function setWeekViewContextEvents() {
rootNode.querySelectorAll('.weekViewContext li').forEach(li => li.addEventListener('click', (() => {
var selectedStyle = li.getAttribute("data-style");
const liElements = rootNode.querySelectorAll('.weekViewContext li');
if (!li.classList.contains("active")) {
for (const liElement of liElements) {
liElement.classList.remove('active');
};
li.classList.add("active");
rootNode.classList.remove.apply(rootNode.classList, Array.from(rootNode.classList).filter(v=>v.startsWith("style")));
rootNode.classList.add(selectedStyle);
};
rootNode.querySelector(".weekViewContext").classList.toggle("active");
})));
};
function setWeekViewContext() {
var activeStyle = Array.from(rootNode.classList).filter(v=>v.startsWith("style"));
var liElements = "";
var styles = 11;
for (i=1;i<styles+1;i++) {
var liIcon = "<div class='liIcon iconStyle"+i+"'><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div><div class='box'></div></div>";
liElements += "<li data-style='style"+i+"'>"+liIcon+"Style "+i+"</li>";
};
rootNode.querySelector("span").appendChild(dv.el("ul", liElements, {cls: "weekViewContext"}));
rootNode.querySelector(".weekViewContext li[data-style="+activeStyle+"]").classList.add("active");
setWeekViewContextEvents();
};
function setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter) {
var taskCounter = parseInt(dueCounter+doneCounter+overdueCounter);
var tasksRemaining = taskCounter - doneCounter;
var percentage = Math.round(100/(dueCounter+doneCounter+overdueCounter)*doneCounter);
percentage = isNaN(percentage) ? 100 : percentage;
if (dueCounter == 0 && doneCounter == 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarHeartIcon;
} else if (tasksRemaining > 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarClockIcon;
} else if (dueCounter == 0 && doneCounter != 0) {
rootNode.querySelector("button.statistic").innerHTML = calendarCheckIcon;
};
if (tasksRemaining > 99) {tasksRemaining = "⚠️"};
rootNode.querySelector("button.statistic").setAttribute("data-percentage", percentage);
rootNode.querySelector("button.statistic").setAttribute("data-remaining", tasksRemaining);
rootNode.querySelector("#statisticDone").innerText = "✅ Done: " + doneCounter + "/" + taskCounter;
rootNode.querySelector("#statisticDue").innerText = "📅 Due: " + dueCounter;
rootNode.querySelector("#statisticOverdue").innerText = "⚠️ Overdue: " + overdueCounter;
rootNode.querySelector("#statisticStart").innerText = "🛫 Start: " + startCounter;
rootNode.querySelector("#statisticScheduled").innerText = "⏳ Scheduled: " + scheduledCounter;
rootNode.querySelector("#statisticRecurrence").innerText = "🔁 Recurrence: " + recurrenceCounter;
rootNode.querySelector("#statisticDailyNote").innerText = "📄 Daily Notes: " + dailyNoteCounter;
};
function removeExistingView() {
if (rootNode.querySelector(`#tasksCalendar${tid} .grid`)) {
rootNode.querySelector(`#tasksCalendar${tid} .grid`).remove();
} else if (rootNode.querySelector(`#tasksCalendar${tid} .list`)) {
rootNode.querySelector(`#tasksCalendar${tid} .list`).remove();
};
};
function getMonth(tasks, month) {
removeExistingView();
var currentTitle = "<span>"+moment(month).format("MMMM")+"</span><span> "+moment(month).format("YYYY")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle;
var gridContent = "";
var firstDayOfMonth = moment(month).format("d");
var firstDateOfMonth = moment(month).startOf("month").format("D");
var lastDateOfMonth = moment(month).endOf("month").format("D");
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
// Move First Week Of Month To Second Week In Month View
if (firstDayOfMonth == 0) { firstDayOfMonth = 7};
// Set Grid Heads
var gridHeads = "";
for (h=0-firstDayOfMonth+parseInt(firstDayOfWeek);h<7-firstDayOfMonth+parseInt(firstDayOfWeek);h++) {
var weekDayNr = moment(month).add(h, "days").format("d");
var weekDayName = moment(month).add(h, "days").format("ddd");
if ( tDay == weekDayNr && tMonth == moment(month).format("M") && tYear == moment(month).format("YYYY") ) {
gridHeads += "<div class='gridHead today' data-weekday='" + weekDayNr + "'>" + weekDayName + "</div>";
} else {
gridHeads += "<div class='gridHead' data-weekday='" + weekDayNr + "'>" + weekDayName + "</div>";
};
};
// Set Wrappers
var wrappers = "";
var starts = 0-firstDayOfMonth+parseInt(firstDayOfWeek);
for (w=1; w<7; w++) {
var wrapper = "";
var weekNr = "";
var yearNr = "";
var monthName = moment(month).format("MMM").replace(".","").substring(0,3);
for (i=starts;i<starts+7;i++) {
if (i==starts) {
weekNr = moment(month).add(i, "days").format("w");
yearNr = moment(month).add(i, "days").format("YYYY");
};
var currentDate = moment(month).add(i, "days").format("YYYY-MM-DD");
var currentDate1 = moment(month).add(i, "days").format("YYYY-MM-DD(ddd)");
if (!dailyNoteFolder) {var dailyNotePath = currentDate1} else {var dailyNotePath = dailyNoteFolder+"/"+currentDate1};
var weekDay = moment(month).add(i, "days").format("d");
var shortDayName = moment(month).add(i, "days").format("D");
var longDayName = moment(month).add(i, "days").format("D. MMM");
var shortWeekday = moment(month).add(i, "days").format("ddd");
// Filter Tasks
getTasks(currentDate);
// Count Events Only From Selected Month
if (moment(month).format("MM") == moment(month).add(i, "days").format("MM")) {
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
// Get Overdue Count From Today
if (moment().format("YYYY-MM-DD") == moment(month).add(i, "days").format("YYYY-MM-DD")) {
overdueCounter = overdue.length;
};
};
// Set New Content Container
var cellContent = setTaskContentContainer(currentDate);
// Set Cell Name And Weekday
if ( moment(month).add(i, "days").format("D") == 1 ) {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
cell = cell.replace("{{class}}", "{{class}} newMonth");
} else {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", shortDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
};
// Set prevMonth, currentMonth, nextMonth
if (i < 0) {
cell = cell.replace("{{class}}", "prevMonth");
} else if (i >= 0 && i < lastDateOfMonth && tToday !== currentDate) {
cell = cell.replace("{{class}}", "currentMonth");
} else if ( i >= 0 && i< lastDateOfMonth && tToday == currentDate) {
cell = cell.replace("{{class}}", "currentMonth today");
} else if (i >= lastDateOfMonth) {
cell = cell.replace("{{class}}", "nextMonth");
};
wrapper += cell;
};
wrappers += "<div class='wrapper'><div class='wrapperButton' data-week='"+weekNr+"' data-year='"+yearNr+"'>W"+weekNr+"</div>"+wrapper+"</div>";
starts += 7;
};
gridContent += "<div class='gridHeads'><div class='gridHead'></div>"+gridHeads+"</div>";
gridContent += "<div class='wrappers' data-month='"+monthName+"'>"+wrappers+"</div>";
rootNode.querySelector("span").appendChild(dv.el("div", gridContent, {cls: "grid"}));
setWrapperEvents();
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "month");
};
function getWeek(tasks, week) {
removeExistingView();
var currentTitle = "<span>"+moment(week).format("YYYY")+"</span><span> "+moment(week).format("[W]w")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle
var gridContent = "";
var currentWeekday = moment(week).format("d");
var weekNr = moment(week).format("[W]w");
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
for (i=0-currentWeekday+parseInt(firstDayOfWeek);i<7-currentWeekday+parseInt(firstDayOfWeek);i++) {
var currentDate = moment(week).add(i, "days").format("YYYY-MM-DD");
if (!dailyNoteFolder) {var dailyNotePath = currentDate} else {var dailyNotePath = dailyNoteFolder+"/"+currentDate};
var weekDay = moment(week).add(i, "days").format("d");
var dayName = moment(currentDate).format("ddd D.");
var longDayName = moment(currentDate).format("ddd, D. MMM");
// Filter Tasks
getTasks(currentDate);
// Count Events From Selected Week
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
if (moment().format("YYYY-MM-DD") == moment(week).add(i, "days").format("YYYY-MM-DD")) {
overdueCounter = overdue.length;
};
// Set New Content Container
var cellContent = setTaskContentContainer(currentDate);
// Set Cell Name And Weekday
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
// Set Cell Name And Weekday
if ( moment(week).add(i, "days").format("D") == 1 ) {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", longDayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
} else {
var cell = cellTemplate.replace("{{date}}", currentDate).replace("{{cellName}}", dayName).replace("{{cellContent}}", cellContent).replace("{{weekday}}", weekDay).replace("{{dailyNote}}", dailyNotePath);
};
// Set Today, Before Today, After Today
if (currentDate < tToday) {
cell = cell.replace("{{class}}", "beforeToday");
} else if (currentDate == tToday) {
cell = cell.replace("{{class}}", "today");
} else if (currentDate > tToday) {
cell = cell.replace("{{class}}", "afterToday");
};
gridContent += cell;
};
rootNode.querySelector("span").appendChild(dv.el("div", gridContent, {cls: "grid", attr:{'data-week': weekNr}}));
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "week");
};
function getList(tasks, month) {
removeExistingView();
var currentTitle = "<span>"+moment(month).format("MMMM")+"</span><span> "+moment(month).format("YYYY")+"</span>";
rootNode.querySelector('button.current').innerHTML = currentTitle;
var listContent = "";
var dueCounter = 0;
var doneCounter = 0;
var overdueCounter = 0;
var startCounter = 0;
var scheduledCounter = 0;
var recurrenceCounter = 0;
var dailyNoteCounter = 0;
// Loop Days From Current Month
for (i=0;i<moment(month).endOf('month').format("D");i++) {
var currentDate = moment(month).startOf('month').add(i, "days").format("YYYY-MM-DD");
var monthName = moment(month).format("MMM").replace(".","").substring(0,3);
// Filter Tasks
getTasks(currentDate);
// Count Events
dueCounter += due.length;
dueCounter += recurrence.length;
dueCounter += scheduled.length;
dueCounter += dailyNote.length;
doneCounter += done.length;
startCounter += start.length;
scheduledCounter += scheduled.length;
recurrenceCounter += recurrence.length;
dailyNoteCounter += dailyNote.length;
if (moment().format("YYYY-MM-DD") == currentDate) {
overdueCounter = overdue.length;
var overdueDetails = "<details open class='overdue'><summary>Overdue</summary>" + setTaskContentContainer(currentDate) + "</details>";
var todayDetails = "<details open class='today'><summary>Today</summary>" + setTaskContentContainer(currentDate) + "</details>";
// Upcoming
if (!upcomingDays) { upcomingDays = "7" };
var upcomingContent = "";
for (t=1;t<parseInt(upcomingDays)+1;t++) {
var next = moment(currentDate).add(t, "days").format("YYYY-MM-DD");
getTasks(next);
upcomingContent += setTaskContentContainer(next);
};
var upcomingDetails = "<details open class='upcoming'><summary>Upcoming</summary>" + upcomingContent + "</details>";
listContent += "<details open class='today'><summary><span>" + moment(currentDate).format("dddd, D") + "</span><span class='weekNr'> " + moment(currentDate).format("[W]w") + "</span></summary><div class='content'>" + overdueDetails + todayDetails + upcomingDetails + "</div></details>"
} else {
listContent += "<details open><summary><span>" + moment(currentDate).format("dddd, D") + "</span><span class='weekNr'> " + moment(currentDate).format("[W]w") + "</span></summary><div class='content'>" + setTaskContentContainer(currentDate) + "</div></details>"
};
};
rootNode.querySelector("span").appendChild(dv.el("div", listContent, {cls: "list", attr:{"data-month": monthName}}));
setStatisticValues(dueCounter, doneCounter, overdueCounter, startCounter, scheduledCounter, recurrenceCounter, dailyNoteCounter);
rootNode.setAttribute("view", "list");
// Scroll To Today If Selected Month Is Current Month
if ( moment().format("YYYY-MM") == moment(month).format("YYYY-MM") ) {
var listElement = rootNode.querySelector(".list");
var todayElement = rootNode.querySelector(".today")
var scrollPos = todayElement.offsetTop - todayElement.offsetHeight + 85;
listElement.scrollTo(0, scrollPos);
};
};