UNPKG

hexo-theme-amazing

Version:

A simple, delicate, and modern theme for Hexo

175 lines (163 loc) 6.82 kB
const moment = require('moment'); const { Component, Fragment } = require('inferno'); const Paginator = require('hexo-component-inferno/lib/view/misc/paginator'); const ArticleMedia = require('hexo-component-inferno/lib/view/common/article_media'); module.exports = class extends Component { render() { const { config, page, site, helper } = this.props; const { url_for, my_cdn, __, date_xml, date } = helper; const language = page.lang || page.language || config.language; var nameMap = language.indexOf('zh') >= 0 ? 'cn' : 'en'; var titleText = language.indexOf('zh') >= 0 ? '文章贡献' : 'Post Calendar'; // ======================= calculate range. var startDate = moment().subtract(0.70, 'years'); var endDate = moment(); var rangeArr = '["' + startDate.format('YYYY-MM-DD') + '", "' + endDate.format('YYYY-MM-DD') + '"]'; // post and count map. var dateMap = new Map(); site.posts.forEach(function (post) { var date1 = post.date.format('YYYY-MM-DD'); var count = dateMap.get(date1); dateMap.set(date1, count == null || count == undefined ? 1 : count + 1); }); // loop the data for the current year, generating the number of post per day var i = 0; var datePosts = '['; var dayTime = 3600 * 24 * 1000; for (var time = startDate; time <= endDate; time += dayTime) { var date1 = moment(time).format('YYYY-MM-DD'); datePosts = (i === 0 ? datePosts + '["' : datePosts + ', ["') + date1 + '", ' + (dateMap.has(date1) ? dateMap.get(date1) : 0) + ']'; i++; } datePosts += ']'; // ======================= function renderArticleList(posts, year, month = null) { const time = moment([page.year, page.month ? page.month - 1 : null].filter(i => i !== null)); return <div> <h3 class="tag is-primary">{month === null ? year : time.locale(language).format('MMMM YYYY')}</h3> <div class="timeline"> {posts.map(post => { const categories = post.categories.map(category => ({ url: url_for(category.path), name: category.name })); return <ArticleMedia url={url_for(post.link || post.path)} title={post.title} date={date(post.date)} dateXml={date_xml(post.date)} categories={categories} thumbnail={post.thumbnail ? url_for(post.thumbnail) : null} />; })} </div> <br/> </div>; } const echartJsUrl = my_cdn(url_for("/js/echarts.min.js")); const js = `function loadEchart(){ if($("#post-calendar").length <= 0){ return; } $.getScript('${echartJsUrl}', function () { let myChart = echarts.init(document.getElementById('post-calendar')); let option = { title: { top: 0, text: '${titleText}', left: '42%', textStyle: { color: '#3C4858' } }, tooltip: { padding: 10, backgroundColor: '#555', borderColor: '#777', borderWidth: 1, formatter: function (obj) { var value = obj.value; return '<div style="font-size: 14px;">' + value[0] + ':' + value[1] + '</div>'; } }, visualMap: { show: true, showLabel: true, categories: [0, 1, 2, 3, 4], calculable: true, inRange: { symbol: 'rect', color: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'] }, itemWidth: 12, itemHeight: 12, orient: 'horizontal', left: '35%', bottom: 0 }, calendar: [{ left: 'center', range: ${rangeArr}, cellSize: [13, 13], splitLine: { show: false }, itemStyle: { color: '#196127', borderColor: '#fff', borderWidth: 2 }, yearLabel: { show: false }, monthLabel: { nameMap: '${nameMap}', fontSize: 11 }, dayLabel: { formatter: '{start} 1st', nameMap: '${nameMap}', fontSize: 11 } }], series: [{ type: 'heatmap', coordinateSystem: 'calendar', calendarIndex: 0, data: ${datePosts} }] }; myChart.setOption(option);})};loadEchart();`; let articleList; if (!page.year) { const years = {}; page.posts.each(p => { years[p.date.year()] = null; }); articleList = Object.keys(years).sort((a, b) => b - a).map(year => { const posts = page.posts.filter(p => p.date.year() === parseInt(year, 10)); return renderArticleList(posts, year, null); }); } else { articleList = renderArticleList(page.posts, page.year, page.month); } return <Fragment> <div className="card"> <div className="card-content"> <div style="post-calendar-pre"> <div id="post-calendar"></div> </div> <script type="text/javascript" src={my_cdn(url_for("/js/echarts.min.js"))}></script> <script type="text/javascript" dangerouslySetInnerHTML={{__html: js}}></script> {articleList} </div> </div> {page.total > 1 ? <Paginator current={page.current} total={page.total} baseUrl={page.base} path={config.pagination_dir} urlFor={url_for} prevTitle={__('common.prev')} nextTitle={__('common.next')} /> : null} </Fragment>; } };