mirror of https://github.com/rancher/ui.git
Merge pull request #2230 from loganhz/pv
Improve pv list and pv detail page
This commit is contained in:
commit
30f81e76ef
|
|
@ -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*/) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{{cru-storage-class
|
||||
mode="view"
|
||||
model=model
|
||||
model=model.storageclass
|
||||
persistentVolumes=model.persistentVolumes
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}),
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
@ -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}}
|
||||
|
|
@ -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'));
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -78,7 +78,6 @@
|
|||
{{labels-section
|
||||
model=model.node
|
||||
showKind=false
|
||||
headers=labelHeaders
|
||||
expandAll=al.expandAll
|
||||
expandFn=expandFn
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue