github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/ui/javascripts/app/models.js (about) 1 // 2 // A Consul service. 3 // 4 App.Service = Ember.Object.extend({ 5 // 6 // The number of failing checks within the service. 7 // 8 failingChecks: function() { 9 // If the service was returned from `/v1/internal/ui/services` 10 // then we have a aggregated value which we can just grab 11 if (this.get('ChecksCritical') !== undefined) { 12 return (this.get('ChecksCritical') + this.get('ChecksWarning')); 13 // Otherwise, we need to filter the child checks by both failing 14 // states 15 } else { 16 var checks = this.get('Checks'); 17 return (checks.filterBy('Status', 'critical').get('length') + 18 checks.filterBy('Status', 'warning').get('length')); 19 } 20 }.property('Checks'), 21 22 // 23 // The number of passing checks within the service. 24 // 25 passingChecks: function() { 26 // If the service was returned from `/v1/internal/ui/services` 27 // then we have a aggregated value which we can just grab 28 if (this.get('ChecksPassing') !== undefined) { 29 return this.get('ChecksPassing'); 30 // Otherwise, we need to filter the child checks by both failing 31 // states 32 } else { 33 return this.get('Checks').filterBy('Status', 'passing').get('length'); 34 } 35 }.property('Checks'), 36 37 // 38 // The formatted message returned for the user which represents the 39 // number of checks failing or passing. Returns `1 passing` or `2 failing` 40 // 41 checkMessage: function() { 42 if (this.get('hasFailingChecks') === false) { 43 return this.get('passingChecks') + ' passing'; 44 } else { 45 return this.get('failingChecks') + ' failing'; 46 } 47 }.property('Checks'), 48 49 nodes: function() { 50 return (this.get('Nodes')); 51 }.property('Nodes'), 52 53 // 54 // Boolean of whether or not there are failing checks in the service. 55 // This is used to set color backgrounds and so on. 56 // 57 hasFailingChecks: Ember.computed.gt('failingChecks', 0), 58 59 // 60 // Key used for filtering through an array of this model, i.e s 61 // searching 62 // 63 filterKey: Ember.computed.alias('Name'), 64 }); 65 66 // 67 // A Consul Node 68 // 69 App.Node = Ember.Object.extend({ 70 // 71 // The number of failing checks within the service. 72 // 73 failingChecks: function() { 74 return this.get('Checks').reduce(function(sum, check) { 75 var status = Ember.get(check, 'Status'); 76 // We view both warning and critical as failing 77 return (status === 'critical' || status === 'warning') ? 78 sum + 1 : 79 sum; 80 }, 0); 81 }.property('Checks'), 82 83 // 84 // The number of passing checks within the service. 85 // 86 passingChecks: function() { 87 return this.get('Checks').filterBy('Status', 'passing').get('length'); 88 }.property('Checks'), 89 90 // 91 // The formatted message returned for the user which represents the 92 // number of checks failing or passing. Returns `1 passing` or `2 failing` 93 // 94 checkMessage: function() { 95 if (this.get('hasFailingChecks') === false) { 96 return this.get('passingChecks') + ' passing'; 97 } else { 98 return this.get('failingChecks') + ' failing'; 99 } 100 }.property('Checks'), 101 102 // 103 // Boolean of whether or not there are failing checks in the service. 104 // This is used to set color backgrounds and so on. 105 // 106 hasFailingChecks: Ember.computed.gt('failingChecks', 0), 107 108 // 109 // The number of services on the node 110 // 111 numServices: Ember.computed.alias('Services.length'), 112 113 services: Ember.computed.alias('Services'), 114 115 filterKey: Ember.computed.alias('Node') 116 }); 117 118 119 // 120 // A key/value object 121 // 122 App.Key = Ember.Object.extend(Ember.Validations.Mixin, { 123 // Validates using the Ember.Validations library 124 validations: { 125 Key: { presence: true } 126 }, 127 128 // Boolean if field should validate JSON 129 validateJson: false, 130 // Boolean if the key is valid 131 keyValid: Ember.computed.empty('errors.Key'), 132 // Boolean if the value is valid 133 valueValid: Ember.computed.empty('errors.Value'), 134 135 // Escape any user-entered parts that aren't URL-safe, but put slashes back since 136 // they are common in keys, and the UI lets users make "folders" by simply adding 137 // them to keys. 138 Key: function(key, value) { 139 // setter 140 if (arguments.length > 1) { 141 clean = value 142 try { 143 clean = decodeURIComponent(clean); 144 } catch (e) { 145 // If they've got something that's not valid URL syntax then keep going; 146 // this means that at worst we might end up double escaping some things. 147 } 148 clean = encodeURIComponent(clean).replace(/%2F/g, "/") 149 this.set('cleanKey', clean); 150 return clean; 151 } 152 153 // getter 154 return this.get('cleanKey') 155 }.property('Key'), 156 157 // The key with the parent removed. 158 // This is only for display purposes, and used for 159 // showing the key name inside of a nested key. 160 keyWithoutParent: function() { 161 return (this.get('Key').replace(this.get('parentKey'), '')); 162 }.property('Key'), 163 164 // Boolean if the key is a "folder" or not, i.e is a nested key 165 // that feels like a folder. Used for UI 166 isFolder: function() { 167 if (this.get('Key') === undefined) { 168 return false; 169 } 170 return (this.get('Key').slice(-1) === '/'); 171 }.property('Key'), 172 173 // Boolean if the key is locked or now 174 isLocked: function() { 175 if (!this.get('Session')) { 176 return false; 177 } else { 178 return true; 179 } 180 }.property('Session'), 181 182 // Determines what route to link to. If it's a folder, 183 // it will link to kv.show. Otherwise, kv.edit 184 linkToRoute: function() { 185 if (this.get('Key').slice(-1) === '/') { 186 return 'kv.show'; 187 } else { 188 return 'kv.edit'; 189 } 190 }.property('Key'), 191 192 // The base64 decoded value of the key. 193 // if you set on this key, it will update 194 // the key.Value 195 valueDecoded: function(key, value) { 196 197 // setter 198 if (arguments.length > 1) { 199 this.set('Value', value); 200 return value; 201 } 202 203 // getter 204 205 // If the value is null, we don't 206 // want to try and base64 decode it, so just return 207 if (this.get('Value') === null) { 208 return ""; 209 } 210 if (Base64.extendString) { 211 // you have to explicitly extend String.prototype 212 Base64.extendString(); 213 } 214 // base64 decode the value 215 return (this.get('Value').fromBase64()); 216 }.property('Value'), 217 218 // Check if JSON is valid by attempting a native JSON parse 219 isValidJson: function() { 220 var value; 221 222 try { 223 window.atob(this.get('Value')); 224 value = this.get('valueDecoded'); 225 } catch (e) { 226 value = this.get('Value'); 227 } 228 229 try { 230 JSON.parse(value); 231 return true; 232 } catch (e) { 233 return false; 234 } 235 }.property('Value'), 236 237 // An array of the key broken up by the / 238 keyParts: function() { 239 var key = this.get('Key'); 240 241 // If the key is a folder, remove the last 242 // slash to split properly 243 if (key.slice(-1) == "/") { 244 key = key.substring(0, key.length - 1); 245 } 246 247 return key.split('/'); 248 }.property('Key'), 249 250 // The parent Key is the key one level above this.Key 251 // key: baz/bar/foobar/ 252 // grandParent: baz/bar/ 253 parentKey: function() { 254 var parts = this.get('keyParts').toArray(); 255 256 // Remove the last item, essentially going up a level 257 // in hierarchy 258 parts.pop(); 259 260 return parts.join("/") + "/"; 261 }.property('Key'), 262 263 // The grandParent Key is the key two levels above this.Key 264 // key: baz/bar/foobar/ 265 // grandParent: baz/ 266 grandParentKey: function() { 267 var parts = this.get('keyParts').toArray(); 268 269 // Remove the last two items, jumping two levels back 270 parts.pop(); 271 parts.pop(); 272 273 return parts.join("/") + "/"; 274 }.property('Key') 275 }); 276 277 // 278 // An ACL 279 // 280 App.Acl = Ember.Object.extend({ 281 isNotAnon: function() { 282 if (this.get('ID') === "anonymous"){ 283 return false; 284 } else { 285 return true; 286 } 287 }.property('ID') 288 }); 289 290 // Wrap localstorage with an ember object 291 App.Settings = Ember.Object.extend({ 292 unknownProperty: function(key) { 293 return localStorage[key]; 294 }, 295 296 setUnknownProperty: function(key, value) { 297 if(Ember.isNone(value)) { 298 delete localStorage[key]; 299 } else { 300 localStorage[key] = value; 301 } 302 this.notifyPropertyChange(key); 303 return value; 304 }, 305 306 clear: function() { 307 this.beginPropertyChanges(); 308 for (var i=0, l=localStorage.length; i<l; i++){ 309 this.set(localStorage.key(i)); 310 } 311 localStorage.clear(); 312 this.endPropertyChanges(); 313 } 314 });