Stack tags

This commit is contained in:
Vincent Fiduccia 2016-11-11 15:47:47 -07:00
parent 9ce9c5fd00
commit 20518f052d
11 changed files with 58 additions and 48 deletions

View File

@ -1,7 +1,7 @@
import Ember from 'ember'; import Ember from 'ember';
import NewOrEdit from 'ui/mixins/new-or-edit'; import NewOrEdit from 'ui/mixins/new-or-edit';
import ModalBase from 'lacsso/components/modal-base'; import ModalBase from 'lacsso/components/modal-base';
import {normalizedChoices, tagsToArray} from 'ui/models/stack'; import {tagChoices, tagsToArray} from 'ui/models/stack';
export default ModalBase.extend(NewOrEdit, { export default ModalBase.extend(NewOrEdit, {
classNames: ['lacsso', 'modal-container', 'large-modal'], classNames: ['lacsso', 'modal-container', 'large-modal'],
@ -28,7 +28,7 @@ export default ModalBase.extend(NewOrEdit, {
}, },
tagChoices: function() { tagChoices: function() {
return normalizedChoices(this.get('allStacks')); return tagChoices(this.get('allStacks'));
}.property('allStacks.@each.group'), }.property('allStacks.@each.group'),
doneSaving: function() { doneSaving: function() {

View File

@ -74,7 +74,6 @@ export default Ember.Component.extend({
return; return;
} }
let tmp = rules.objectAt(idx+1);
rules.removeAt(idx); rules.removeAt(idx);
rules.insertAt(idx+1, rule); rules.insertAt(idx+1, rule);
this.updatePriorities(); this.updatePriorities();

View File

@ -129,7 +129,7 @@ export default Ember.Mixin.create(NewOrEdit, ManageLabels, {
let errors = []; let errors = [];
if ( !this.get('nameParts.prefix') ) { if ( !this.get('nameParts.prefix') ) {
errors.push('Name is required') errors.push('Name is required');
} }
this.set('errors', errors); this.set('errors', errors);

View File

@ -2,7 +2,7 @@ import Ember from 'ember';
import Resource from 'ember-api-store/models/resource'; import Resource from 'ember-api-store/models/resource';
import { parseExternalId } from 'ui/utils/parse-externalid'; import { parseExternalId } from 'ui/utils/parse-externalid';
import C from 'ui/utils/constants'; import C from 'ui/utils/constants';
import Util from 'ui/utils/util'; import { download } from 'ui/utils/util';
import { denormalizeServiceArray } from 'ui/utils/denormalize-snowflakes'; import { denormalizeServiceArray } from 'ui/utils/denormalize-snowflakes';
export function activeIcon(stack) export function activeIcon(stack)
@ -27,15 +27,13 @@ export function tagsToArray(str) {
filter((tag) => tag.length > 0); filter((tag) => tag.length > 0);
} }
export function normalizedChoices(all) { export function tagChoices(all) {
let choices = []; let choices = [];
(all||[]).forEach((stack) => { (all||[]).forEach((stack) => {
choices.addObjects(stack.get('tags')); choices.addObjects(stack.get('tags'));
}); });
return choices.sort((a,b) => { return choices;
return a.toLowerCase().localeCompare(b.toLowerCase());
});
} }
var Stack = Resource.extend({ var Stack = Resource.extend({
@ -101,7 +99,7 @@ var Stack = Resource.extend({
exportConfig: function() { exportConfig: function() {
var url = this.get('endpointSvc').addAuthParams(this.linkFor('composeConfig')); var url = this.get('endpointSvc').addAuthParams(this.linkFor('composeConfig'));
Util.download(url); download(url);
}, },
viewCode: function() { viewCode: function() {

View File

@ -1,7 +1,8 @@
import Ember from 'ember'; import Ember from 'ember';
import Sortable from 'ui/mixins/sortable'; import Sortable from 'ui/mixins/sortable';
import C from 'ui/utils/constants'; import C from 'ui/utils/constants';
import { tagsToArray, normalizedChoices } from 'ui/models/stack'; import { tagsToArray, tagChoices } from 'ui/models/stack';
import { uniqKeys } from 'ui/utils/util';
export default Ember.Controller.extend(Sortable, { export default Ember.Controller.extend(Sortable, {
stacksController: Ember.inject.controller('stacks'), stacksController: Ember.inject.controller('stacks'),
@ -9,24 +10,21 @@ export default Ember.Controller.extend(Sortable, {
prefs: Ember.inject.service(), prefs: Ember.inject.service(),
intl: Ember.inject.service(), intl: Ember.inject.service(),
stacks: Ember.computed.alias('stacksController.stacks'),
infraTemplates: Ember.computed.alias('stacksController.infraTemplates'), infraTemplates: Ember.computed.alias('stacksController.infraTemplates'),
which: Ember.computed.alias('stacksController.which'), which: Ember.computed.alias('stacksController.which'),
tags: Ember.computed.alias('stacksController.tags'), tags: Ember.computed.alias('stacksController.tags'),
showAddtlInfo: false, showAddtlInfo: false,
selectedService: null, selectedService: null,
tagsArray: null, tag: null,
tagChoices: function() { tagChoices: function() {
let out = normalizedChoices(this.get('model')); let choices = tagChoices(this.get('model.stacks'));
tagsToArray(this.get('tags')).forEach((tag) => { tagsToArray(this.get('tags')).forEach((tag) => {
out.addObject(tag); choices.addObject(tag);
}); });
return out.sort((a,b) => { return uniqKeys(choices);
return a.toLowerCase().localeCompare(b.toLowerCase()); }.property('model.stacks.@each.group'), // tags is derived from group..
});
}.property('model.@each.group'),
actions: { actions: {
showAddtlInfo(service) { showAddtlInfo(service) {
@ -44,18 +42,8 @@ export default Ember.Controller.extend(Sortable, {
this.send('setSort', name); this.send('setSort', name);
}, },
updateTags(select) { switchTag(str) {
let options = Array.prototype.slice.call(select.target.options, 0); this.set('tags', str);
let selected = options.filterBy('selected',true).map(opt => opt.value);
if ( selected.length === 0 )
{
this.set('tags','');
}
else
{
this.set('tags', selected.join(','));
}
}, },
}, },

View File

@ -12,16 +12,6 @@
{{/if}} {{/if}}
{{/if}} {{/if}}
<!--
<div class="pull-right r-ml20">
<select class="form-control stack-tags" multiple="true" onchange={{action 'updateTags'}}>
{{#each tagChoices as |choice|}}
<option value={{choice}} selected={{include tagsArray choice}}>{{choice}}</option>
{{/each}}
</select>
</div>
-->
<div class="pull-right"> <div class="pull-right">
<label class="text-muted r-pr5" style="font-size: 13px;">{{t 'stacksPage.sort.label'}}: </label> <label class="text-muted r-pr5" style="font-size: 13px;">{{t 'stacksPage.sort.label'}}: </label>
<div class="btn-group r-pr0" role="group" aria-label="{{t 'stacksPage.sort.label'}}"> <div class="btn-group r-pr0" role="group" aria-label="{{t 'stacksPage.sort.label'}}">
@ -29,9 +19,26 @@
<button {{action 'sortResults' 'name'}} type="button" class="btn btn-sm btn-default {{if (eq sortBy "name") 'active'}}">{{t 'stacksPage.sort.name'}}</button> <button {{action 'sortResults' 'name'}} type="button" class="btn btn-sm btn-default {{if (eq sortBy "name") 'active'}}">{{t 'stacksPage.sort.name'}}</button>
</div> </div>
</div> </div>
{{#if tagChoices.length}}
<div class="btn-group pull-right r-mr10">
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{t (if tags 'stacksPage.tags.one' 'stacksPage.tags.all' ) name=tags}} <i class="icon icon-chevron-down"></i></button>
<ul class="dropdown-menu dropdown-menu-right">
<li class="{{if (eq tags '') 'active'}}"><a href="#" {{action 'switchTag' ''}}>{{t 'stacksPage.tags.all'}}</a></li>
<li class="divider"></li>
{{#each tagChoices as |opt|}}
<li class="{{if (eq tags opt) 'active'}}">
<a href="#" {{action 'switchTag' opt}}>
{{opt}}
</a>
</li>
{{/each}}
</ul>
</div>
{{/if}}
</section> </section>
<section class="stacks-wrap"> <section class="stacks-wrap r-pl0 r-pr0">
<div> <div>
{{#each arranged as |stack|}} {{#each arranged as |stack|}}
{{stack-section model=stack showAddtlInfo='showAddtlInfo' showAddService=(not stack.system)}} {{stack-section model=stack showAddtlInfo='showAddtlInfo' showAddService=(not stack.system)}}

View File

@ -1,7 +1,7 @@
import Ember from 'ember'; import Ember from 'ember';
import NewOrEdit from 'ui/mixins/new-or-edit'; import NewOrEdit from 'ui/mixins/new-or-edit';
import C from 'ui/utils/constants'; import C from 'ui/utils/constants';
import {normalizedChoices} from 'ui/models/stack'; import {tagChoices} from 'ui/models/stack';
export default Ember.Controller.extend(NewOrEdit, { export default Ember.Controller.extend(NewOrEdit, {
queryParams: ['githubRepo','githubBranch','composeFiles','system'], queryParams: ['githubRepo','githubBranch','composeFiles','system'],
@ -20,7 +20,7 @@ export default Ember.Controller.extend(NewOrEdit, {
}, },
groupChoices: function() { groupChoices: function() {
return normalizedChoices(this.get('allStacks')); return tagChoices(this.get('allStacks'));
}.property('allStacks.@each.grouping'), }.property('allStacks.@each.grouping'),
willSave: function() { willSave: function() {

View File

@ -19,11 +19,9 @@ function githubUrl(repo,branch,file) {
export default Ember.Route.extend({ export default Ember.Route.extend({
model: function(params/*, transition*/) { model: function(params/*, transition*/) {
let group = 'user';
var stack = this.get('store').createRecord({ var stack = this.get('store').createRecord({
type: 'stack', type: 'stack',
startOnCreate: true, startOnCreate: true,
group: group
}); });
var dockerUrl = null; var dockerUrl = null;

View File

@ -312,6 +312,22 @@ export function pluralize(count,singular,plural) {
} }
} }
export function uniqKeys(data, field=undefined) {
// Make a map of all the unique category names.
// If multiple casings of the same name are present, first wins.
let cased = {};
data.map((obj) => (field ? obj[field] : obj))
.filter((str) => str && str.length)
.forEach((str) => {
let lc = str.toLowerCase();
if ( !cased[lc] ) {
cased[lc] = str;
}
});
return Object.keys(cased).uniq().sort().map((str) => cased[str]);
}
export function camelToTitle(str) { export function camelToTitle(str) {
return (str||'').dasherize().split('-').map((str) => { return ucFirst(str); }).join(' '); return (str||'').dasherize().split('-').map((str) => { return ucFirst(str); }).join(' ');
} }
@ -341,7 +357,8 @@ var Util = {
formatKbps: formatKbps, formatKbps: formatKbps,
formatSi: formatSi, formatSi: formatSi,
pluralize: pluralize, pluralize: pluralize,
camelToTitle: camelToTitle camelToTitle: camelToTitle,
uniqKeys: uniqKeys,
}; };
window.Util = Util; window.Util = Util;

View File

@ -1,6 +1,6 @@
{ {
"name": "ui", "name": "ui",
"version": "1.2.20", "version": "1.2.22",
"private": true, "private": true,
"directories": { "directories": {
"doc": "doc", "doc": "doc",

View File

@ -1124,6 +1124,9 @@ stacksPage:
label: Sort By label: Sort By
state: State state: State
name: Name name: Name
tags:
all: All Tags
one: 'Tag: {name}'
noInfra: You do not currently have any Infrastructure Stacks noInfra: You do not currently have any Infrastructure Stacks
noMatch: No Stacks match the selected tags noMatch: No Stacks match the selected tags
new: new: