Merge pull request #2230 from loganhz/pv

Improve pv list and pv detail page
This commit is contained in:
Westly Wright 2018-09-10 09:52:27 -07:00 committed by GitHub
commit 30f81e76ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 245 additions and 128 deletions

View File

@ -1,13 +1,13 @@
import Route from '@ember/routing/route';
import { set } from '@ember/object';
import { get, set } from '@ember/object';
export default Route.extend({
model() {
const original = this.modelFor('authenticated.cluster.storage.classes.detail');
set(this, 'originalModel', original);
set(this, 'originalModel', get(original, 'storageclass'));
return original.clone();
return get(original, 'storageclass').clone();
},
setupController(controller/* , model*/) {

View File

@ -1,4 +1,5 @@
{{cru-storage-class
mode="view"
model=model
model=model.storageclass
persistentVolumes=model.persistentVolumes
}}

View File

@ -1,11 +1,18 @@
import Route from '@ember/routing/route';
import { get } from '@ember/object';
import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
export default Route.extend({
clusterStore: service(),
model(params) {
return get(this, 'clusterStore').find('storageclass', params.storage_class_id);
const clusterStore = get(this, 'clusterStore');
const storageClassId = params.storage_class_id;
return hash({
storageclass: clusterStore.find('storageclass', storageClassId),
persistentVolumes: clusterStore.findAll('persistentVolume').then((data) => (data || []).filterBy('storageClassId', storageClassId))
});
},
});

View File

@ -8,38 +8,4 @@
<h1>{{t 'persistentVolumePage.header'}}</h1>
</section>
{{#sortable-table
tableClassNames="bordered"
paging=true
pagingLabel="pagination.volume"
headers=headers
bulkActions=true
descending=descending
body=rows
sortBy=sortBy
as |sortable kind obj dt|
}}
{{#if (eq kind "row")}}
<tr class="main-row">
<td class="row-check" valign="middle" style="padding-top: 2px;">
{{check-box nodeId=obj.id}}
</td>
<td data-title="{{dt.state}}">
{{badge-state model=obj}}
</td>
<td data-title="{{dt.name}}">
<a href="{{href-to "authenticated.cluster.storage.persistent-volumes.detail" obj.id}}">{{obj.displayName}}</a>
</td>
<td data-title="{{dt.source}}">
{{obj.displaySource}}
</td>
<td data-title="{{dt.actions}}" class="actions">
{{action-menu model=obj}}
</td>
</tr>
{{else if (eq kind "nomatch")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'persistentVolumePage.noMatch'}}</td></tr>
{{else if (eq kind "norows")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'persistentVolumePage.noData'}}</td></tr>
{{/if}}
{{/sortable-table}}
{{persistent-volume-table rows=model.persistentVolumes}}

View File

@ -13,6 +13,9 @@
{{#if model.description}}
{{banner-message color='bg-secondary mb-0 mt-10' message=(linkify model.description)}}
{{/if}}
{{#if model.showTransitioningMessage}}
<div class="{{model.stateColor}}"><p>{{uc-first model.transitioningMessage}}</p></div>
{{/if}}
{{else}}
{{form-name-description
model=primaryResource
@ -24,10 +27,39 @@
}}
{{/if}}
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'cruPersistentVolume.source.label'}}{{field-required editing=editing}}</label>
{{#if editing}}
{{#if isView}}
<div class="row banner bg-info basics">
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'cruPersistentVolume.source.label'}}</label>
{{t (concat 'volumeSource.' sourceName '.title')}}
</div>
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'cruPersistentVolume.capacity.label'}}</label>
{{capacity}} {{t 'cruPersistentVolume.capacity.unit'}}
</div>
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'cruPersistentVolume.reclaimPolicy'}}</label>
{{model.persistentVolumeReclaimPolicy}}
</div>
</div>
<div class="row banner bg-info basics">
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'cruPersistentVolume.pvc'}}</label>
{{#if model.displayPvc}}
{{model.displayPvc}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</div>
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'generic.created'}}</label>
{{date-calendar model.created}}
</div>
</div>
{{else}}
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'cruPersistentVolume.source.label'}}{{field-required editing=editing}}</label>
{{new-select
content=sourceChoices
prompt="cruPersistentVolume.source.prompt"
@ -36,26 +68,18 @@
value=sourceName
readOnly=isView
}}
{{else}}
<div>
{{t (concat 'volumeSource.' sourceName '.title')}}
</div>
{{/if}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'cruPersistentVolume.capacity.label'}}{{field-required editing=editing}}</label>
{{#if editing}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'cruPersistentVolume.capacity.label'}}{{field-required editing=editing}}</label>
<div class="input-group">
{{input-number classNames="form-control" value=capacity}}
<span class="input-group-addon bg-default">{{t 'cruPersistentVolume.capacity.unit'}}</span>
</div>
{{else}}
<div>
{{capacity}} {{t 'cruPersistentVolume.capacity.unit'}}
</div>
{{/if}}
</div>
</div>
</div>
{{/if}}
<hr class="mb-20" />
@ -139,14 +163,20 @@
{{/accordion-list-item}}
{{#if isView}}
{{resource-event-list
resourceType=(t 'generic.persistentVolume')
expandAll=al.expandAll
expandFn=expandFn
name=model.name
kind="PersistentVolume"
}}
{{/if}}
{{resource-event-list
resourceType=(t 'generic.persistentVolume')
expandAll=al.expandAll
expandFn=expandFn
name=model.name
kind="PersistentVolume"
}}
{{annotations-section
model=model
expandAll=al.expandAll
expandFn=expandFn
}}
{{/if}}
{{/accordion-list}}
{{#unless isView}}

View File

@ -23,19 +23,44 @@
}}
{{/if}}
<div class="row">
<div class="col span-12">
<label class="acc-label">{{t 'cruStorageClass.provisioner.label'}}</label>
{{searchable-select
allowCustom=true
content=provisionerChoices
value=primaryResource.provisioner
readOnly=isView
}}
{{#if isView}}
<section>
<div class="row banner bg-info basics">
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'cruStorageClass.provisioner.label'}}</label>
{{primaryResource.provisioner}}
</div>
<div class="vertical-middle">
<label class="acc-label vertical-middle p-0">{{t 'generic.created'}}</label>
{{date-calendar primaryResource.created}}
</div>
</div>
</section>
{{else}}
<div class="row">
<div class="col span-12">
<label class="acc-label">{{t 'cruStorageClass.provisioner.label'}}</label>
{{searchable-select
allowCustom=true
content=provisionerChoices
value=primaryResource.provisioner
}}
</div>
</div>
</div>
{{/if}}
{{#accordion-list showExpandAll=false as | al expandFn |}}
{{#if isView}}
{{#accordion-list-item
title=(t 'cruStorageClass.pv.title')
detail=(t 'cruStorageClass.pv.detail')
expandAll=expandAll
expand=(action expandFn)
expandOnInit=true
}}
{{persistent-volume-table rows=persistentVolumes}}
{{/accordion-list-item}}
{{/if}}
{{#accordion-list-item
title=(t 'cruStorageClass.parameters.title')
detail=(t 'cruStorageClass.parameters.detail')
@ -119,6 +144,20 @@
</div>
</div>
{{/accordion-list-item}}
{{#if isView}}
{{labels-section
model=primaryResource
showKind=false
expandAll=al.expandAll
expandFn=expandFn
}}
{{annotations-section
model=primaryResource
expandAll=al.expandAll
expandFn=expandFn
}}
{{/if}}
{{/accordion-list}}
{{#unless isView}}

View File

@ -4,7 +4,7 @@
rule=rule
editing=editing}}
{{else if (not editing)}}
<div class="p-20">{{t 'formNodeAffinity.noRules'}}</div>
<div class="text-center text-muted lacsso pt-20 pb-20">{{t 'formNodeAffinity.noRules'}}</div>
{{/each}}
{{#if editing}}

View File

@ -1,43 +1,64 @@
import { observer } from '@ember/object';
import { computed, get, observer } from '@ember/object';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import ManageLabels from 'shared/mixins/manage-labels';
import layout from './template';
const HEADERS_WITH_KIND = [
{
name: 'kind',
sort: ['type', 'key'],
translationKey: 'labelsSection.kind',
width: '90',
},
{
name: 'key',
sort: ['key'],
translationKey: 'labelsSection.key',
width: '350',
},
{
name: 'value',
sort: ['value', 'key'],
translationKey: 'labelsSection.value',
},
];
const HEADERS = [
{
name: 'key',
sort: ['key'],
translationKey: 'labelsSection.key',
width: '350',
},
{
name: 'value',
sort: ['value', 'key'],
translationKey: 'labelsSection.value',
},
];
export default Component.extend(ManageLabels, {
layout,
model: null,
sortBy: 'kind',
showKind: true,
descending: true,
headers: [
{
name: 'kind',
sort: ['type', 'key'],
translationKey: 'labelsSection.kind',
width: '90',
},
{
name: 'key',
sort: ['key'],
translationKey: 'labelsSection.key',
width: '350',
},
{
name: 'value',
sort: ['value', 'key'],
translationKey: 'labelsSection.value',
},
],
sortBy: 'kind',
translationDetail: 'labelsSection.detail',
showKind: true,
descending: true,
labelSource: alias('model.labels'),
didReceiveAttrs() {
this.initLabels(this.get('labelSource'));
},
labelsObserver: observer('model.labels', function() {
this.initLabels(this.get('labelSource'));
}),
headers: computed('showKind', function() {
return get(this, 'showKind') ? HEADERS_WITH_KIND : HEADERS;
}),
});

View File

@ -1,6 +1,6 @@
{{#accordion-list-item
title=(t 'labelsSection.title')
detail=(t 'labelsSection.detail')
detail=(t translationDetail)
status=(t 'labelsSection.status' count=labelArray.length)
statusClass=(if labelArray.length 'bg-success' 'text-muted')
expandAll=expandAll
@ -27,6 +27,10 @@
<td data-title="{{t 'labelsSection.key'}}:" class="force-wrap">{{label.key}}</td>
<td data-title="{{t 'labelsSection.value'}}:" class="force-wrap">{{pretty-json value=label.value}}</td>
</tr>
{{else if (eq kind "nomatch")}}
<tr>
<td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'labelsSection.noMatch'}}</td>
</tr>
{{else if (eq kind "norows")}}
<tr>
<td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'labelsSection.noData'}}</td>

View File

@ -1,7 +1,8 @@
import Controller from '@ember/controller';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import layout from './template';
import { inject as service } from '@ember/service';
export const headers = [
const headers = [
{
name: 'state',
sort: ['sortState', 'displayName'],
@ -15,6 +16,12 @@ export const headers = [
searchField: 'displayName',
translationKey: 'generic.name',
},
{
name: 'displayPvc',
sort: ['displayPvc', 'sortName', 'id'],
searchField: 'displayPvc',
translationKey: 'cruPersistentVolume.pvc',
},
{
name: 'source',
sort: ['displaySource', 'name', 'id'],
@ -23,9 +30,15 @@ export const headers = [
},
];
export default Controller.extend({
queryParams: ['sortBy'],
sortBy: 'name',
export default Component.extend({
scope: service(),
layout,
headers,
rows: alias('model.persistentVolumes'),
tagName: '',
sortBy: 'name',
searchText: '',
subRows: true,
suffix: true,
paging: true,
});

View File

@ -0,0 +1,42 @@
{{#sortable-table
tableClassNames="bordered"
paging=true
pagingLabel="pagination.volume"
headers=headers
bulkActions=true
descending=descending
body=rows
sortBy=sortBy
as |sortable kind obj dt|
}}
{{#if (eq kind "row")}}
<tr class="main-row">
<td class="row-check" valign="middle" style="padding-top: 2px;">
{{check-box nodeId=obj.id}}
</td>
<td data-title="{{dt.state}}">
{{badge-state model=obj}}
</td>
<td data-title="{{dt.name}}">
<a href="{{href-to "authenticated.cluster.storage.persistent-volumes.detail" obj.id}}">{{obj.displayName}}</a>
</td>
<td data-title="{{dt.displayPvc}}">
{{#if obj.displayPvc}}
{{obj.displayPvc}}
{{else}}
<div class="text-muted">{{t 'generic.na'}}</div>
{{/if}}
</td>
<td data-title="{{dt.source}}">
{{obj.displaySource}}
</td>
<td data-title="{{dt.actions}}" class="actions">
{{action-menu model=obj}}
</td>
</tr>
{{else if (eq kind "nomatch")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'persistentVolumePage.noMatch'}}</td></tr>
{{else if (eq kind "norows")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'persistentVolumePage.noData'}}</td></tr>
{{/if}}
{{/sortable-table}}

View File

@ -14,6 +14,12 @@ export default Volume.extend({
return !!get(this, 'links.remove') && get(this, 'state') !== 'bound';
}),
displayPvc: computed('claimRef.namespace', 'claimRef.name', function() {
if ( get(this, 'claimRef.name') ) {
return `${ get(this, 'claimRef.namespace') }/${ get(this, 'claimRef.name') }`;
}
}),
actions: {
edit() {
get(this, 'router').transitionTo('authenticated.cluster.storage.persistent-volumes.detail.edit', get(this, 'id'));

View File

@ -1,17 +0,0 @@
import Controller from '@ember/controller';
export default Controller.extend({
labelHeaders: [
{
name: 'key',
sort: ['key'],
translationKey: 'labelsSection.key',
width: '350',
},
{
name: 'value',
sort: ['value', 'key'],
translationKey: 'labelsSection.value',
},
],
});

View File

@ -78,7 +78,6 @@
{{labels-section
model=model.node
showKind=false
headers=labelHeaders
expandAll=al.expandAll
expandFn=expandFn
}}

View File

@ -2282,6 +2282,8 @@ cruPersistentVolume:
storageClass:
label: Assign to Storage Class
prompt: None
pvc: Persistent Volume Claim
reclaimPolicy: Reclaim Policy
capacity:
label: Capacity
unit: GiB
@ -2642,6 +2644,9 @@ cruStorageClass:
view: 'Storage Class: {name}'
allowVolumeExpansion:
label: Allow users to expand volumes
pv:
title: Persistent Volumes
detail: Persistent Volumes provisioned by the current storage class.
mountOptions:
label: Mount Options
addActionLabel: Add Option
@ -4302,6 +4307,7 @@ labelsSection:
key: Key
value: Value
noData: No labels
noMatch: No labels match the current search
loginShibboleth:
buttonText: Log In with Shibboleth