-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0d2b1de
commit e0f344d
Showing
8 changed files
with
277 additions
and
3 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import app from 'flarum/admin/app'; | ||
|
||
export default class Umami { | ||
static instance = null; | ||
bearerToken = null; | ||
|
||
static getInstance() { | ||
if (!Umami.instance) { | ||
Umami.instance = new Umami(); | ||
} | ||
return Umami.instance; | ||
} | ||
|
||
async login() { | ||
if (this.bearerToken) { | ||
console.info('[michaelbelgium-umami] Bearer token already set, not fetching new one.'); | ||
return true; | ||
} | ||
|
||
if ( | ||
app.data.settings['michaelbelgium-umami.api_username'] === undefined || | ||
app.data.settings['michaelbelgium-umami.api_password'] === undefined || | ||
app.data.settings['michaelbelgium-umami.api_username'] === '' || | ||
app.data.settings['michaelbelgium-umami.api_password'] === '' | ||
) { | ||
console.error('[michaelbelgium-umami] API username and/or password not set or emtpy.'); | ||
return false; | ||
} | ||
|
||
const corsProxyUrl = 'https://cors-anywhere.herokuapp.com/'; | ||
const targetUrl = app.data.settings['michaelbelgium-umami.domain'] + '/api/auth/login'; | ||
|
||
try { | ||
const response = await app.request({ | ||
url: corsProxyUrl + targetUrl, | ||
method: 'POST', | ||
body: { | ||
username: app.data.settings['michaelbelgium-umami.api_username'], | ||
password: app.data.settings['michaelbelgium-umami.api_password'], | ||
}, | ||
}); | ||
|
||
this.bearerToken = response.token; | ||
console.info('[michaelbelgium-umami] Logged in as', response.user.username); | ||
return true; | ||
} catch (error) { | ||
console.error('[michaelbelgium-umami] Error logging in:', error); | ||
} | ||
return false; | ||
} | ||
|
||
async website() { | ||
return await app.request({ | ||
url: app.data.settings['michaelbelgium-umami.domain'] + '/api/websites/' + app.data.settings['michaelbelgium-umami.site_id'], | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer ' + this.bearerToken, | ||
}, | ||
}); | ||
} | ||
|
||
async websiteStats() { | ||
let stats = {}; | ||
|
||
const now = new Date(); | ||
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); | ||
weekAgo.setHours(0, 0, 0, 0); | ||
|
||
let response = await app.request({ | ||
url: app.data.settings['michaelbelgium-umami.domain'] + '/api/websites/' + app.data.settings['michaelbelgium-umami.site_id'] + '/stats', | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer ' + this.bearerToken, | ||
}, | ||
params: { | ||
startAt: weekAgo.getTime(), | ||
endAt: now.getTime(), | ||
}, | ||
}); | ||
|
||
stats = response; | ||
|
||
response = await app.request({ | ||
url: app.data.settings['michaelbelgium-umami.domain'] + '/api/websites/' + app.data.settings['michaelbelgium-umami.site_id'] + '/active', | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer ' + this.bearerToken, | ||
}, | ||
}); | ||
|
||
stats.live = response.x; | ||
|
||
return stats; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import DashboardWidget, { IDashboardWidgetAttrs } from 'flarum/admin/components/DashboardWidget'; | ||
import LoadingIndicator from 'flarum/common/components/LoadingIndicator'; | ||
import Umami from './Umami'; | ||
import icon from 'flarum/common/helpers/icon'; | ||
import app from 'flarum/admin/app'; | ||
|
||
export default class UmamiWidget extends DashboardWidget { | ||
loading = false; | ||
umami = Umami.getInstance(); | ||
stats = null; | ||
website = null; | ||
success = true; | ||
|
||
async oninit(vnode) { | ||
super.oninit(vnode); | ||
|
||
this.loading = true; | ||
m.redraw(); | ||
|
||
this.success = await this.umami.login(); | ||
|
||
if (this.success) { | ||
this.stats = await this.umami.websiteStats(); | ||
this.website = await this.umami.website(); | ||
} | ||
|
||
this.loading = false; | ||
m.redraw(); | ||
} | ||
|
||
className() { | ||
return 'UmamiWidget'; | ||
} | ||
|
||
content() { | ||
if (!this.success) { | ||
return ( | ||
<div> | ||
<h4>Umami statistics</h4> | ||
<p>{app.translator.trans('michaelbelgium-umami.admin.settings.errors.no_connection')}</p> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div> | ||
<h4>Umami statistics</h4> | ||
<div className="UmamiWidget-stats"> | ||
<section> | ||
<dt>{this.loading ? <LoadingIndicator size="small" display="inline" /> : <>{this.stats.live}</>}</dt> | ||
<h3> | ||
{icon('fas fa-circle fa-beat')} {app.translator.trans('michaelbelgium-umami.admin.widget.live')} | ||
</h3> | ||
</section> | ||
<section> | ||
<dt> | ||
{this.loading ? ( | ||
<LoadingIndicator size="small" display="inline" /> | ||
) : ( | ||
<> | ||
{this.stats.pageviews.value} {this.changeToSpan(this.stats.visits.change)} | ||
</> | ||
)} | ||
</dt> | ||
<h3>{app.translator.trans('michaelbelgium-umami.admin.widget.views')}</h3> | ||
</section> | ||
<section> | ||
<dt> | ||
{this.loading ? ( | ||
<LoadingIndicator size="small" display="inline" /> | ||
) : ( | ||
<> | ||
{this.stats.visits.value} {this.changeToSpan(this.stats.visits.value)} | ||
</> | ||
)} | ||
</dt> | ||
<h3>{app.translator.trans('michaelbelgium-umami.admin.widget.visits')}</h3> | ||
</section> | ||
<section> | ||
<dt> | ||
{this.loading ? ( | ||
<LoadingIndicator size="small" display="inline" /> | ||
) : ( | ||
<> | ||
{this.stats.visitors.value} {this.changeToSpan(this.stats.visitors.change)} | ||
</> | ||
)} | ||
</dt> | ||
<h3>{app.translator.trans('michaelbelgium-umami.admin.widget.visitors')}</h3> | ||
</section> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
changeToSpan(change) { | ||
return ( | ||
<span className={change >= 0 ? 'more' : 'less'}> | ||
{change >= 0 ? '+' : '-'} {change} | ||
</span> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
.DashboardPage .UmamiWidget { | ||
h4 { | ||
color: @muted-color; | ||
margin-top: 0; | ||
} | ||
|
||
.UmamiWidget-stats { | ||
display: flex; | ||
justify-content: space-between; | ||
width: 25%; | ||
|
||
section { | ||
dt { | ||
color: #111; | ||
font-size: 20px; | ||
font-weight: bold; | ||
text-align: right; | ||
|
||
span { | ||
font-size: 12px; | ||
padding: 0 5px; | ||
|
||
&.more { | ||
color: #15a46e; | ||
background: #cef8e0; | ||
} | ||
|
||
&.less { | ||
color: #f75c46; | ||
background: #ffebe7; | ||
} | ||
} | ||
} | ||
|
||
h3 { | ||
font-size: 12px; | ||
color: @muted-color; | ||
text-transform: uppercase; | ||
|
||
i.fa-circle { | ||
color: green; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,20 @@ | ||
michaelbelgium-umami: | ||
admin: | ||
widget: | ||
live: 'Live' | ||
views: 'Page views' | ||
visits: 'Visits' | ||
visitors: 'Visitors' | ||
settings: | ||
errors: | ||
no_connection: 'Could not fetch statistics, please check your API credentials.' | ||
site_id: | ||
label: 'Website ID' | ||
help: 'The website ID of this Flarum instance on Umami. You can find this in the details of the website settings on Umami.' | ||
domain: | ||
label: 'Domain' | ||
help: 'The domain where Umami is located.' | ||
help: 'The domain where Umami is located.' | ||
username: | ||
label: 'API Username' | ||
password: | ||
label: 'API Password' |