Ensured regular data for a short URL is loaded if defined

This commit is contained in:
Alejandro Celaya 2018-07-30 21:34:06 +02:00
parent 13004f6d57
commit 0f34d473b9
3 changed files with 59 additions and 16 deletions

View file

@ -39,6 +39,11 @@ export class ShlinkApiClient {
.then(resp => resp.data.visits.data) .then(resp => resp.data.visits.data)
.catch(e => this._handleAuthError(e, this.getShortUrlVisits, [shortCode, dates])); .catch(e => this._handleAuthError(e, this.getShortUrlVisits, [shortCode, dates]));
getShortUrl = shortCode =>
this._performRequest(`/short-codes/${shortCode}`, 'GET')
.then(resp => resp.data)
.catch(e => this._handleAuthError(e, this.getShortUrl, [shortCode]));
_performRequest = async (url, method = 'GET', params = {}, data = {}) => { _performRequest = async (url, method = 'GET', params = {}, data = {}) => {
if (isEmpty(this._token)) { if (isEmpty(this._token)) {
this._token = await this._authenticate(); this._token = await this._authenticate();

View file

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { Doughnut, HorizontalBar } from 'react-chartjs-2'; import { Doughnut, HorizontalBar } from 'react-chartjs-2';
import Moment from 'react-moment';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { pick } from 'ramda'; import { pick } from 'ramda';
import { Card, CardBody, CardHeader } from 'reactstrap'; import { Card, CardBody, CardHeader, UncontrolledTooltip } from 'reactstrap';
import { getShortUrlVisits } from './reducers/shortUrlVisits'; import { getShortUrlVisits } from './reducers/shortUrlVisits';
import VisitsParser from '../visits/services/VisitsParser'; import VisitsParser from '../visits/services/VisitsParser';
import preloader from '@fortawesome/fontawesome-free-solid/faCircleNotch'; import preloader from '@fortawesome/fontawesome-free-solid/faCircleNotch';
@ -17,9 +18,14 @@ export class ShortUrlsVisits extends React.Component {
} }
render() { render() {
const { match: { params }, selectedServer, visitsParser, shortUrlVisits: { visits, loading, error } } = this.props; const {
match: { params },
selectedServer,
visitsParser,
shortUrlVisits: { visits, loading, error, shortUrl }
} = this.props;
const serverUrl = selectedServer ? selectedServer.url : ''; const serverUrl = selectedServer ? selectedServer.url : '';
const shortUrl = `${serverUrl}/${params.shortCode}`; const shortLink = `${serverUrl}/${params.shortCode}`;
const generateGraphData = (stats, label, isBarChart) => ({ const generateGraphData = (stats, label, isBarChart) => ({
labels: Object.keys(stats), labels: Object.keys(stats),
datasets: [ datasets: [
@ -72,15 +78,45 @@ export class ShortUrlsVisits extends React.Component {
); );
}; };
const renderCreated = () =>
<span>
<b id="created"><Moment fromNow>{shortUrl.dateCreated}</Moment></b>
<UncontrolledTooltip placement="bottom" target="created">
<Moment format="YYYY-MM-DD HH:mm">{shortUrl.dateCreated}</Moment>
</UncontrolledTooltip>
</span>;
return ( return (
<div className="short-urls-container"> <div className="short-urls-container">
<header>
<Card className="bg-light"> <Card className="bg-light">
<CardBody> <CardBody>
<h2>Visit stats for <a target="_blank" href={shortUrl}>{shortUrl}</a></h2> <h2>
{
shortUrl.visitsCount &&
<span className="badge badge-primary float-right">Visits: {shortUrl.visitsCount}</span>
}
Visit stats for <a target="_blank" href={shortLink}>{shortLink}</a>
</h2>
<hr />
{shortUrl.dateCreated && <div>
Created:
&nbsp;
{loading && <small>Loading...</small>}
{!loading && renderCreated()}
</div>}
<div>
Original URL:
&nbsp;
{loading && <small>Loading...</small>}
{!loading && <a target="_blank" href={shortUrl.longUrl}>{shortUrl.longUrl}</a>}
</div>
</CardBody> </CardBody>
</Card> </Card>
</header>
<section>
{renderContent()} {renderContent()}
</section>
</div> </div>
); );
} }

View file

@ -5,6 +5,7 @@ const GET_SHORT_URL_VISITS_ERROR = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_E
const GET_SHORT_URL_VISITS = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS'; const GET_SHORT_URL_VISITS = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS';
const initialState = { const initialState = {
shortUrl: {},
visits: [], visits: [],
loading: false, loading: false,
error: false error: false
@ -25,6 +26,7 @@ export default function dispatch (state = initialState, action) {
}; };
case GET_SHORT_URL_VISITS: case GET_SHORT_URL_VISITS:
return { return {
shortUrl: action.shortUrl,
visits: action.visits, visits: action.visits,
loading: false, loading: false,
error: false error: false
@ -34,13 +36,13 @@ export default function dispatch (state = initialState, action) {
} }
} }
export const getShortUrlVisits = (shortCode, dates) => async dispatch => { export const getShortUrlVisits = (shortCode, dates) => dispatch => {
dispatch({ type: GET_SHORT_URL_VISITS_START }); dispatch({ type: GET_SHORT_URL_VISITS_START });
try { Promise.all([
const visits = await ShlinkApiClient.getShortUrlVisits(shortCode, dates); ShlinkApiClient.getShortUrlVisits(shortCode, dates),
dispatch({ visits, type: GET_SHORT_URL_VISITS }); ShlinkApiClient.getShortUrl(shortCode)
} catch (e) { ])
dispatch({ type: GET_SHORT_URL_VISITS_ERROR }); .then(([visits, shortUrl]) => dispatch({ visits, shortUrl, type: GET_SHORT_URL_VISITS }))
} .catch(() => dispatch({ type: GET_SHORT_URL_VISITS_ERROR }));
}; };