github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/ui/app/controllers/clients/index.js (about) 1 import { alias, readOnly } from '@ember/object/computed'; 2 import { inject as service } from '@ember/service'; 3 import Controller, { inject as controller } from '@ember/controller'; 4 import { computed } from '@ember/object'; 5 import { scheduleOnce } from '@ember/runloop'; 6 import intersection from 'lodash.intersection'; 7 import SortableFactory from 'nomad-ui/mixins/sortable-factory'; 8 import Searchable from 'nomad-ui/mixins/searchable'; 9 import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize'; 10 11 export default Controller.extend( 12 SortableFactory(['id', 'name', 'compositeStatus', 'datacenter']), 13 Searchable, 14 { 15 userSettings: service(), 16 clientsController: controller('clients'), 17 18 nodes: alias('model.nodes'), 19 agents: alias('model.agents'), 20 21 queryParams: { 22 currentPage: 'page', 23 searchTerm: 'search', 24 sortProperty: 'sort', 25 sortDescending: 'desc', 26 qpClass: 'class', 27 qpState: 'state', 28 qpDatacenter: 'dc', 29 qpVolume: 'volume', 30 }, 31 32 currentPage: 1, 33 pageSize: readOnly('userSettings.pageSize'), 34 35 sortProperty: 'modifyIndex', 36 sortDescending: true, 37 38 searchProps: computed(() => ['id', 'name', 'datacenter']), 39 40 qpClass: '', 41 qpState: '', 42 qpDatacenter: '', 43 qpVolume: '', 44 45 selectionClass: selection('qpClass'), 46 selectionState: selection('qpState'), 47 selectionDatacenter: selection('qpDatacenter'), 48 selectionVolume: selection('qpVolume'), 49 50 optionsClass: computed('nodes.[]', function() { 51 const classes = Array.from(new Set(this.nodes.mapBy('nodeClass'))) 52 .compact() 53 .without(''); 54 55 // Remove any invalid node classes from the query param/selection 56 scheduleOnce('actions', () => { 57 this.set('qpClass', serialize(intersection(classes, this.selectionClass))); 58 }); 59 60 return classes.sort().map(dc => ({ key: dc, label: dc })); 61 }), 62 63 optionsState: computed(() => [ 64 { key: 'initializing', label: 'Initializing' }, 65 { key: 'ready', label: 'Ready' }, 66 { key: 'down', label: 'Down' }, 67 { key: 'ineligible', label: 'Ineligible' }, 68 { key: 'draining', label: 'Draining' }, 69 ]), 70 71 optionsDatacenter: computed('nodes.[]', function() { 72 const datacenters = Array.from(new Set(this.nodes.mapBy('datacenter'))).compact(); 73 74 // Remove any invalid datacenters from the query param/selection 75 scheduleOnce('actions', () => { 76 this.set('qpDatacenter', serialize(intersection(datacenters, this.selectionDatacenter))); 77 }); 78 79 return datacenters.sort().map(dc => ({ key: dc, label: dc })); 80 }), 81 82 optionsVolume: computed('nodes.[]', function() { 83 const flatten = (acc, val) => acc.concat(val.toArray()); 84 85 const allVolumes = this.nodes.mapBy('hostVolumes').reduce(flatten, []); 86 const volumes = Array.from(new Set(allVolumes.mapBy('name'))); 87 88 scheduleOnce('actions', () => { 89 this.set('qpVolume', serialize(intersection(volumes, this.selectionVolume))); 90 }); 91 92 return volumes.sort().map(volume => ({ key: volume, label: volume })); 93 }), 94 95 filteredNodes: computed( 96 'nodes.[]', 97 'selectionClass', 98 'selectionState', 99 'selectionDatacenter', 100 'selectionVolume', 101 function() { 102 const { 103 selectionClass: classes, 104 selectionState: states, 105 selectionDatacenter: datacenters, 106 selectionVolume: volumes, 107 } = this; 108 109 const onlyIneligible = states.includes('ineligible'); 110 const onlyDraining = states.includes('draining'); 111 112 // states is a composite of node status and other node states 113 const statuses = states.without('ineligible').without('draining'); 114 115 return this.nodes.filter(node => { 116 if (classes.length && !classes.includes(node.get('nodeClass'))) return false; 117 if (statuses.length && !statuses.includes(node.get('status'))) return false; 118 if (datacenters.length && !datacenters.includes(node.get('datacenter'))) return false; 119 if (volumes.length && !node.hostVolumes.find(volume => volumes.includes(volume.name))) 120 return false; 121 122 if (onlyIneligible && node.get('isEligible')) return false; 123 if (onlyDraining && !node.get('isDraining')) return false; 124 125 return true; 126 }); 127 } 128 ), 129 130 listToSort: alias('filteredNodes'), 131 listToSearch: alias('listSorted'), 132 sortedNodes: alias('listSearched'), 133 134 isForbidden: alias('clientsController.isForbidden'), 135 136 setFacetQueryParam(queryParam, selection) { 137 this.set(queryParam, serialize(selection)); 138 }, 139 140 actions: { 141 gotoNode(node) { 142 this.transitionToRoute('clients.client', node); 143 }, 144 }, 145 } 146 );