Mend news reporting

This commit is contained in:
Ilya Ig. Petrov 2017-05-31 19:32:03 +05:00
parent dc1371063b
commit 6ed04d680a
2 changed files with 157 additions and 103 deletions

View File

@ -38,12 +38,21 @@ export default function getApp(theState) {
} }
async componentDidMount() { setNewsStatusTo(newsArr) {
this.setStatusTo(
<ol>
{newsArr.map(([title, url]) => (<li><a href={url}>{title}</a></li>))}
</ol>
);
}
async showNews() {
console.log('Did mount!');
const uiComDate = 'ui-last-comment-date'; const uiComDate = 'ui-last-comment-date';
const uiComEtag = 'ui-last-comments-etag'; const uiComEtag = 'ui-last-comments-etag';
const uiLastNews = 'ui-last-news'; const uiLastNewsArr = 'ui-last-news-arr';
const statusFromHash = this.state.hashParams.get('status'); const statusFromHash = this.state.hashParams.get('status');
if (statusFromHash) { if (statusFromHash) {
@ -65,8 +74,10 @@ export default function getApp(theState) {
headers: new Headers(headers), headers: new Headers(headers),
}; };
const ghUrl = `https://api.github.com/repos/edge-ware/edge-ware.github.io/issues/1/comments${query}`;
console.log(ghUrl);
const [comments, etag] = await fetch( const [comments, etag] = await fetch(
`https://api.github.com/repos/edge-ware/edge-ware.github.io/issues/1/comments${query}`, ghUrl,
params params
).then( ).then(
(res) => Promise.all([ (res) => Promise.all([
@ -75,130 +86,172 @@ export default function getApp(theState) {
]), ]),
(err) => { (err) => {
this.showErrors({message: 'Что-то не так с сетью. Не удалось достать новости.'}); this.showErrors({message: 'Не удалось достать новости: что-то не так с сетью.', wrapped: err});
return [false, false]; return [false, false];
} }
); );
console.log('RESP', comments, etag);
if (etag) { if (etag) {
localStorage[uiComEtag] = etag; localStorage[uiComEtag] = etag;
} }
if (!(comments && comments.length)) {
const news = localStorage[uiLastNews];
if (news) {
this.setStatusTo(news);
} else {
this.setStatusTo('У нас ничего нового.');
}
return;
}
const lastComment = comments.pop();
if (lastComment) {
const lastDate = lastComment.updated_at || lastComment.created_at;
localStorage[uiComDate] = lastDate;
const newsText = lastComment.body.split(/\r?\n/)[0].replace(/^\s*#+\s*/g, '');
localStorage[uiLastNews] = newsText;
this.setStatusTo(newsText);
}
} const ifNews = (() => {
showErrors(err, ...args/* ...warns, cb */) { if (!(comments && comments.length)) {
const news = JSON.parse(localStorage[uiLastNewsArr]);
const lastArg = args[args.length - 1]; if (news) {
const cb = (lastArg && typeof lastArg === 'function') this.setNewsStatusTo(news);
? args.pop() return true;
: () => {};
const warns = args;
const warningHtml = warns
.map(
(w) => w && w.message || ''
)
.filter( (m) => m )
.map( (m) => '✘ ' + m )
.join('<br/>');
let messageHtml = '';
if (err) {
let wrapped = err.wrapped;
messageHtml = err.message || '';
while( wrapped ) {
const deeperMsg = wrapped && wrapped.message;
if (deeperMsg) {
messageHtml = messageHtml + ' &gt; ' + deeperMsg;
} }
wrapped = wrapped.wrapped; return false;
} }
let minDate;
const news = [];
console.log('we have', comments);
comments.forEach((comment) => {
const curDate = comment.updated_at || comment.created_at;
const newsTitle = this.getNewsHeadline( comment.body );
if (newsTitle) {
if (!minDate || curDate <= minDate) {
minDate = curDate;
}
news.push([newsTitle, comment.html_url]);
}
});
if (!news.length) {
return false;
}
localStorage[uiComDate] = minDate;
console.log('New date!', minDate);
localStorage[uiLastNewsArr] = JSON.stringify(news);
this.setNewsStatusTo(news);
return true;
})();
if (!ifNews) {
this.setStatusTo('Ничего нового.');
}
}
componentDidMount() {
this.showNews();
}
getNewsHeadline(comBody) {
const headline = comBody.split(/\r?\n/)[0];
const ifOver = /#+\s*$/.test(headline);
if (ifOver) {
return false;
} }
messageHtml = messageHtml.trim(); return headline.replace(/^\s*#+\s*/g, '');
if (warningHtml) {
messageHtml = messageHtml ? messageHtml + '<br/>' + warningHtml : warningHtml; }
showErrors(err, ...args/* ...warns, cb */) {
const lastArg = args[args.length - 1];
const cb = (lastArg && typeof lastArg === 'function')
? args.pop()
: () => {};
const warns = args;
const warningHtml = warns
.map(
(w) => w && w.message || ''
)
.filter( (m) => m )
.map( (m) => '✘ ' + m )
.join('<br/>');
let messageHtml = '';
if (err) {
let wrapped = err.wrapped;
messageHtml = err.message || '';
while( wrapped ) {
const deeperMsg = wrapped && wrapped.message;
if (deeperMsg) {
messageHtml = messageHtml + ' &gt; ' + deeperMsg;
}
wrapped = wrapped.wrapped;
} }
this.setStatusTo(
(<span>
<span style="color:red">
{err ? <span><span class="emoji">🔥</span> Ошибка!</span> : 'Некритичная oшибка.'}
</span>
<br/>
<span style="font-size: 0.9em; color: darkred" dangerouslySetInnerHTML={{__html: messageHtml}}></span>
{' '}
{err && <a href="" onClick={(evt) => {
this.props.apis.errorHandlers.viewError('pup-ext-err', err);
evt.preventDefault();
}}>[Техн.детали]</a>}
</span>),
cb
);
} }
messageHtml = messageHtml.trim();
switchInputs(val) { if (warningHtml) {
messageHtml = messageHtml ? messageHtml + '<br/>' + warningHtml : warningHtml;
this.setState({
ifInputsDisabled: val === 'off' ? true : false,
});
} }
this.setStatusTo(
(<span>
<span style="color:red">
{err ? <span><span class="emoji">🔥</span> Ошибка!</span> : 'Некритичная oшибка.'}
</span>
<br/>
<span style="font-size: 0.9em; color: darkred" dangerouslySetInnerHTML={{__html: messageHtml}}></span>
{' '}
{err && <a href="" onClick={(evt) => {
conduct( this.props.apis.errorHandlers.viewError('pup-ext-err', err);
beforeStatus, operation, afterStatus, evt.preventDefault();
onSuccess = () => {}, onError = () => {}
) {
this.setStatusTo(beforeStatus); }}>[Техн.детали]</a>}
this.switchInputs('off'); </span>),
operation((err, res, ...warns) => { cb
);
warns = warns.filter( (w) => w ); }
if (err || warns.length) {
this.showErrors(err, ...warns);
} else {
this.setStatusTo(afterStatus);
}
this.switchInputs('on');
if (!err) {
onSuccess(res);
} else {
onError(err);
}
}); switchInputs(val) {
} this.setState({
ifInputsDisabled: val === 'off' ? true : false,
});
render(originalProps) { }
console.log('Render'); conduct(
beforeStatus, operation, afterStatus,
onSuccess = () => {}, onError = () => {}
) {
this.setStatusTo(beforeStatus);
this.switchInputs('off');
operation((err, res, ...warns) => {
warns = warns.filter( (w) => w );
if (err || warns.length) {
this.showErrors(err, ...warns);
} else {
this.setStatusTo(afterStatus);
}
this.switchInputs('on');
if (!err) {
onSuccess(res);
} else {
onError(err);
}
});
}
render(originalProps) {
console.log('Render');
const props = Object.assign({}, originalProps, { const props = Object.assign({}, originalProps, {
funs: { funs: {
setStatusTo: this.setStatusTo.bind(this), setStatusTo: this.setStatusTo.bind(this),
conduct: this.conduct.bind(this), conduct: this.conduct.bind(this),
showErrors: this.showErrors.bind(this), showErrors: this.showErrors.bind(this),
showNews: this.showNews.bind(this),
}, },
ifInputsDisabled: this.state.ifInputsDisabled, ifInputsDisabled: this.state.ifInputsDisabled,
hashParams: this.state.hashParams, hashParams: this.state.hashParams,

View File

@ -60,11 +60,12 @@ export default function getPacChooser(theState) {
chosenPacName: 'none', chosenPacName: 'none',
}; };
this.updatePac = function updatePac() { this.updatePac = function updatePac(onSuccess) {
props.funs.conduct( props.funs.conduct(
'Обновляем...', 'Обновляем...',
(cb) => props.apis.antiCensorRu.syncWithPacProviderAsync(cb), (cb) => props.apis.antiCensorRu.syncWithPacProviderAsync(cb),
'Обновлено.' 'Обновлено.',
onSuccess
); );
}; };
@ -155,7 +156,7 @@ export default function getPacChooser(theState) {
componentDidMount() { componentDidMount() {
if (this.props.apis.antiCensorRu.ifFirstInstall) { if (this.props.apis.antiCensorRu.ifFirstInstall) {
this.updatePac(); this.updatePac( this.props.funs.showNews );
} }
} }