111
This commit is contained in:
4
.obsidian/workspace-mobile.json
vendored
4
.obsidian/workspace-mobile.json
vendored
@@ -15,8 +15,8 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"file": "2025년 월력형 메모형 일정.canvas",
|
"file": "2025년 월력형 메모형 일정.canvas",
|
||||||
"viewState": {
|
"viewState": {
|
||||||
"x": 72.33978119493428,
|
"x": 367.6551404139326,
|
||||||
"y": 16729.691819631746,
|
"y": 16424.826482819222,
|
||||||
"zoom": -0.22966050199868698
|
"zoom": -0.22966050199868698
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -793,30 +793,6 @@
|
|||||||
"width":406,
|
"width":406,
|
||||||
"height":60
|
"height":60
|
||||||
},
|
},
|
||||||
{"id":"adf17c4a04f03e39","type":"text","text":"# 1. 5. ( 월 )","x":-494,"y":16720,"width":409,"height":60},
|
|
||||||
{
|
|
||||||
"id":"f8e1a3382c3e3e4e",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 본부중대 멀티탭 설치 현황 합철",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":15880,
|
|
||||||
"width":414,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"c6cd0ac8c7319495",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 부대야전정비지시서 현횐ㅇ(미완결)처리",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":15940,
|
|
||||||
"width":414,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"e8c7e9ac898f158e","type":"text","text":"# 12. 30. ( 화 ) ","x":-90,"y":16420,"width":399,"height":60},
|
|
||||||
{"id":"f2ca8fae1b695873","type":"text","text":"- [ ] 당직근무","x":-90,"y":16480,"width":399,"height":50},
|
|
||||||
{"id":"aa8027f65819cda6","type":"text","text":"# 1. 6. ( 화 ) ","x":-85,"y":16720,"width":399,"height":60},
|
|
||||||
{
|
{
|
||||||
"id":"4fcef30f72c539a8",
|
"id":"4fcef30f72c539a8",
|
||||||
"type":"text",
|
"type":"text",
|
||||||
@@ -869,101 +845,6 @@
|
|||||||
"height":60,
|
"height":60,
|
||||||
"color":"1"
|
"color":"1"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id":"b15297ff20881dca",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] [[동절기 채난유류(등유) 위탁보관, 수불]],~26.3.15,김용대",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":16000,
|
|
||||||
"width":414,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"e5f0cf0bd07871f1",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 판초우의 교체 소요 파악,~29,박형주",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-500,
|
|
||||||
"y":16240,
|
|
||||||
"width":260,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"c2944f832283822a","type":"text","text":"# 12. 29. ( 월 )","x":-499,"y":16420,"width":409,"height":60},
|
|
||||||
{"id":"4bc34dd3a8c3ef44","type":"text","text":"# 12.23(화) ","x":-85,"y":15760,"width":399,"height":60},
|
|
||||||
{
|
|
||||||
"id":"7632cbecf133635e",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] [[전투장비지휘검열]] 후속조치",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":16060,
|
|
||||||
"width":409,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"8a48bb0ad5d1b8a4",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 26년 소방계획서 공문보고, 출력물(양면) 제출,유재형",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-494,
|
|
||||||
"y":16120,
|
|
||||||
"width":409,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"5ce3bc84326ed106",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 26년 장비 예방정비 계획표 입력,~26,원정완",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":16180,
|
|
||||||
"width":2020,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"871723bf627c4aa3","type":"text","text":"# 12.24(수) ","x":309,"y":15760,"width":409,"height":60},
|
|
||||||
{"id":"d774d3ed75270acf","type":"text","text":"# 12. 31. ( 수 ) ","x":309,"y":16420,"width":409,"height":60},
|
|
||||||
{
|
|
||||||
"id":"785a1545c87d4753",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 본부중대 보일러실 온풍기 추가 수정",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":15820,
|
|
||||||
"width":414,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"cb181c2f3d7f06e2","type":"text","text":"# 12.22(월)","x":-494,"y":15760,"width":409,"height":60},
|
|
||||||
{
|
|
||||||
"id":"87086b245a59b199",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 보급,통가솔린두입구,플라스틱,10개,화인찬,김용대,1500,4번창고",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-107,
|
|
||||||
"y":15820,
|
|
||||||
"width":421,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"8e165c613d791ff3",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 25년 치장물자 실셈 재물조사 후 결산 추진 지시,조태숙",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":309,
|
|
||||||
"y":15820,
|
|
||||||
"width":409,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"b93656d41b466896",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 수통클린 세척,1,2교육대 636,800,한승민,~31",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":309,
|
|
||||||
"y":15880,
|
|
||||||
"width":409,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id":"cc00494d6eea2085",
|
"id":"cc00494d6eea2085",
|
||||||
"type":"text",
|
"type":"text",
|
||||||
@@ -1015,70 +896,6 @@
|
|||||||
"width":385,
|
"width":385,
|
||||||
"height":60
|
"height":60
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id":"719a08b28d4a3c2a",
|
|
||||||
"type":"text",
|
|
||||||
"text":"# 12.26(금)",
|
|
||||||
"styleAttributes":{
|
|
||||||
"border":null
|
|
||||||
},
|
|
||||||
"x":1122,
|
|
||||||
"y":15760,
|
|
||||||
"width":404,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"adf37e306dd3892d",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] [[간부필수교육]] 관리",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":1122,
|
|
||||||
"y":15820,
|
|
||||||
"width":399,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"6025294eb7304d85",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 전투장비지휘검열 후속조치계혹고고,원정욀",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":1122,
|
|
||||||
"y":15880,
|
|
||||||
"width":399,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"3a9626006f771473",
|
|
||||||
"type":"text",
|
|
||||||
"text":" - [ ] 25년 소방계획서 작성결과 통보",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-499,
|
|
||||||
"y":16530,
|
|
||||||
"width":808,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"a4f65e136e9b90cd",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 26년 재활용 자원매각 계약서 심의 후 결과보고,신상이, ~31",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-494,
|
|
||||||
"y":16590,
|
|
||||||
"width":1134,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":"287d550949875bd9",
|
|
||||||
"type":"text",
|
|
||||||
"text":"- [ ] 공간력 사업추진 소요보고,~31, 유재형,",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-500,
|
|
||||||
"y":16650,
|
|
||||||
"width":1212,
|
|
||||||
"height":70
|
|
||||||
},
|
|
||||||
{"id":"117e25b351f3d2bc","type":"text","text":"- [ ] 근무휴식","x":309,"y":16480,"width":409,"height":50},
|
|
||||||
{"id":"f10cd26fe462eb73","type":"text","text":"# 1. 7. ( 수 ) ","x":309,"y":16720,"width":409,"height":60},
|
|
||||||
{
|
{
|
||||||
"id":"331c9b8e052d7d98",
|
"id":"331c9b8e052d7d98",
|
||||||
"type":"text",
|
"type":"text",
|
||||||
@@ -1104,33 +921,6 @@
|
|||||||
{"id":"605e08f7842af9fd","type":"text","text":"# 9.25(목)\n- [x] 25년 부사관 역량강화 워크샵 0830-1730 6중대 강의장,2강의장,축구,중원탑막국수\n- [ ] 유압크레인 인솔(0830), 현수막 교체6개소 ==취소==\n- [ ] 동원예비군용, 부연대장용 치장총기 4정 치장 건의\n- [ ] 암호장비 반납 공문작성, 반납\n- [x] 총기탁본 수정,델리스상 업로드 ✅ 2025-09-25\n- [ ] ","x":677,"y":4020,"width":389,"height":700},
|
{"id":"605e08f7842af9fd","type":"text","text":"# 9.25(목)\n- [x] 25년 부사관 역량강화 워크샵 0830-1730 6중대 강의장,2강의장,축구,중원탑막국수\n- [ ] 유압크레인 인솔(0830), 현수막 교체6개소 ==취소==\n- [ ] 동원예비군용, 부연대장용 치장총기 4정 치장 건의\n- [ ] 암호장비 반납 공문작성, 반납\n- [x] 총기탁본 수정,델리스상 업로드 ✅ 2025-09-25\n- [ ] ","x":677,"y":4020,"width":389,"height":700},
|
||||||
{"id":"a894d9973fce5771","type":"text","text":"# 9.24(수)\n- [ ] 지원과 회식 ==취소==\n- [x] 화재취약 시설 일제 점검,소방안전FTX일정 확인~9.25(목)한\n- [x] 월동준비 퇴의,0930, 주임원사실\n- [ ] 1600, 장거리배차신고, 연대장님실. ==취소==\n- [x] 지역상생급식비 집행 #예산\n- [x] 타이머콘센트 구매, 사용다보수비","x":286,"y":4020,"width":391,"height":700},
|
{"id":"a894d9973fce5771","type":"text","text":"# 9.24(수)\n- [ ] 지원과 회식 ==취소==\n- [x] 화재취약 시설 일제 점검,소방안전FTX일정 확인~9.25(목)한\n- [x] 월동준비 퇴의,0930, 주임원사실\n- [ ] 1600, 장거리배차신고, 연대장님실. ==취소==\n- [x] 지역상생급식비 집행 #예산\n- [x] 타이머콘센트 구매, 사용다보수비","x":286,"y":4020,"width":391,"height":700},
|
||||||
{"id":"5ff577ba55755c0c","type":"text","text":"# 9.23(화)\n- [x] 유압크레인 배차신청\n- [ ] 26년 군 간부 자가운전 자동차 동원유보 대상 종합 보고,1500시한,원정완주무관\n- [x] 전입간부 상담관 상담(10시)\n- [ ] ","x":-116,"y":4020,"width":402,"height":700},
|
{"id":"5ff577ba55755c0c","type":"text","text":"# 9.23(화)\n- [x] 유압크레인 배차신청\n- [ ] 26년 군 간부 자가운전 자동차 동원유보 대상 종합 보고,1500시한,원정완주무관\n- [x] 전입간부 상담관 상담(10시)\n- [ ] ","x":-116,"y":4020,"width":402,"height":700},
|
||||||
{"id":"638dcbd292424977","type":"text","text":"# 2026. 1. 1. ( 목 )","x":718,"y":16420,"width":404,"height":60,"color":"1"},
|
|
||||||
{
|
|
||||||
"id":"379f515c3e778b70",
|
|
||||||
"type":"text",
|
|
||||||
"text":"# 2026. 1. 2. ( 금 )",
|
|
||||||
"styleAttributes":{
|
|
||||||
"border":null
|
|
||||||
},
|
|
||||||
"x":1122,
|
|
||||||
"y":16420,
|
|
||||||
"width":404,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"96a963d0474dfba7","type":"text","text":"# 2026. 1. 8. ( 목 )","x":718,"y":16720,"width":404,"height":60},
|
|
||||||
{
|
|
||||||
"id":"84ef4bfe943c7a64",
|
|
||||||
"type":"text",
|
|
||||||
"text":"# 2026. 1. 9. ( 금 )",
|
|
||||||
"styleAttributes":{
|
|
||||||
"border":null
|
|
||||||
},
|
|
||||||
"x":1122,
|
|
||||||
"y":16720,
|
|
||||||
"width":404,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"8fc3ca54ea18b843","type":"text","text":"# 12.25(목)","x":718,"y":15760,"width":404,"height":60,"color":"1"},
|
|
||||||
{"id":"289087511fbeeae9","type":"text","text":"# 9.26(금)\n- [ ] 유압크레인 인솔(0830), 현수막 교체6개소 ==취소==\n- [x] 제 2회 군인가족의날 행사(1130-1630,논산일대)\n- [ ] 유압크레인 배차신청, 현수막 교체6개소 ==취소==\n- 10중대, 사용자보수비 집행건의,유리파슨,최봉호상사 #예산\n\t- 7개소, 화요일견적서 받을예정\n\t- 10만원 에어컨 가스 ㅁㆍㄹ자유지비 집행예정\n- [ ] ~10.2(목) 영선반 연대본청,1~3교육대 지하 노후배관 점검예정\n- [x] 장거리배차 신고, 연대장님 시간 반영\n- [ ] 3교육대, 일병 박세정(행정병,) 무기고 고정출입자 신청\n- [x] 월동준비 계획 초안보고,주임원사님\n- [x] 아스콘, 포장작업,병영식당 앞\n- [ ] 환경예산 계획보고, 다음주 화요일수령예정\n- [x] k5방독면, 보호대 보유량, 신청시 선제 받을수 있는지 \n- [x] 훈련병 세제 소요, 펜?, 지퍼백? 보급기준","x":1060,"y":4020,"width":392,"height":700},
|
{"id":"289087511fbeeae9","type":"text","text":"# 9.26(금)\n- [ ] 유압크레인 인솔(0830), 현수막 교체6개소 ==취소==\n- [x] 제 2회 군인가족의날 행사(1130-1630,논산일대)\n- [ ] 유압크레인 배차신청, 현수막 교체6개소 ==취소==\n- 10중대, 사용자보수비 집행건의,유리파슨,최봉호상사 #예산\n\t- 7개소, 화요일견적서 받을예정\n\t- 10만원 에어컨 가스 ㅁㆍㄹ자유지비 집행예정\n- [ ] ~10.2(목) 영선반 연대본청,1~3교육대 지하 노후배관 점검예정\n- [x] 장거리배차 신고, 연대장님 시간 반영\n- [ ] 3교육대, 일병 박세정(행정병,) 무기고 고정출입자 신청\n- [x] 월동준비 계획 초안보고,주임원사님\n- [x] 아스콘, 포장작업,병영식당 앞\n- [ ] 환경예산 계획보고, 다음주 화요일수령예정\n- [x] k5방독면, 보호대 보유량, 신청시 선제 받을수 있는지 \n- [x] 훈련병 세제 소요, 펜?, 지퍼백? 보급기준","x":1060,"y":4020,"width":392,"height":700},
|
||||||
{"id":"29aaae03c8a89065","type":"text","text":"## 9.12(금)\n1. 위임보수 소요보고\n\t1. 오수관 누수 추가하고 최종 보고서 작성 검토보고(오전중)\n2. 당직근무 등록 소속 변경 요청\n3. 제설제 소요 파악 보고\n4. 1330 25년 4분기 위임보수 소요종합 보고(연대장님)","x":1063,"y":3280,"width":392,"height":260},
|
{"id":"29aaae03c8a89065","type":"text","text":"## 9.12(금)\n1. 위임보수 소요보고\n\t1. 오수관 누수 추가하고 최종 보고서 작성 검토보고(오전중)\n2. 당직근무 등록 소속 변경 요청\n3. 제설제 소요 파악 보고\n4. 1330 25년 4분기 위임보수 소요종합 보고(연대장님)","x":1063,"y":3280,"width":392,"height":260},
|
||||||
{"id":"6cf3ef32e3749744","type":"text","text":"# 9.5(금)\n1. 13:30 30연대장님 신고, 주임원사 면담\n2. 30연대 첫출근\n3. 월 지휘관 탄약고 점검 수행\n4. ","x":1020,"y":2880,"width":392,"height":202},
|
{"id":"6cf3ef32e3749744","type":"text","text":"# 9.5(금)\n1. 13:30 30연대장님 신고, 주임원사 면담\n2. 30연대 첫출근\n3. 월 지휘관 탄약고 점검 수행\n4. ","x":1020,"y":2880,"width":392,"height":202},
|
||||||
@@ -1906,22 +1696,7 @@
|
|||||||
"width":397,
|
"width":397,
|
||||||
"height":60
|
"height":60
|
||||||
},
|
},
|
||||||
{"id":"bbcf5864b29504a7","type":"text","text":"- [ ] 잔금일(휴가써야됨)","x":1122,"y":16780,"width":404,"height":50,"color":"1"},
|
|
||||||
{
|
|
||||||
"id":"addd0c07fae33c36",
|
|
||||||
"type":"text",
|
|
||||||
"text":"Tf현장확인/토의,~30,유재형",
|
|
||||||
"styleAttributes":{},
|
|
||||||
"x":-494,
|
|
||||||
"y":16780,
|
|
||||||
"width":260,
|
|
||||||
"height":60
|
|
||||||
},
|
|
||||||
{"id":"7e5aafa735602f6c","type":"text","text":"# 1. 17. ( 토 )","x":1520,"y":17081,"width":380,"height":60,"color":"#0011ff"},
|
{"id":"7e5aafa735602f6c","type":"text","text":"# 1. 17. ( 토 )","x":1520,"y":17081,"width":380,"height":60,"color":"#0011ff"},
|
||||||
{"id":"2456a354ee4f6639","type":"text","text":"# 2026. 1. 15. ( 목 )","x":712,"y":17081,"width":404,"height":60},
|
|
||||||
{"id":"502edc0d503de833","type":"text","text":"# 1. 13. ( 화 ) ","x":-92,"y":17081,"width":399,"height":60},
|
|
||||||
{"id":"0418ca3bde23c9ce","type":"text","text":"# 1. 14. ( 수 ) ","x":303,"y":17081,"width":409,"height":60},
|
|
||||||
{"id":"18599e4145524edb","type":"text","text":"# 1. 12. ( 월 )","x":-500,"y":17081,"width":409,"height":60},
|
|
||||||
{
|
{
|
||||||
"id":"3368df33f713f877",
|
"id":"3368df33f713f877",
|
||||||
"type":"text",
|
"type":"text",
|
||||||
@@ -1935,6 +1710,90 @@
|
|||||||
"height":60
|
"height":60
|
||||||
},
|
},
|
||||||
{"id":"3c8a637ab7de66bd","type":"text","text":"- [ ] 당직근무","x":1520,"y":17141,"width":380,"height":60},
|
{"id":"3c8a637ab7de66bd","type":"text","text":"- [ ] 당직근무","x":1520,"y":17141,"width":380,"height":60},
|
||||||
|
{"id":"adf17c4a04f03e39","type":"text","text":"# 1. 5. ( 월 )","x":-494,"y":16720,"width":409,"height":60},
|
||||||
|
{"id":"e8c7e9ac898f158e","type":"text","text":"# 12. 30. ( 화 ) ","x":-90,"y":16420,"width":399,"height":60},
|
||||||
|
{"id":"f2ca8fae1b695873","type":"text","text":"- [ ] 당직근무","x":-90,"y":16480,"width":399,"height":50},
|
||||||
|
{"id":"aa8027f65819cda6","type":"text","text":"# 1. 6. ( 화 ) ","x":-85,"y":16720,"width":399,"height":60},
|
||||||
|
{"id":"c2944f832283822a","type":"text","text":"# 12. 29. ( 월 )","x":-499,"y":16420,"width":409,"height":60},
|
||||||
|
{
|
||||||
|
"id":"3a9626006f771473",
|
||||||
|
"type":"text",
|
||||||
|
"text":" - [ ] 25년 소방계획서 작성결과 통보",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":16530,
|
||||||
|
"width":808,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"addd0c07fae33c36",
|
||||||
|
"type":"text",
|
||||||
|
"text":"Tf현장확인/토의,~30,유재형",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-494,
|
||||||
|
"y":16780,
|
||||||
|
"width":260,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{"id":"502edc0d503de833","type":"text","text":"# 1. 13. ( 화 ) ","x":-92,"y":17081,"width":399,"height":60},
|
||||||
|
{"id":"0418ca3bde23c9ce","type":"text","text":"# 1. 14. ( 수 ) ","x":303,"y":17081,"width":409,"height":60},
|
||||||
|
{"id":"18599e4145524edb","type":"text","text":"# 1. 12. ( 월 )","x":-500,"y":17081,"width":409,"height":60},
|
||||||
|
{
|
||||||
|
"id":"8a48bb0ad5d1b8a4",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 26년 소방계획서 공문보고, 출력물(양면) 제출,유재형",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-494,
|
||||||
|
"y":16120,
|
||||||
|
"width":409,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"5ce3bc84326ed106",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 26년 장비 예방정비 계획표 입력,~26,원정완",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":16180,
|
||||||
|
"width":2020,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{"id":"d774d3ed75270acf","type":"text","text":"# 12. 31. ( 수 ) ","x":309,"y":16420,"width":409,"height":60},
|
||||||
|
{
|
||||||
|
"id":"a4f65e136e9b90cd",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 26년 재활용 자원매각 계약서 심의 후 결과보고,신상이, ~31",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-494,
|
||||||
|
"y":16590,
|
||||||
|
"width":1134,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"287d550949875bd9",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 공간력 사업추진 소요보고,~31, 유재형,",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-500,
|
||||||
|
"y":16650,
|
||||||
|
"width":1212,
|
||||||
|
"height":70
|
||||||
|
},
|
||||||
|
{"id":"117e25b351f3d2bc","type":"text","text":"- [ ] 근무휴식","x":309,"y":16480,"width":409,"height":50},
|
||||||
|
{"id":"f10cd26fe462eb73","type":"text","text":"# 1. 7. ( 수 ) ","x":309,"y":16720,"width":409,"height":60},
|
||||||
|
{"id":"638dcbd292424977","type":"text","text":"# 2026. 1. 1. ( 목 )","x":718,"y":16420,"width":404,"height":60,"color":"1"},
|
||||||
|
{"id":"96a963d0474dfba7","type":"text","text":"# 2026. 1. 8. ( 목 )","x":718,"y":16720,"width":404,"height":60},
|
||||||
|
{"id":"2456a354ee4f6639","type":"text","text":"# 2026. 1. 15. ( 목 )","x":712,"y":17081,"width":404,"height":60},
|
||||||
|
{
|
||||||
|
"id":"e5f0cf0bd07871f1",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 판초우의 교체 소요 파악,~29,박형주",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-500,
|
||||||
|
"y":16240,
|
||||||
|
"width":1560,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id":"35616196b00ebf96",
|
"id":"35616196b00ebf96",
|
||||||
"type":"text",
|
"type":"text",
|
||||||
@@ -1944,7 +1803,148 @@
|
|||||||
"y":16300,
|
"y":16300,
|
||||||
"width":409,
|
"width":409,
|
||||||
"height":50
|
"height":50
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"id":"7632cbecf133635e",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] [[전투장비지휘검열]] 후속조치",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":16060,
|
||||||
|
"width":409,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"b15297ff20881dca",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] [[동절기 채난유류(등유) 위탁보관, 수불]],~26.3.15,김용대",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":16000,
|
||||||
|
"width":414,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"c6cd0ac8c7319495",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 부대야전정비지시서 현횐ㅇ(미완결)처리",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":15940,
|
||||||
|
"width":414,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"f8e1a3382c3e3e4e",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 본부중대 멀티탭 설치 현황 합철",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":15880,
|
||||||
|
"width":414,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"b93656d41b466896",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 수통클린 세척,1,2교육대 636,800,한승민,~31",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":309,
|
||||||
|
"y":15880,
|
||||||
|
"width":409,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"785a1545c87d4753",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 본부중대 보일러실 온풍기 추가 수정",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-499,
|
||||||
|
"y":15820,
|
||||||
|
"width":414,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"87086b245a59b199",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 보급,통가솔린두입구,플라스틱,10개,화인찬,김용대,1500,4번창고",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":-107,
|
||||||
|
"y":15820,
|
||||||
|
"width":421,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"8e165c613d791ff3",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 25년 치장물자 실셈 재물조사 후 결산 추진 지시,조태숙",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":309,
|
||||||
|
"y":15820,
|
||||||
|
"width":409,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{"id":"4bc34dd3a8c3ef44","type":"text","text":"# 12.23(화) ","x":-85,"y":15760,"width":399,"height":60},
|
||||||
|
{"id":"871723bf627c4aa3","type":"text","text":"# 12.24(수) ","x":309,"y":15760,"width":409,"height":60},
|
||||||
|
{"id":"cb181c2f3d7f06e2","type":"text","text":"# 12.22(월)","x":-494,"y":15760,"width":409,"height":60},
|
||||||
|
{"id":"8fc3ca54ea18b843","type":"text","text":"# 12.25(목)","x":718,"y":15760,"width":404,"height":60,"color":"1"},
|
||||||
|
{
|
||||||
|
"id":"719a08b28d4a3c2a",
|
||||||
|
"type":"text",
|
||||||
|
"text":"# 12.26(금)",
|
||||||
|
"styleAttributes":{
|
||||||
|
"border":null
|
||||||
|
},
|
||||||
|
"x":1122,
|
||||||
|
"y":15760,
|
||||||
|
"width":404,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"adf37e306dd3892d",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] [[간부필수교육]] 관리",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":1122,
|
||||||
|
"y":15820,
|
||||||
|
"width":399,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"6025294eb7304d85",
|
||||||
|
"type":"text",
|
||||||
|
"text":"- [ ] 전투장비지휘검열 후속조치계혹고고,원정욀",
|
||||||
|
"styleAttributes":{},
|
||||||
|
"x":1122,
|
||||||
|
"y":15880,
|
||||||
|
"width":399,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"379f515c3e778b70",
|
||||||
|
"type":"text",
|
||||||
|
"text":"# 2026. 1. 2. ( 금 )",
|
||||||
|
"styleAttributes":{
|
||||||
|
"border":null
|
||||||
|
},
|
||||||
|
"x":1122,
|
||||||
|
"y":16420,
|
||||||
|
"width":404,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":"84ef4bfe943c7a64",
|
||||||
|
"type":"text",
|
||||||
|
"text":"# 2026. 1. 9. ( 금 )",
|
||||||
|
"styleAttributes":{
|
||||||
|
"border":null
|
||||||
|
},
|
||||||
|
"x":1122,
|
||||||
|
"y":16720,
|
||||||
|
"width":404,
|
||||||
|
"height":60
|
||||||
|
},
|
||||||
|
{"id":"bbcf5864b29504a7","type":"text","text":"- [ ] 잔금일(휴가써야됨)","x":1122,"y":16780,"width":404,"height":50,"color":"1"}
|
||||||
],
|
],
|
||||||
"edges":[
|
"edges":[
|
||||||
{"id":"0770ebab68805d50","toFloating":false,"fromNode":"61759ae0f21ff868","fromSide":"bottom","toNode":"0ec5b12ac275d216","toSide":"top"},
|
{"id":"0770ebab68805d50","toFloating":false,"fromNode":"61759ae0f21ff868","fromSide":"bottom","toNode":"0ec5b12ac275d216","toSide":"top"},
|
||||||
|
|||||||
219
Obsidian-Tasks-Calendar-main/README-1.md
Normal file
219
Obsidian-Tasks-Calendar-main/README-1.md
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|

|
||||||
219
Obsidian-Tasks-Calendar-main/README.md
Normal file
219
Obsidian-Tasks-Calendar-main/README.md
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|

|
||||||
10
Obsidian-Tasks-Calendar-main/tasksCalendar/demo_file-1.md
Normal file
10
Obsidian-Tasks-Calendar-main/tasksCalendar/demo_file-1.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
cssclasses:
|
||||||
|
- dashboard
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```dataviewjs
|
||||||
|
await dv.view("tasksCalendar", {pages: "", view: "week", firstDayOfWeek: "1", options: "style1"})
|
||||||
|
```
|
||||||
10
Obsidian-Tasks-Calendar-main/tasksCalendar/demo_file.md
Normal file
10
Obsidian-Tasks-Calendar-main/tasksCalendar/demo_file.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
cssclasses:
|
||||||
|
- dashboard
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```dataviewjs
|
||||||
|
await dv.view("tasksCalendar", {pages: "", view: "week", firstDayOfWeek: "1", options: "style1"})
|
||||||
|
```
|
||||||
722
Obsidian-Tasks-Calendar-main/tasksCalendar/view-1.css
Normal file
722
Obsidian-Tasks-Calendar-main/tasksCalendar/view-1.css
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
.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; }
|
||||||
702
Obsidian-Tasks-Calendar-main/tasksCalendar/view-1.js
Normal file
702
Obsidian-Tasks-Calendar-main/tasksCalendar/view-1.js
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
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("'", "'");
|
||||||
|
var taskPath = obj.link.path.replace("'", "'");
|
||||||
|
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+" "+noteFilename } else { noteFilename = taskIcon+" "+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);
|
||||||
|
};
|
||||||
|
};
|
||||||
722
Obsidian-Tasks-Calendar-main/tasksCalendar/view.css
Normal file
722
Obsidian-Tasks-Calendar-main/tasksCalendar/view.css
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
.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; }
|
||||||
702
Obsidian-Tasks-Calendar-main/tasksCalendar/view.js
Normal file
702
Obsidian-Tasks-Calendar-main/tasksCalendar/view.js
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
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("'", "'");
|
||||||
|
var taskPath = obj.link.path.replace("'", "'");
|
||||||
|
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+" "+noteFilename } else { noteFilename = taskIcon+" "+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);
|
||||||
|
};
|
||||||
|
};
|
||||||
4
README.md
Normal file
4
README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# choibk
|
||||||
|
|
||||||
|
일단 성공, 사진도 보내지고..<br>
|
||||||
|
2025.11.9(일) 아침 824분 성공. 하지만 모든 자료가 날라갔다
|
||||||
3
ReadItLater Inbox/Note 2025-03-23 05-20-45-1.md
Normal file
3
ReadItLater Inbox/Note 2025-03-23 05-20-45-1.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[[ReadItLater]] [[Textsnippet]]
|
||||||
|
|
||||||
|
203.254.163.74
|
||||||
3
ReadItLater Inbox/Note 2025-03-23 05-20-45.md
Normal file
3
ReadItLater Inbox/Note 2025-03-23 05-20-45.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[[ReadItLater]] [[Textsnippet]]
|
||||||
|
|
||||||
|
203.254.163.74
|
||||||
3
ReadItLater Inbox/Note 2025-03-23 05-20-54-1.md
Normal file
3
ReadItLater Inbox/Note 2025-03-23 05-20-54-1.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[[ReadItLater]] [[Textsnippet]]
|
||||||
|
|
||||||
|
203.254.163.74
|
||||||
3
ReadItLater Inbox/Note 2025-03-23 05-20-54.md
Normal file
3
ReadItLater Inbox/Note 2025-03-23 05-20-54.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[[ReadItLater]] [[Textsnippet]]
|
||||||
|
|
||||||
|
203.254.163.74
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [(1 hour) The Legend of Ashitaka - Princess Mononoke OST (Lull and Relax Arranged)](https://youtube.com/watch?v=53tW43gG-5M&feature=shared)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/53tW43gG-5M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [(50분 핵심 마인드셋) 지금부터 2년간 '이렇게' 살면 인생 알아서 바뀝니다.](https://youtube.com/watch?v=Nls4_O06-MU&si=Tf8GorBGFOEe-yS8)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Nls4_O06-MU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [(50분 핵심 마인드셋) 지금부터 2년간 '이렇게' 살면 인생 알아서 바뀝니다.](https://youtube.com/watch?v=Nls4_O06-MU&si=Tf8GorBGFOEe-yS8)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Nls4_O06-MU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [24년 하반기 군무원 경채 면접 준비전략- #경채면접기출#경채면접준비방법#경채합격전략](https://youtu.be/WvFwl1cwkqk?si=vTDpGKN5DvTbEfsF)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WvFwl1cwkqk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [24년 하반기 군무원 경채 면접 준비전략- #경채면접기출#경채면접준비방법#경채합격전략](https://youtu.be/WvFwl1cwkqk?si=vTDpGKN5DvTbEfsF)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WvFwl1cwkqk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [4번째 불합격 | 장수생의 수험끝, 새로운시작 | 나는 나의 시간들앞에 한치의 부끄러움이 없다! #취업준비생 #불합격#동기부여#장수생#수험끝](https://youtube.com/watch?v=5KOf3pCKXgQ&si=EplYcc5LVmp-EZW2)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/5KOf3pCKXgQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [Clair de Lune (Extended)](https://youtube.com/watch?v=ea2WoUtbzuw&si=urkW_zE9cZNmzlee)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ea2WoUtbzuw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
|
#공부
|
||||||
6
ReadItLater Inbox/Youtube - Clair de Lune (Extended).md
Normal file
6
ReadItLater Inbox/Youtube - Clair de Lune (Extended).md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [Clair de Lune (Extended)](https://youtube.com/watch?v=ea2WoUtbzuw&si=urkW_zE9cZNmzlee)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ea2WoUtbzuw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
|
#공부
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [Clair de Lune (Studio Version)](https://youtube.com/watch?v=X-Xxqt6Xdio&si=_6Hq5SKKxNnWzo9i)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/X-Xxqt6Xdio" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [Clair de Lune (Studio Version)](https://youtube.com/watch?v=X-Xxqt6Xdio&si=_6Hq5SKKxNnWzo9i)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/X-Xxqt6Xdio" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# ["IQ 낮아도 됩니다." 공부한 것을 100% 흡수하는 방법 (박문호 박사 통합본)](https://youtu.be/KHr7A0YJuRk?si=F1Ipol0NaCBq2GL_)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KHr7A0YJuRk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# ["IQ 낮아도 됩니다." 공부한 것을 100% 흡수하는 방법 (박문호 박사 통합본)](https://youtu.be/KHr7A0YJuRk?si=F1Ipol0NaCBq2GL_)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KHr7A0YJuRk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [[2022 최고의 플러그인] 할 일(Task, To do) 관리를 자동화 해주는 플러그인](https://youtu.be/KH_P3GKtS1k?si=JC-HJiSFA3hjnzKB)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KH_P3GKtS1k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[티아고 포르테, 닉마일로, 토마스프랭크, 알버트 아인슈타인]] [[Youtube]]
|
||||||
|
|
||||||
|
# [[국내 유일] 개인지식관리 / 생산성 방법론 이렇게 많았나? GTD, 세컨드 브레인, 제텔카스텐 등 모든 방법론 총집합 ★](https://youtube.com/watch?v=RyZzJb3QFVU&si=MX7Ej8J-rDESqyRL)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/RyZzJb3QFVU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [[소확행부동산]부동산전자계약 어렵지 않아요(부동산전자계약3분완성)](https://youtu.be/CDNzvRe12uo?si=b2rW3FYvmTg8rFX4)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/CDNzvRe12uo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [[소확행부동산]부동산전자계약 어렵지 않아요(부동산전자계약3분완성)](https://youtu.be/CDNzvRe12uo?si=b2rW3FYvmTg8rFX4)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/CDNzvRe12uo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [[지식뉴스] "연금개혁안, 27년 만에 정면돌파 선택했다"...정부가 빠르게 50대 부담 늘린 이유 (ft.조동찬 기자, 전영수 교수) / SBS / 교양이를 부탁해](https://youtube.com/watch?v=gACoVdcxm_I&si=gCyIYYFPVJS56qlm)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/gACoVdcxm_I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 검색 🔎, 가장 쉬운 지식 접근법-1.md
Normal file
5
ReadItLater Inbox/Youtube - 검색 🔎, 가장 쉬운 지식 접근법-1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [검색 🔎, 가장 쉬운 지식 접근법](https://youtu.be/KZkBdaJpQ-c?si=zdhEQZMBYUD826A7)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KZkBdaJpQ-c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 검색 🔎, 가장 쉬운 지식 접근법.md
Normal file
5
ReadItLater Inbox/Youtube - 검색 🔎, 가장 쉬운 지식 접근법.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [검색 🔎, 가장 쉬운 지식 접근법](https://youtu.be/KZkBdaJpQ-c?si=zdhEQZMBYUD826A7)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KZkBdaJpQ-c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공무원 기출문제 공부법 - 공시생은 시간이 금! 줄이는 공부를 하자!](https://youtu.be/0P-4PeN_GFo?si=ESFlusPezp6W8Cl-)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/0P-4PeN_GFo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공무원 기출문제 공부법 - 공시생은 시간이 금! 줄이는 공부를 하자!](https://youtu.be/0P-4PeN_GFo?si=ESFlusPezp6W8Cl-)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/0P-4PeN_GFo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공부 못하는 애들 특 |영어단어 제발 이렇게 외우세요](https://youtube.com/shorts/j9dSYULCbKI?si=o9tuOapdQOQx-VQq)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/j9dSYULCbKI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공부를 죽을만큼 하기 싫을때 쓰는 방법 ft정승제](https://youtube.com/shorts/AJGTIjnNakQ?si=i8CwfaxGlfl8N2-T)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/AJGTIjnNakQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공부를 죽을만큼 하기 싫을때 쓰는 방법 ft정승제](https://youtube.com/shorts/AJGTIjnNakQ?si=i8CwfaxGlfl8N2-T)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/AJGTIjnNakQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공부법은 3가지만 알면 끝입니다. (80분 편집본 영상)](https://youtube.com/watch?v=2DRhRmsmZMU&si=W5b1L9pyxWTv4OHW)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/2DRhRmsmZMU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [공부법은 3가지만 알면 끝입니다. (80분 편집본 영상)](https://youtube.com/watch?v=2DRhRmsmZMU&si=W5b1L9pyxWTv4OHW)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/2DRhRmsmZMU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [뇌효율 잡는 의대생 암기법 【motemote|#shorts 】](https://youtube.com/shorts/tOoBE1J-pUk?si=Y3CRjPiIOhlznpWa)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/tOoBE1J-pUk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [뇌효율 잡는 의대생 암기법 【motemote|#shorts 】](https://youtube.com/shorts/tOoBE1J-pUk?si=Y3CRjPiIOhlznpWa)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/tOoBE1J-pUk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [당신의 의지가 약한 게 아니었다 #명언 #철학 #동기부여 #자기계발](https://youtube.com/shorts/fR9vV8qESQc?si=PlzfMfEOnJlAI3u4)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/fR9vV8qESQc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [당신의 의지가 약한 게 아니었다 #명언 #철학 #동기부여 #자기계발](https://youtube.com/shorts/fR9vV8qESQc?si=PlzfMfEOnJlAI3u4)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/fR9vV8qESQc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [당신의 체력을 비약적으로 상승시키는 3가지 방법](https://youtu.be/Y8K_S8_-Dl0?si=eaMSGx1bIWapGOjP)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Y8K_S8_-Dl0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [당신의 체력을 비약적으로 상승시키는 3가지 방법](https://youtu.be/Y8K_S8_-Dl0?si=eaMSGx1bIWapGOjP)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Y8K_S8_-Dl0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [독기 품고 딱 1년만 미쳐봐라 장담하는데 인생이 바뀔거다.. #쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/Cbxs9pBsC3E?si=lLJ7Eo-hjRm761TZ)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Cbxs9pBsC3E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [뒤늦게 시험을 준비하시는 분들에게 (직장인 공부법 풀영상)](https://youtu.be/czHzTlNZl90?si=Qb8jbjKYGh0uD-4m)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/czHzTlNZl90" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [뒤늦게 시험을 준비하시는 분들에게 (직장인 공부법 풀영상)](https://youtu.be/czHzTlNZl90?si=Qb8jbjKYGh0uD-4m)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/czHzTlNZl90" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 때로는 죽어야 산다-1.md
Normal file
5
ReadItLater Inbox/Youtube - 때로는 죽어야 산다-1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [때로는 죽어야 산다](https://youtube.com/shorts/xq4e-S5EXKk?si=QVrbfMvuQVe0fKQn)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/xq4e-S5EXKk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 때로는 죽어야 산다.md
Normal file
5
ReadItLater Inbox/Youtube - 때로는 죽어야 산다.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [때로는 죽어야 산다](https://youtube.com/shorts/xq4e-S5EXKk?si=QVrbfMvuQVe0fKQn)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/xq4e-S5EXKk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 라마의 환생이 알려주는 ‘행복한 하루’ 🤫-1.md
Normal file
5
ReadItLater Inbox/Youtube - 라마의 환생이 알려주는 ‘행복한 하루’ 🤫-1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [라마의 환생이 알려주는 ‘행복한 하루’ 🤫](https://youtube.com/shorts/84LKIr5Dims?si=1aC6zpWcFr0Npr2Q)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/84LKIr5Dims" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 라마의 환생이 알려주는 ‘행복한 하루’ 🤫.md
Normal file
5
ReadItLater Inbox/Youtube - 라마의 환생이 알려주는 ‘행복한 하루’ 🤫.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [라마의 환생이 알려주는 ‘행복한 하루’ 🤫](https://youtube.com/shorts/84LKIr5Dims?si=1aC6zpWcFr0Npr2Q)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/84LKIr5Dims" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [러닝 달리기 자세 3단계 방법 (ft.포즈 미드풋 만들기)](https://youtu.be/3j0z-h0UTqc?si=Q33WGhmmer6xJAz5)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/3j0z-h0UTqc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [러닝 달리기 자세 3단계 방법 (ft.포즈 미드풋 만들기)](https://youtu.be/3j0z-h0UTqc?si=Q33WGhmmer6xJAz5)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/3j0z-h0UTqc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [미드풋 감각 쉽게 익히는 방법 (미드풋을 만드는 동작) #미드풋 #자세 #교정](https://youtu.be/wKtTbcDqSTM?si=pbMizzTSrhR1MWjE)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/wKtTbcDqSTM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [미드풋 감각 쉽게 익히는 방법 (미드풋을 만드는 동작) #미드풋 #자세 #교정](https://youtu.be/wKtTbcDqSTM?si=pbMizzTSrhR1MWjE)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/wKtTbcDqSTM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [보자마자 오열했다..레전드 명언이다..#쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/3dTdJnr47Vk?si=PS2_A1f51jIGVtAA)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/3dTdJnr47Vk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [부동산 계약서(월세계약서/전세계약서) 작성할때 봐야할 꿀팁!](https://youtu.be/gGTGlXZvY8U?si=FiufX7su44aBxydG)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/gGTGlXZvY8U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [부동산 계약서(월세계약서/전세계약서) 작성할때 봐야할 꿀팁!](https://youtu.be/gGTGlXZvY8U?si=FiufX7su44aBxydG)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/gGTGlXZvY8U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [순경 3개월 합격자의 기출 회독 영상 (형소법)](https://youtu.be/C3vTEmcjP8I?si=K74ymwPoxHHvaEXX)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/C3vTEmcjP8I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [순경 3개월 합격자의 기출 회독 영상 (형소법)](https://youtu.be/C3vTEmcjP8I?si=K74ymwPoxHHvaEXX)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/C3vTEmcjP8I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [시험에서 1% 최상위 점수를 받는 1% 공부법](https://youtube.com/watch?v=9tFUhDLrih4&si=Oe-UiDDLGYxRgacV)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/9tFUhDLrih4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 시험에서 1% 최상위 점수를 받는 1% 공부법.md
Normal file
5
ReadItLater Inbox/Youtube - 시험에서 1% 최상위 점수를 받는 1% 공부법.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [시험에서 1% 최상위 점수를 받는 1% 공부법](https://youtube.com/watch?v=9tFUhDLrih4&si=Oe-UiDDLGYxRgacV)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/9tFUhDLrih4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [쓰르라미 울 적에 (When They Cry) OST - You (Piano Cover)](https://youtube.com/watch?v=bwQP4Ynr9_s&si=WuTNLiTGfEm-F21_)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/bwQP4Ynr9_s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [쓰르라미 울 적에 (When They Cry) OST - You (Piano Cover)](https://youtube.com/watch?v=bwQP4Ynr9_s&si=WuTNLiTGfEm-F21_)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/bwQP4Ynr9_s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# ["안녕하세요 X밥이에요" 라고 인사 한다는 양익준의 심각한 상태💦 자존감을 지키는 방법 #체크리스트](https://youtube.com/watch?v=GPOeEVv9f4A&si=U46srDqAIhL_UNT6)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/GPOeEVv9f4A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [얼마나 필요할까? 자금조달 프로세스 최신 총정리 | 흥청망청](https://youtube.com/watch?v=lTQzluV8UCQ&si=avHEJRvBp4xCJLt9)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/lTQzluV8UCQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [얼마나 필요할까? 자금조달 프로세스 최신 총정리 | 흥청망청](https://youtube.com/watch?v=lTQzluV8UCQ&si=avHEJRvBp4xCJLt9)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/lTQzluV8UCQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [옵시디언 MOC, 대시보드 홈페이지 만들기, 인덱스 노트](https://youtu.be/JknCCe1k9UY?si=SXtd-9gxfDAb-b31)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/JknCCe1k9UY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [옵시디언 MOC, 대시보드 홈페이지 만들기, 인덱스 노트](https://youtu.be/JknCCe1k9UY?si=SXtd-9gxfDAb-b31)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/JknCCe1k9UY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [이 10가지 못고치면 인생이 나락간다.. #쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/bhlxrOddY9I?si=-Hvs8uHsyD_NNOh-)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/bhlxrOddY9I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [이것만 친한 친구에게도 죽을때까지 숨겨야 하는 것.. #쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/iPNubn5WOBg?si=2-4Z3oqSK78pUsGK)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/iPNubn5WOBg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 이렇게 해보세요 슬프거나 짜증날 때-1.md
Normal file
5
ReadItLater Inbox/Youtube - 이렇게 해보세요 슬프거나 짜증날 때-1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [이렇게 해보세요 슬프거나 짜증날 때](https://youtube.com/shorts/e9JABrHI2Ok?si=7aSx86TYRxhKVVT9)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/e9JABrHI2Ok" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 이렇게 해보세요 슬프거나 짜증날 때.md
Normal file
5
ReadItLater Inbox/Youtube - 이렇게 해보세요 슬프거나 짜증날 때.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [이렇게 해보세요 슬프거나 짜증날 때](https://youtube.com/shorts/e9JABrHI2Ok?si=7aSx86TYRxhKVVT9)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/e9JABrHI2Ok" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [인강 없이 7개월 동안 이윤규 공부법으로 합격했습니다. (이현우 순경 1부)](https://youtu.be/7Y3_VpH72ps?si=q8hoylBxZJtfNfKB)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/7Y3_VpH72ps" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [인강 없이 7개월 동안 이윤규 공부법으로 합격했습니다. (이현우 순경 1부)](https://youtu.be/7Y3_VpH72ps?si=q8hoylBxZJtfNfKB)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/7Y3_VpH72ps" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [주택담보대출 상환은 이렇게 하는게 가장 이득입니다~](https://youtube.com/watch?v=WBvcQcRmyZ8&si=NVC_Vb2PNAP7zp1b)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WBvcQcRmyZ8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [주택담보대출 상환은 이렇게 하는게 가장 이득입니다~](https://youtube.com/watch?v=WBvcQcRmyZ8&si=NVC_Vb2PNAP7zp1b)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WBvcQcRmyZ8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [지식관리 끝판왕 옵시디언 설치 및 기본 설명, 세컨드 브레인 구축](https://youtu.be/iWvtk9RsU8Q?si=KHJIrTAbFE79eo1k)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/iWvtk9RsU8Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [지식관리 끝판왕 옵시디언 설치 및 기본 설명, 세컨드 브레인 구축](https://youtu.be/iWvtk9RsU8Q?si=KHJIrTAbFE79eo1k)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/iWvtk9RsU8Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [짐노페디 1번 (Gymnopédie No. 1) 1시간 연속재생/화면 꺼짐](https://youtube.com/watch?v=12phiGs9OlE&si=vF_B0aASyeRcWJt-)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/12phiGs9OlE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
|
#공부
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [짐노페디 1번 (Gymnopédie No. 1) 1시간 연속재생/화면 꺼짐](https://youtube.com/watch?v=12phiGs9OlE&si=vF_B0aASyeRcWJt-)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/12phiGs9OlE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
|
#공부
|
||||||
5
ReadItLater Inbox/Youtube - 집수리 요구하는 집주인 대응법-1.md
Normal file
5
ReadItLater Inbox/Youtube - 집수리 요구하는 집주인 대응법-1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [집수리 요구하는 집주인 대응법](https://youtube.com/shorts/n853H7b6Kz0?si=rjfSShvx9zexhf-f)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/n853H7b6Kz0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
5
ReadItLater Inbox/Youtube - 집수리 요구하는 집주인 대응법.md
Normal file
5
ReadItLater Inbox/Youtube - 집수리 요구하는 집주인 대응법.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [집수리 요구하는 집주인 대응법](https://youtube.com/shorts/n853H7b6Kz0?si=rjfSShvx9zexhf-f)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/n853H7b6Kz0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [착하게 살면 반드시 망한다 ..#쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/84tRfuG9Jrc?si=AavhIroGUPaYyAxU)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/84tRfuG9Jrc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [포즈와 미드풋 초보 러너 탈출 방법(ft. 러닝의 1단계)#포즈 #미드풋 #초보러너탈출 포즈, 낙하, 당기기, 미드풋을 구사하기 힘드신 분들을 위해 단계별로 알려드리는 영상입니다](https://youtu.be/R9DukpDw4Bo?si=KdDJ1NTfnZJojgtT)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/R9DukpDw4Bo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [하버드 도서관에 붙어있는 레전드 명언.. #쇼펜하우어 #니체 #석가모니 #맹자 #명언 #인생조언 #철학 #좋은글 #좋은말 #좋은글귀](https://youtube.com/shorts/u9AO_zwqJtg?si=m46tChoeOmGAuS8s)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/u9AO_zwqJtg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [하버드대, 코넬대에서 권장하는 성과가 입증된 '진짜' 공부법 | ft.하버드대 교육심리 전공 [🧠일.공.심]](https://youtube.com/watch?v=QBCN9fRTRT0&si=cNKFdm8uV5sjAo90)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/QBCN9fRTRT0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [𝐏𝐥𝐚𝐲𝐥𝐢𝐬𝐭 멘탈훈련소 BEST 동기부여 모음](https://youtu.be/qngXahvw2ug?feature=shared)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/qngXahvw2ug" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[[ReadItLater]] [[Youtube]]
|
||||||
|
|
||||||
|
# [𝐏𝐥𝐚𝐲𝐥𝐢𝐬𝐭 멘탈훈련소 BEST 동기부여 모음](https://youtu.be/qngXahvw2ug?feature=shared)
|
||||||
|
|
||||||
|
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/qngXahvw2ug" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
0
ReadItLater-1.md
Normal file
0
ReadItLater-1.md
Normal file
0
ReadItLater.md
Normal file
0
ReadItLater.md
Normal file
BIN
Resized_20251127_141040.jpeg
Normal file
BIN
Resized_20251127_141040.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
Resized_20251127_141053.jpeg
Normal file
BIN
Resized_20251127_141053.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 991 KiB |
BIN
Resized_CamScanner 2024-03-14 13.25_1710390353206.jpeg
Normal file
BIN
Resized_CamScanner 2024-03-14 13.25_1710390353206.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user