Add filterbar in apps view
This commit is contained in:
@@ -6,6 +6,11 @@
|
||||
{{ $t('apps.title') }}
|
||||
<div>
|
||||
<TextInput v-model="filter" placeholder="Filter ..." />
|
||||
<ButtonGroup>
|
||||
<Dropdown outline tool :options="tagFilterOptions" option-key="id" option-label="name" v-model="tagFilter"></Dropdown>
|
||||
<Dropdown outline tool :options="stateFilterOptions" option-key="id" v-model="stateFilter"></Dropdown>
|
||||
<Dropdown outline tool :options="domainFilterOptions" option-key="id" option-label="domain" v-model="domainFilter"></Dropdown>
|
||||
</ButtonGroup>
|
||||
<Button tool @click="toggleView()" :icon="viewType === VIEW_TYPE.GRID ? 'fas fa-list' : 'fas fa-grip'"></Button>
|
||||
</div>
|
||||
</h1>
|
||||
@@ -91,17 +96,21 @@
|
||||
|
||||
<script>
|
||||
|
||||
import { Button, ButtonGroup, Icon, TableView, TextInput } from 'pankow';
|
||||
import { Button, ButtonGroup, Dropdown, Icon, TableView, TextInput } from 'pankow';
|
||||
|
||||
import { APP_TYPES, HSTATES, ISTATES, RSTATES } from '../constants.js';
|
||||
import AppsModel from '../models/AppsModel.js';
|
||||
import ApplinksModel from '../models/ApplinksModel.js';
|
||||
import GroupsModel from '../models/GroupsModel.js';
|
||||
import DomainsModel from '../models/DomainsModel.js';
|
||||
import ApplinkDialog from './ApplinkDialog.vue';
|
||||
|
||||
const API_ORIGIN = import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin;
|
||||
const accessToken = localStorage.token;
|
||||
|
||||
const appsModel = AppsModel.create(API_ORIGIN, accessToken);
|
||||
const groupsModel = GroupsModel.create(API_ORIGIN, accessToken);
|
||||
const domainsModel = DomainsModel.create(API_ORIGIN, accessToken);
|
||||
const applinksModel = ApplinksModel.create(API_ORIGIN, accessToken);
|
||||
|
||||
const VIEW_TYPE = {
|
||||
@@ -117,6 +126,7 @@ export default {
|
||||
ApplinkDialog,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Dropdown,
|
||||
Icon,
|
||||
TableView,
|
||||
TextInput,
|
||||
@@ -130,6 +140,24 @@ export default {
|
||||
filter: '',
|
||||
apps: [],
|
||||
viewType: (localStorage.appsView && (localStorage.appsView === VIEW_TYPE.GRID || localStorage.appsView === VIEW_TYPE.LIST)) ? localStorage.appsView : VIEW_TYPE.GRID,
|
||||
tagFilter: '',
|
||||
tagFilterOptions: [{
|
||||
id: '',
|
||||
name: 'All Tags',
|
||||
}],
|
||||
domainFilter: '',
|
||||
domainFilterOptions: [{
|
||||
id: '',
|
||||
domain: 'All Domains',
|
||||
}],
|
||||
stateFilter: '',
|
||||
stateFilterOptions: [
|
||||
{ id: '', label: 'All States' },
|
||||
{ id: 'running', label: 'Running' },
|
||||
{ id: 'stopped', label: 'Stopped' },
|
||||
{ id: 'update_available', label: 'Update Available' },
|
||||
{ id: 'not_responding', label: 'Not Responding' },
|
||||
],
|
||||
listColumns: {
|
||||
icon: {
|
||||
width: '32px'
|
||||
@@ -159,6 +187,23 @@ export default {
|
||||
filteredApps() {
|
||||
return this.apps.filter(a => {
|
||||
return a.fqdn.indexOf(this.filter) !== -1;
|
||||
}).filter(a => {
|
||||
if (!this.domainFilter) return true;
|
||||
return a.domain === this.domainFilter;
|
||||
}).filter(a => {
|
||||
if (!this.tagFilter) return true;
|
||||
return a.tags.indexOf(this.tagFilter) !== -1;
|
||||
}).filter(a => {
|
||||
if (!this.stateFilter) return true;
|
||||
|
||||
if (this.stateFilter === 'running') return a.runState === RSTATES.RUNNING && a.health === HSTATES.HEALTHY && a.installationState === ISTATES.INSTALLED;
|
||||
if (this.stateFilter === 'stopped') return a.runState === RSTATES.STOPPED;
|
||||
|
||||
// TODO implement this
|
||||
// if (this.stateFilter === 'update_available') return !!(Client.getConfig().update[a.id] && Client.getConfig().update[a.id].manifest.version && Client.getConfig().update[a.id].manifest.version !== a.manifest.version);
|
||||
if (this.stateFilter === 'update_available') return false;
|
||||
|
||||
return a.runState === RSTATES.RUNNING && (a.health !== HSTATES.HEALTHY || a.installationState !== ISTATES.INSTALLED); // not responding
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -217,6 +262,10 @@ export default {
|
||||
}
|
||||
|
||||
this.apps = apps;
|
||||
|
||||
// gets all tags used by all apps, flattens the arrays and new Set() will dedupe
|
||||
const tags = [...new Set(this.apps.map(a => a.tags).flat())].map(t => { return { id: t, name: t }; });
|
||||
this.tagFilterOptions = [{ id: '', name: 'All Tags', }].concat(tags);
|
||||
},
|
||||
toggleView() {
|
||||
this.viewType = this.viewType === VIEW_TYPE.LIST ? VIEW_TYPE.GRID : VIEW_TYPE.LIST;
|
||||
@@ -226,6 +275,13 @@ export default {
|
||||
async mounted() {
|
||||
await this.refreshApps();
|
||||
|
||||
const domains = await domainsModel.list();
|
||||
this.domainFilterOptions = this.domainFilterOptions.concat(domains.map(d => { d.id = d.domain; return d; }));
|
||||
this.domainFilter = this.domainFilterOptions[0].id;
|
||||
|
||||
this.stateFilter = this.stateFilterOptions[0].id;
|
||||
this.tagFilter = this.tagFilterOptions[0].id;
|
||||
|
||||
this.ready = true;
|
||||
|
||||
refreshInterval = setInterval(this.refreshApps, 5000);
|
||||
|
||||
Reference in New Issue
Block a user