Add filterbar in apps view

This commit is contained in:
Johannes Zellner
2025-01-05 12:52:11 +01:00
parent bc8b32ebab
commit a43f9d78c4
2 changed files with 84 additions and 1 deletions

View File

@@ -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);