|
|
@ -5,12 +5,28 @@ import toastr from 'toastr' |
|
|
|
|
|
|
|
|
export default class VisitorComponent extends Component { |
|
|
export default class VisitorComponent extends Component { |
|
|
state = { |
|
|
state = { |
|
|
id: "", |
|
|
visitors: [], |
|
|
visitors: null |
|
|
info: null |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
componentDidMount() { |
|
|
componentDidMount() { |
|
|
this.setState({ id: this.props.match.params.id }) |
|
|
this.setState({ id: this.props.match.params.id }) |
|
|
|
|
|
fetch("/api/v1/protected/lookup", { |
|
|
|
|
|
method: "POST", |
|
|
|
|
|
body: JSON.stringify({ |
|
|
|
|
|
ID: this.props.match.params.id |
|
|
|
|
|
}), |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Authorization': window.localStorage.getItem('token'), |
|
|
|
|
|
'Content-Type': 'application/json' |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.then(res => res.ok ? res.json() : Promise.reject(res.json())) |
|
|
|
|
|
.then(info => this.setState({ info })) |
|
|
|
|
|
.catch(e => { |
|
|
|
|
|
toastr.error(`Could not fetch lookup: ${e}`) |
|
|
|
|
|
}) |
|
|
|
|
|
this.loop = setInterval(() => { |
|
|
fetch('/api/v1/protected/visitors', { |
|
|
fetch('/api/v1/protected/visitors', { |
|
|
method: 'POST', |
|
|
method: 'POST', |
|
|
body: JSON.stringify({ |
|
|
body: JSON.stringify({ |
|
|
@ -24,6 +40,11 @@ export default class VisitorComponent extends Component { |
|
|
.then(res => res.ok ? res.json() : Promise.reject(res.json())) |
|
|
.then(res => res.ok ? res.json() : Promise.reject(res.json())) |
|
|
.then(visitors => this.setState({ visitors })) |
|
|
.then(visitors => this.setState({ visitors })) |
|
|
.catch(e => e.done(res => toastr.error(`Could not fetch visitors: ${res}`))) |
|
|
.catch(e => e.done(res => toastr.error(`Could not fetch visitors: ${res}`))) |
|
|
|
|
|
}, 1000) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() { |
|
|
|
|
|
clearInterval(this.loop) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// getUTMSource is a function which generates the output for the utm[...] table column
|
|
|
// getUTMSource is a function which generates the output for the utm[...] table column
|
|
|
@ -36,14 +57,18 @@ export default class VisitorComponent extends Component { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
render() { |
|
|
render() { |
|
|
const { visitors } = this.state |
|
|
const { visitors, id, info } = this.state |
|
|
return ( |
|
|
return ( |
|
|
<Container > |
|
|
<Container > |
|
|
|
|
|
{info && <p> |
|
|
|
|
|
Entry with id {id} was created at {moment(info.CreatedOn).format('LLL')} and redirects to '{info.URL}'. Currently it has {visitors.length} visits. |
|
|
|
|
|
</p>} |
|
|
<Table celled> |
|
|
<Table celled> |
|
|
<Table.Header> |
|
|
<Table.Header> |
|
|
<Table.Row> |
|
|
<Table.Row> |
|
|
<Table.HeaderCell>Timestamp</Table.HeaderCell> |
|
|
<Table.HeaderCell>Timestamp</Table.HeaderCell> |
|
|
<Table.HeaderCell>IP</Table.HeaderCell> |
|
|
<Table.HeaderCell>IP</Table.HeaderCell> |
|
|
|
|
|
<Table.HeaderCell>User Agent</Table.HeaderCell> |
|
|
<Table.HeaderCell>Referer</Table.HeaderCell> |
|
|
<Table.HeaderCell>Referer</Table.HeaderCell> |
|
|
<Table.HeaderCell>UTM (source, medium, campaign, content, term)</Table.HeaderCell> |
|
|
<Table.HeaderCell>UTM (source, medium, campaign, content, term)</Table.HeaderCell> |
|
|
</Table.Row> |
|
|
</Table.Row> |
|
|
@ -52,6 +77,7 @@ export default class VisitorComponent extends Component { |
|
|
{visitors && visitors.map((visit, idx) => <Table.Row key={idx}> |
|
|
{visitors && visitors.map((visit, idx) => <Table.Row key={idx}> |
|
|
<Table.Cell>{moment(visit.Timestamp).format('LLL')}</Table.Cell> |
|
|
<Table.Cell>{moment(visit.Timestamp).format('LLL')}</Table.Cell> |
|
|
<Table.Cell>{visit.IP}</Table.Cell> |
|
|
<Table.Cell>{visit.IP}</Table.Cell> |
|
|
|
|
|
<Table.Cell>{visit.UserAgent}</Table.Cell> |
|
|
<Table.Cell>{visit.Referer}</Table.Cell> |
|
|
<Table.Cell>{visit.Referer}</Table.Cell> |
|
|
<Table.Cell>{this.getUTMSource(visit)}</Table.Cell> |
|
|
<Table.Cell>{this.getUTMSource(visit)}</Table.Cell> |
|
|
</Table.Row>)} |
|
|
</Table.Row>)} |
|
|
|