Add stats to index page

This commit is contained in:
Stanislav Romanov 2022-08-28 15:26:38 +03:00
parent 87f2db24f9
commit c9918ba879
13 changed files with 155 additions and 27 deletions

15
app/components/stat.hbs Normal file
View file

@ -0,0 +1,15 @@
<div
class='px-4 py-5 bg-white shadow rounded-lg overflow-hidden sm:p-6'
...attributes
>
<dt class='text-sm font-medium text-gray-500 truncate'>
{{@title}}
</dt>
<dd class='mt-1 text-3xl font-semibold text-gray-900'>
{{#if (has-block)}}
{{yield}}
{{else}}
{{@value}}
{{/if}}
</dd>
</div>

View file

@ -0,0 +1,11 @@
import { helper } from '@ember/component/helper';
export default helper(function dateTimeFormat([date], named) {
if (typeof date === 'string') {
date = new Date(date);
}
const formatter = new Intl.DateTimeFormat(window.navigator.language, named);
return formatter.format(date);
});

View file

@ -0,0 +1,11 @@
import { helper } from '@ember/component/helper';
export default helper(function formatBytes([bytes, decimals] /*, named*/) {
if (bytes == 0) return '0 Bytes';
let k = 1024,
dm = decimals || 2,
sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
});

View file

@ -1,6 +1,5 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
export default class AdminRoute extends Route {
@service meilisearch;
@ -11,10 +10,6 @@ export default class AdminRoute extends Route {
}
async model() {
return hash({
indexes: this.meilisearch.getIndexes(),
health: this.meilisearch.getHealth(),
version: this.meilisearch.getVersion(),
});
return this.meilisearch.getIndexes();
}
}

16
app/routes/admin/index.js Normal file
View file

@ -0,0 +1,16 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
export default class AdminIndexRoute extends Route {
@service meilisearch;
@service session;
async model() {
return hash({
health: this.meilisearch.getHealth(),
version: this.meilisearch.getVersion(),
stats: this.meilisearch.getStats(),
});
}
}

View file

@ -5,6 +5,6 @@ export default class IndexRoute extends Route {
@service router;
beforeModel() {
this.router.transitionTo('admin.indexes');
this.router.transitionTo('admin');
}
}

View file

@ -16,4 +16,8 @@ export default class MeilisearchService extends Service {
getVersion() {
return query('version');
}
getStats() {
return query('stats');
}
}

View file

@ -14,7 +14,7 @@
}}
<nav>
<div class='px-4 py-2 text-sm text-gray'>Indexes</div>
{{#each @model.indexes as |item|}}
{{#each @model as |item|}}
<LinkTo
@route='admin.indexes.item'
@model={{item}}
@ -52,25 +52,6 @@
><Icons::Logout class='mr-1' />Logout</button>
</nav>
{{/let}}
<div class='flex flex-row items-center mt-auto px-4 pt-2'>
<span
class='mr-1 text-gray'
title='The version of a running Meilisearch instance'
>v{{@model.version.pkgVersion}}</span>
{{#if (eq @model.health.status 'available')}}
<Icons::CheckboxMarkedCircle
class='text-green'
@size={{18}}
@title={{@model.health.status}}
/>
{{else}}
<Icons::AlertCircle
class='text-yellow'
@size={{18}}
@title={{@model.health.status}}
/>
{{/if}}
</div>
</div>
</div>

View file

@ -0,0 +1,24 @@
<dl class='grid grid-cols-1 md:grid-cols-4 gap-5'>
<Stat @title='Status'>
<div class='flex items-center'>
{{#if (eq @model.health.status 'available')}}
<Icons::CheckboxMarkedCircle class='text-green mr-1' @size={{26}} />
{{else}}
<Icons::AlertCircle class='text-yellow mr-1' @size={{26}} />
{{/if}}
{{capitalize @model.health.status}}
</div>
</Stat>
<Stat
@title='Database size'
@value={{format-bytes @model.stats.databaseSize}}
/>
<Stat
@title='Last update'
@value={{date-time-format @model.stats.lastUpdate}}
/>
<Stat
@title='The version of the Meilisearch instance'
@value={{@model.version.pkgVersion}}
/>
</dl>

View file

@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | stat', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Stat />`);
assert.dom(this.element).hasText('');
// Template block usage:
await render(hbs`
<Stat>
template block text
</Stat>
`);
assert.dom(this.element).hasText('template block text');
});
});

View file

@ -0,0 +1,17 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Helper | DateTimeFormat', function (hooks) {
setupRenderingTest(hooks);
// TODO: Replace this with your real tests.
test('it renders', async function (assert) {
this.set('inputValue', '1234');
await render(hbs`{{date-time-format this.inputValue}}`);
assert.dom(this.element).hasText('1234');
});
});

View file

@ -0,0 +1,17 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Helper | formatBytes', function (hooks) {
setupRenderingTest(hooks);
// TODO: Replace this with your real tests.
test('it renders', async function (assert) {
this.set('inputValue', '1234');
await render(hbs`{{format-bytes this.inputValue}}`);
assert.dom(this.element).hasText('1234');
});
});

View file

@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'meiliadmin/tests/helpers';
module('Unit | Route | admin/index', function (hooks) {
setupTest(hooks);
test('it exists', function (assert) {
let route = this.owner.lookup('route:admin/index');
assert.ok(route);
});
});