Commit 130d9b2d4b5cccafdcbb5d697ab3007a90c9741a
/calendar : minimal year display
mixmix committed on 7/19/2018, 9:11:08 PMParent: 9b9ae32751d87f8c75ee8da7d23f22f5b9250a74
Files changed
app/page/calendar.js | added |
app/page/calendar.mcss | added |
router/sync/routes.js | changed |
app/page/calendar.js | |||
---|---|---|---|
@@ -1,0 +1,171 @@ | |||
1 … | +const nest = require('depnest') | ||
2 … | +const { h, Value, computed } = require('mutant') | ||
3 … | + | ||
4 … | +exports.gives = nest('app.page.calendar') | ||
5 … | + | ||
6 … | +exports.needs = nest({ | ||
7 … | +}) | ||
8 … | + | ||
9 … | +exports.create = (api) => { | ||
10 … | + return nest('app.page.calendar', calendarPage) | ||
11 … | + | ||
12 … | + function calendarPage (location) { | ||
13 … | + const cal = Cal() | ||
14 … | + | ||
15 … | + return h('CalendarPage', { title: '/calendar' }, cal) | ||
16 … | + } | ||
17 … | +} | ||
18 … | + | ||
19 … | +const MONTHS = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] | ||
20 … | +const DAYS = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ] | ||
21 … | + | ||
22 … | +function Cal () { | ||
23 … | + const year = Value(new Date().getFullYear()) | ||
24 … | + const today = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 1, 0) | ||
25 … | + | ||
26 … | + const root = computed(year, year => { | ||
27 … | + return h('Calendar', [ | ||
28 … | + Header(year), | ||
29 … | + MONTHS.map((month, i) => { | ||
30 … | + return h('div.month', [ | ||
31 … | + h('div.label', month.substr(0, 3)), | ||
32 … | + h('div.graph', [ | ||
33 … | + // Labels(), | ||
34 … | + Month(year, i) | ||
35 … | + ]) | ||
36 … | + ]) | ||
37 … | + }) | ||
38 … | + ]) | ||
39 … | + }) | ||
40 … | + | ||
41 … | + return root | ||
42 … | + | ||
43 … | + function Header (year) { | ||
44 … | + return h('div.header', [ | ||
45 … | + h('p.year', [ | ||
46 … | + year, | ||
47 … | + h('a', { 'ev-click': () => year.set(year() - 1) }, '-'), | ||
48 … | + h('a', { 'ev-click': () => year.set(year() + 1) }, '+') | ||
49 … | + ]) | ||
50 … | + // h('p.percentage', yearProgress(year)) | ||
51 … | + ]) | ||
52 … | + } | ||
53 … | + | ||
54 … | + // function yearProgress (year) { | ||
55 … | + // const diff = new Date() - new Date(year, 0, 1, 0) | ||
56 … | + // const progress = ((diff / 31536000000) * 100).toFixed(2) | ||
57 … | + // const yd = Math.abs((progress / 100).toFixed(2)) | ||
58 … | + | ||
59 … | + // return progress < 0 ? yd + ` YEARS AWAY` : progress > 100 ? yd + ` YEARS AGO` : progress + '%' | ||
60 … | + // } | ||
61 … | + | ||
62 … | + // function doLabels () { | ||
63 … | + // let html = '' | ||
64 … | + // let y = 0 | ||
65 … | + | ||
66 … | + // for (var i = 0; i < 7; i++) { | ||
67 … | + // y = (i * 14) | ||
68 … | + // html += `<text class="dayLabel" x="5" y='${y}' dy="10">${DAYS[i].substr(0, 1)}</text>` | ||
69 … | + // } | ||
70 … | + // return html | ||
71 … | + // } | ||
72 … | + | ||
73 … | + function Month (year, monthIndex) { | ||
74 … | + const monthLength = new Date(year, monthIndex + 1, 0).getDate() | ||
75 … | + // NOTE Date takes month as a monthIndex i.e. april = 3 | ||
76 … | + // and day = 0 goes back a day | ||
77 … | + const days = Array(monthLength).fill().map((_, i) => i + 1) | ||
78 … | + | ||
79 … | + const style = { | ||
80 … | + display: 'grid', | ||
81 … | + 'grid-gap': '.2rem' | ||
82 … | + } | ||
83 … | + | ||
84 … | + var date | ||
85 … | + var weekday | ||
86 … | + var week | ||
87 … | + var offset = getDay(new Date(year, monthIndex, 1)) - 1 | ||
88 … | + | ||
89 … | + return h('div', { style }, days.map(day => { | ||
90 … | + date = new Date(year, monthIndex, day) | ||
91 … | + weekday = getDay(date) | ||
92 … | + if (weekday === 0) weekday = 7 // urghh I want monday to be the start of the week | ||
93 … | + week = Math.ceil((day + offset) / 7) | ||
94 … | + | ||
95 … | + return h('div.day', { | ||
96 … | + attributes: { 'data-day': day }, | ||
97 … | + style: { | ||
98 … | + 'grid-row': `${weekday} / ${weekday + 1}`, | ||
99 … | + 'grid-column': `${week} / ${week + 1}` | ||
100 … | + } | ||
101 … | + }) | ||
102 … | + })) | ||
103 … | + } | ||
104 … | + | ||
105 … | + function getDay (date) { | ||
106 … | + const d = date.getDay() | ||
107 … | + return d === 0 ? 7 : d | ||
108 … | + | ||
109 … | + // Weeks run 0...6 (Sun - Sat) | ||
110 … | + // this shifts those days around by 1 | ||
111 … | + } | ||
112 … | + | ||
113 … | + function doMonth (moxsd ........ | ||
114 … | + .th) { | ||
115 … | + var html = '' | ||
116 … | + const monthLength = new Date(year, month + 1, 0).getDate() | ||
117 … | + let date = 0 | ||
118 … | + let x = 0 | ||
119 … | + let y = 0 | ||
120 … | + | ||
121 … | + while (date < monthLength) { | ||
122 … | + x += 14 | ||
123 … | + let week = 0 | ||
124 … | + | ||
125 … | + while (week < 7 && date !== monthLength) { | ||
126 … | + y = week * 14 | ||
127 … | + let day = new Date(year, month, date, 0) | ||
128 … | + let dotab = `tabIndex="0"` | ||
129 … | + | ||
130 … | + if (day.getDay() !== week) { | ||
131 … | + style = 'null' | ||
132 … | + dotab = '' | ||
133 … | + date-- | ||
134 … | + } else if (String(day) === String(today)) { | ||
135 … | + style = 'today' | ||
136 … | + } else if (day < today) { | ||
137 … | + style = 'gone' | ||
138 … | + } else if (day.getDay() === 5 || day.getDay() === 6) { | ||
139 … | + style = 'weekend' | ||
140 … | + } else { | ||
141 … | + style = 'day' | ||
142 … | + } | ||
143 … | + | ||
144 … | + html += `<rect id="square" class='${style}' x='${x}' y='${y}' title='${(date + 1) === 0 ? 'null' : DAYS[week] + ' ' + (date + 1)}' width="12px" height="12px" rx="2" ry="2" onclick=" | ||
145 … | + UpdateFooter(${year}, ${month}, ${(date + 1)}, ${week}, this)" onblur="" ${dotab}></rect>` | ||
146 … | + | ||
147 … | + week++ | ||
148 … | + date++ | ||
149 … | + } | ||
150 … | + } | ||
151 … | + return html | ||
152 … | + } | ||
153 … | +} | ||
154 … | + | ||
155 … | +function UpdateFooter (year, month, date, week, obj) { | ||
156 … | + obj.addEventListener('blur', () => { footer.innerHTML = '' }) | ||
157 … | + let diff = ((new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 0) - new Date(year, month, date)) / 86400000) | ||
158 … | + let num = Math.abs(diff).toFixed() | ||
159 … | + let calc | ||
160 … | + | ||
161 … | + diff < 0 ? calc = `In ${num} Day${num > 1 ? 's' : ''}.` : diff == 0 ? calc = `Today.` : calc = `${num} Day${num > 1 ? 's' : ''} ago.` | ||
162 … | + footer.innerHTML = `${MONTHS[month]} ${date}, ${DAYS[week]}. ${calc}` | ||
163 … | +} | ||
164 … | + | ||
165 … | +function getYear (diff) { | ||
166 … | + location.hash = parseInt(location.hash.replace('#', '')) + parseInt(diff) | ||
167 … | +} | ||
168 … | + | ||
169 … | +// window.onhashchange = function () { | ||
170 … | +// Year(parseInt(location.hash.replace('#', ''))) | ||
171 … | +// } |
app/page/calendar.mcss | ||
---|---|---|
@@ -1,0 +1,115 @@ | ||
1 … | +CalendarPage { | |
2 … | + width: 100% | |
3 … | + | |
4 … | + display: grid | |
5 … | + justify-content: center | |
6 … | +} | |
7 … | + | |
8 … | + | |
9 … | +Calendar { | |
10 … | + font-family: 'input_mono_regular', monospace | |
11 … | + text-transform: uppercase | |
12 … | + | |
13 … | + display: block | |
14 … | + height: 100% | |
15 … | + min-height: 400px | |
16 … | + width: 100% | |
17 … | + | |
18 … | + padding: 0 | |
19 … | + margin: 0 | |
20 … | + | |
21 … | + section { | |
22 … | + position: relative | |
23 … | + top: 50% | |
24 … | + margin: 0 auto | |
25 … | + user-select: none | |
26 … | + -webkit-user-select: none | |
27 … | + -ms-user-select: none | |
28 … | + -webkit-transform: translateY(-50%) | |
29 … | + -ms-transform: translateY(-50%) | |
30 … | + transform: translateY(-50%) | |
31 … | + text-align: center | |
32 … | + } | |
33 … | + | |
34 … | + div.header { | |
35 … | + margin: 0 10px 40px 10px | |
36 … | + text-align: left | |
37 … | + align-content: flex-start | |
38 … | + | |
39 … | + p.year { | |
40 … | + font-size: 40px | |
41 … | + font-weight: bold | |
42 … | + | |
43 … | + a { | |
44 … | + text-align: center | |
45 … | + color: #000 | |
46 … | + width: 30px | |
47 … | + display: inline-block | |
48 … | + margin-left: 10px | |
49 … | + | |
50 … | + :hover { | |
51 … | + color: #ffffff | |
52 … | + background: #000 | |
53 … | + cursor: pointer | |
54 … | + } | |
55 … | + } | |
56 … | + } | |
57 … | + | |
58 … | + p.percentage { | |
59 … | + font-size: 20px | |
60 … | + color: #8b8b8b | |
61 … | + } | |
62 … | + } | |
63 … | + | |
64 … | + div.month { | |
65 … | + margin: 10px | |
66 … | + display: inline-block | |
67 … | + /* width:100px */ | |
68 … | + /* height: 130px */ | |
69 … | + | |
70 … | + div.label { | |
71 … | + font-size: 20px | |
72 … | + font-weight: bold | |
73 … | + text-align: left | |
74 … | + margin-bottom: 5px | |
75 … | + } | |
76 … | + | |
77 … | + div.graph { | |
78 … | + | |
79 … | + div { | |
80 … | + div.day { | |
81 … | + background: #000 | |
82 … | + height: .8rem | |
83 … | + width: .8rem | |
84 … | + | |
85 … | + border-radius: .1rem | |
86 … | + } | |
87 … | + } | |
88 … | + } | |
89 … | + } | |
90 … | + | |
91 … | + | |
92 … | + /* p { margin: 0px; } */ | |
93 … | + | |
94 … | + /* svg.graph { color:white; width: 100%; height: 100px; } */ | |
95 … | + /* svg.graph text {font-family: 'input_mono_regular'; stroke:none; fill:#8b8b8b; font-size:14px; text-anchor: middle; } */ | |
96 … | + /* svg.graph text.dayLabel { font-size: 10px; } */ | |
97 … | + /* svg.graph rect { stroke:none; outline: none; } */ | |
98 … | + /* svg.graph rect:hover, rect:focus { fill: #ff1e00 !important; cursor:pointer; } */ | |
99 … | + | |
100 … | + /* svg.graph rect.null { fill: none; stroke: none;} */ | |
101 … | + /* svg.graph rect.today { fill:#ff1e00; } */ | |
102 … | + /* svg.graph rect.day { fill:#8b8b8b; } */ | |
103 … | + /* svg.graph rect.weekend { fill:#747474 } */ | |
104 … | + /* svg.graph rect.gone { fill:#000000 } */ | |
105 … | + /* svg.graph path { stroke-linecap: butt; stroke-dasharray: 1,1; fill:none; stroke:#333; stroke-width:13px } */ | |
106 … | + | |
107 … | + /* @media only screen and (min-width: 1440px) */ | |
108 … | + /* { section { width: 1440px; }} */ | |
109 … | + | |
110 … | + /* @media only screen and (max-width: 1440px) */ | |
111 … | + /* { section { width: 720px; }} */ | |
112 … | + | |
113 … | + /* @media only screen and (max-width: 720px) */ | |
114 … | + /* { section { width: 360px; }} */ | |
115 … | +} |
router/sync/routes.js | ||
---|---|---|
@@ -4,10 +4,11 @@ | ||
4 | 4 … | exports.gives = nest('router.sync.routes') |
5 | 5 … | |
6 | 6 … | exports.needs = nest({ |
7 | 7 … | 'app.page': { |
8 … | + 'calendar': 'first', | |
9 … | + 'blob': 'first', | |
8 | 10 … | 'errors': 'first', |
9 | - 'blob': 'first', | |
10 | 11 … | 'channel': 'first', |
11 | 12 … | 'imageSearch': 'first', |
12 | 13 … | 'notifications': 'first', |
13 | 14 … | 'posts': 'first', |
@@ -28,8 +29,9 @@ | ||
28 | 29 … | const pages = api.app.page |
29 | 30 … | |
30 | 31 … | // loc = location |
31 | 32 … | const routes = [ |
33 … | + [ loc => loc.page === 'calendar', pages.calendar ], | |
32 | 34 … | [ loc => loc.page === 'errors', pages.errors ], |
33 | 35 … | [ loc => loc.page === 'imageSearch', pages.imageSearch ], |
34 | 36 … | [ loc => loc.page === 'notifications', pages.notifications ], |
35 | 37 … | [ loc => loc.page === 'posts', pages.posts ], |
Built with git-ssb-web