mirror of https://github.com/rancher/ui.git
Implemented CRUD for project
This commit is contained in:
parent
e761fefd8e
commit
bb9e744ccf
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { hash } from 'rsvp';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import Route from '@ember/routing/route';
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
authzStore: service('authz-store'),
|
||||||
|
model: function (params) {
|
||||||
|
return hash({
|
||||||
|
project: this.get('authzStore').find('project', params.project_id),
|
||||||
|
projectRoleTemplateBindings: this.get('authzStore').findAll('projectRoleTemplateBinding', null, { filter: { projectId: params.project_id } }),
|
||||||
|
projects: this.get('authzStore').findAll('project'),
|
||||||
|
roles: this.get('authzStore').findAll('projectRoleTemplate'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{{new-edit-project model=model editing=true}}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import Route from '@ember/routing/route';
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
authzStore: service('authz-store'),
|
||||||
|
model: function () {
|
||||||
|
return this.get('authzStore').findAll('project').then(projects => {
|
||||||
|
return {
|
||||||
|
projects
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<section class="header clearfix">
|
||||||
|
<h1 class="pull-left">{{t 'projectsPage.header'}}</h1>
|
||||||
|
<div class="vertical-middle"></div>
|
||||||
|
|
||||||
|
<div class="right-buttons">
|
||||||
|
{{#link-to "authenticated.projects.new" class="btn bg-primary btn-sm icon-btn"}}
|
||||||
|
<span class="darken">
|
||||||
|
<i class="icon icon-folder"></i>
|
||||||
|
</span>
|
||||||
|
<span>{{t 'projectsPage.addProject'}}</span>
|
||||||
|
{{/link-to}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{project-table model=model.projects}}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { hash } from 'rsvp';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import Route from '@ember/routing/route';
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
authzStore: service('authz-store'),
|
||||||
|
model: function () {
|
||||||
|
const project = this.get('authzStore').createRecord({
|
||||||
|
type: `project`,
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
const projectRoleTemplateBindings = [{
|
||||||
|
subjectKind: 'User',
|
||||||
|
subjectName: '',
|
||||||
|
projectRoleTemplateId: '',
|
||||||
|
projectId: '',
|
||||||
|
}];
|
||||||
|
return hash({
|
||||||
|
project,
|
||||||
|
projectRoleTemplateBindings,
|
||||||
|
projects: this.get('authzStore').findAll('project'),
|
||||||
|
roles: this.get('authzStore').findAll('projectRoleTemplate'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{{new-edit-project model=model editing=false}}
|
||||||
|
|
@ -32,17 +32,7 @@ var Project = Resource.extend(PolledResource, {
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
edit: function() {
|
edit: function() {
|
||||||
this.get('router').transitionTo('authenticated.clusters.project', this.get('id'));
|
this.get('router').transitionTo('authenticated.projects.edit', this.get('id'));
|
||||||
},
|
|
||||||
|
|
||||||
delete: function() {
|
|
||||||
return this.delete().then(() => {
|
|
||||||
// If you're in the project that was deleted, go back to the default project
|
|
||||||
if ( this.get('active') )
|
|
||||||
{
|
|
||||||
window.location.href = window.location.href;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate: function() {
|
activate: function() {
|
||||||
|
|
@ -85,14 +75,9 @@ var Project = Resource.extend(PolledResource, {
|
||||||
let l = this.get('links');
|
let l = this.get('links');
|
||||||
|
|
||||||
var choices = [
|
var choices = [
|
||||||
{ label: 'action.setDefault', icon: 'icon icon-star-fill', action: 'setAsDefault', enabled: this.get('canSetDefault')},
|
{ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: true},
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: !!l.update },
|
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: true, altAction: 'delete', bulkable: true },
|
||||||
{ divider: true },
|
|
||||||
{ label: 'action.activate', icon: 'icon icon-play', action: 'activate', enabled: !!a.activate, bulkable: true},
|
|
||||||
{ label: 'action.deactivate', icon: 'icon icon-pause', action: 'promptStop', enabled: !!a.deactivate, altAction: 'deactivate', bulkable: true},
|
|
||||||
{ divider: true },
|
|
||||||
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove, altAction: 'delete', bulkable: true },
|
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true },
|
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true },
|
||||||
];
|
];
|
||||||
|
|
@ -100,6 +85,15 @@ var Project = Resource.extend(PolledResource, {
|
||||||
return choices;
|
return choices;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
delete: function (/*arguments*/) {
|
||||||
|
var promise = this._super.apply(this, arguments);
|
||||||
|
return promise.then(() => {
|
||||||
|
this.set('state', 'removed');
|
||||||
|
}).catch((err) => {
|
||||||
|
this.get('growl').fromError('Error deleting', err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
icon: computed('active', function() {
|
icon: computed('active', function() {
|
||||||
if ( this.get('active') )
|
if ( this.get('active') )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,12 @@ Router.map(function() {
|
||||||
|
|
||||||
this.route('prefs');
|
this.route('prefs');
|
||||||
|
|
||||||
|
this.route('projects', {path: '/projects'}, function() {
|
||||||
|
this.route('index', {path: '/'});
|
||||||
|
this.route('edit', {path: '/:project_id'});
|
||||||
|
this.route('new', {path: '/add'});
|
||||||
|
});
|
||||||
|
|
||||||
// Clusters
|
// Clusters
|
||||||
this.route('clusters', {path: '/clusters'}, function() {
|
this.route('clusters', {path: '/clusters'}, function() {
|
||||||
this.route('index', {path: '/'});
|
this.route('index', {path: '/'});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
import { alias } from '@ember/object/computed';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { reject, all as PromiseAll } from 'rsvp';
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import NewOrEdit from 'ui/mixins/new-or-edit';
|
||||||
|
import layout from './template';
|
||||||
|
|
||||||
|
export default Component.extend(NewOrEdit, {
|
||||||
|
layout,
|
||||||
|
intl: service(),
|
||||||
|
router: service(),
|
||||||
|
authzStore: service('authz-store'),
|
||||||
|
model: null,
|
||||||
|
|
||||||
|
primaryResource: alias('model.project'),
|
||||||
|
memberArray: alias('model.projectRoleTemplateBindings'),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
cancel() {
|
||||||
|
this.goBack();
|
||||||
|
},
|
||||||
|
addMember(kind) {
|
||||||
|
this.get('memberArray').pushObject({
|
||||||
|
subjectKind: kind,
|
||||||
|
subjectName: '',
|
||||||
|
projectRoleTemplateId: '',
|
||||||
|
projectId: '',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeMember(obj) {
|
||||||
|
this.get('memberArray').removeObject(obj);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
goBack: function () {
|
||||||
|
this.get('router').transitionTo('/projects');
|
||||||
|
},
|
||||||
|
|
||||||
|
doesNameExist() {
|
||||||
|
const project = this.get('primaryResource');
|
||||||
|
const currentProjects = this.get('model.projects');
|
||||||
|
|
||||||
|
if (currentProjects.findBy('name', project.get('name'))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
doseMemberNameInvalid() {
|
||||||
|
const members = this.get('memberArray');
|
||||||
|
return members.any(r => r.subjectName.length === 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
doseMemberRoleInvalid() {
|
||||||
|
const members = this.get('memberArray');
|
||||||
|
return members.any(r => r.projectRoleTemplateId.length === 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
validate: function () {
|
||||||
|
var errors = this.get('errors', errors) || [];
|
||||||
|
|
||||||
|
if ((this.get('model.project.name') || '').trim().length === 0) {
|
||||||
|
errors.push(this.get('intl').findTranslationByKey('projectsPage.new.errors.nameReq'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.get('editing') && this.doesNameExist()) {
|
||||||
|
errors.push(this.get('intl').findTranslationByKey('projectsPage.new.errors.nameInExists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.doseMemberNameInvalid()) {
|
||||||
|
errors.push(this.get('intl').findTranslationByKey('projectsPage.new.errors.memberNameReq'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.doseMemberRoleInvalid()) {
|
||||||
|
errors.push(this.get('intl').findTranslationByKey('projectsPage.new.errors.memberRoleReq'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.length) {
|
||||||
|
this.set('errors', errors.uniq());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.set('errors', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
doSave() {
|
||||||
|
return this._super.apply(this, arguments).then((project) => {
|
||||||
|
const projectId = project.id;
|
||||||
|
const members = this.get('memberArray');
|
||||||
|
const promises = [];
|
||||||
|
members.forEach(member => {
|
||||||
|
member.projectId = projectId;
|
||||||
|
const promise = this.get('authzStore').rawRequest({
|
||||||
|
url: 'projectroletemplatebinding',
|
||||||
|
method: 'POST',
|
||||||
|
data: member,
|
||||||
|
});
|
||||||
|
promises.push(promise);
|
||||||
|
});
|
||||||
|
return PromiseAll(promises).catch((error) => {
|
||||||
|
return reject(error.body.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
doneSaving() {
|
||||||
|
this.goBack();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<section class="header clearfix">
|
||||||
|
<div class="pull-left">
|
||||||
|
{{#if editing}}
|
||||||
|
<h1>{{t 'projectsPage.editProject'}}</h1>
|
||||||
|
{{else}}
|
||||||
|
<h1>{{t 'projectsPage.addProject'}}</h1>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="horizontal-form container-fluid">
|
||||||
|
{{form-name-description
|
||||||
|
name=model.project.name
|
||||||
|
nameLabel="projectsPage.new.form.name.label"
|
||||||
|
nameRequired=true
|
||||||
|
nameDisabled=editing
|
||||||
|
namePlaceholder="projectsPage.new.form.name.placeholder"
|
||||||
|
colClass="col span-7"
|
||||||
|
descriptionShown=false
|
||||||
|
}}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="horizontal-form container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-3">
|
||||||
|
<label class="pb-5 acc-label">{{t 'projectsPage.new.form.members.labelText'}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pl-10 pr-10">
|
||||||
|
<table class="table fixed no-lines">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="150">{{t 'projectsPage.new.form.members.kind.label'}}</th>
|
||||||
|
<th>{{t 'projectsPage.new.form.members.name.label'}}</th>
|
||||||
|
<th>{{t 'projectsPage.new.form.members.role.label'}}</th>
|
||||||
|
<th width="10"> </th>
|
||||||
|
<th width="40"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each memberArray as |member|}}
|
||||||
|
{{project-member-row member=member roles=model.roles remove="removeMember"}}
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5">
|
||||||
|
<button class="btn bg-link icon-btn p-0" {{action "addMember" "User"}}>
|
||||||
|
<span class="darken"><i class="icon icon-plus text-small"/></span>
|
||||||
|
<span>{{t 'projectsPage.new.form.members.addUser'}}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn bg-link icon-btn p-0" {{action "addMember" "Group"}}>
|
||||||
|
<span class="darken"><i class="icon icon-plus text-small"/></span>
|
||||||
|
<span>{{t 'projectsPage.new.form.members.addGroup'}}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn bg-link icon-btn p-0" {{action "addMember" "ServiceAccount"}}>
|
||||||
|
<span class="darken"><i class="icon icon-plus text-small"/></span>
|
||||||
|
<span>{{t 'projectsPage.new.form.members.addServiceAccount'}}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{{top-errors errors=errors}}
|
||||||
|
{{save-cancel createLabel=(if editing 'projectsPage.saveEdit' 'projectsPage.saveNew') save="save" cancel="cancel"}}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import layout from './template';
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
layout,
|
||||||
|
member: null,
|
||||||
|
roles: null,
|
||||||
|
|
||||||
|
tagName: 'TR',
|
||||||
|
classNames: 'main-row',
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
remove: function () {
|
||||||
|
this.sendAction('remove', this.get('member'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function () {
|
||||||
|
this._super(...arguments);
|
||||||
|
this.set('choices', this.get('roles').map(role => {
|
||||||
|
return {
|
||||||
|
label: role.name,
|
||||||
|
value: role.id,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
kind: function() {
|
||||||
|
return `projectsPage.new.form.members.${this.get('member.subjectKind').toLowerCase()}`
|
||||||
|
}.property('member.subjectKind')
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<td class="pr-20">
|
||||||
|
{{t kind}}
|
||||||
|
</td>
|
||||||
|
<td class="pr-20">
|
||||||
|
{{input type="text" value=member.subjectName classNames="form-control"}}
|
||||||
|
</td>
|
||||||
|
<td class="pr-20">
|
||||||
|
{{searchable-select content=choices value=member.projectRoleTemplateId}}
|
||||||
|
</td>
|
||||||
|
<td> </td>
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button class="btn bg-primary btn-sm" {{action "remove"}}>
|
||||||
|
<i class="icon icon-minus" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
@ -1,18 +1,8 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import layout from './template';
|
import layout from './template';
|
||||||
import { inject as service } from '@ember/service'
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
layout,
|
layout,
|
||||||
model: null,
|
model: null,
|
||||||
tagName: 'TR',
|
tagName: 'TR',
|
||||||
showCluster: false,
|
|
||||||
scope: service(),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
switchTo(id) {
|
|
||||||
// @TODO bad
|
|
||||||
window.lc('authenticated').send('switchProject', id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,12 @@
|
||||||
{{#if bulkActions}}
|
<td valign="middle" class="row-check" style="padding-top: 2px;">
|
||||||
<td valign="middle" class="row-check" style="padding-top: 2px;">
|
|
||||||
{{check-box nodeId=model.id}}
|
|
||||||
</td>
|
|
||||||
{{/if}}
|
|
||||||
<td data-title="{{dt.state}}" class="state">
|
|
||||||
{{badge-state model=model}}
|
|
||||||
</td>
|
</td>
|
||||||
{{#if showCluster}}
|
<td data-title="{{t 'projects.table.project.label'}}:" class="clip">
|
||||||
<td data-title="{{dt.cluster}}">
|
{{#link-to "authenticated.projects.edit" model.id }} {{model.name}} {{/link-to}}
|
||||||
<a href="{{href-to 'authenticated.clusters.cluster.index' model.cluster.id}}">{{model.cluster.displayName}}</a>
|
|
||||||
</td>
|
|
||||||
{{/if}}
|
|
||||||
<td data-title="{{dt.name}}">
|
|
||||||
<a href="{{href-to 'authenticated.project.index' model.id}}" {{action "switchTo" model.id}}>{{model.displayName}}</a>
|
|
||||||
</td>
|
</td>
|
||||||
<td colspan="3" class="text-center text-muted">
|
<td data-title="{{t 'projects.table.created.label'}}:">
|
||||||
Counts Coming Soon
|
{{date-calendar model.created}}
|
||||||
</td>
|
</td>
|
||||||
<!--
|
<td data-title="{{t 'generic.actions'}}:" class="actions">
|
||||||
<td data-title="{{dt.stacks}}" class="text-center">
|
|
||||||
{{model.numStacks}}
|
|
||||||
</td>
|
|
||||||
<td data-title="{{dt.services}}" class="text-center">
|
|
||||||
{{model.numServices}}
|
|
||||||
</td>
|
|
||||||
<td data-title="{{dt.containers}}" class="text-center">
|
|
||||||
{{model.numContainers}}
|
|
||||||
</td>
|
|
||||||
-->
|
|
||||||
<td data-title="{{dt.default}}" class="text-center">
|
|
||||||
{{#if model.isDefault}}<i class="icon icon-star-fill"></i>{{else}}<span class="text-muted">–</span>{{/if}}
|
|
||||||
</td>
|
|
||||||
<td data-title="{{dt.actions}} "class="actions">
|
|
||||||
{{action-menu model=model}}
|
{{action-menu model=model}}
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -1,70 +1,21 @@
|
||||||
import { computed } from '@ember/object';
|
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import layout from './template';
|
import layout from './template';
|
||||||
|
|
||||||
const headersWithCluster = [
|
const headers = [{
|
||||||
{
|
|
||||||
name: 'state',
|
|
||||||
sort: ['sortState','name','id'],
|
|
||||||
translationKey: 'generic.state',
|
|
||||||
width: 125,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'cluster',
|
|
||||||
sort: ['cluster.displayName','displayName','id'],
|
|
||||||
translationKey: 'clustersPage.cluster.label',
|
|
||||||
searchField: ['cluster.displayName'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'name',
|
name: 'name',
|
||||||
sort: ['displayName','id'],
|
sort: ['name'],
|
||||||
translationKey: 'clustersPage.environment.label',
|
translationKey: 'projectsPage.table.header.project.label',
|
||||||
searchField: ['displayName'],
|
},{
|
||||||
},
|
name: 'created',
|
||||||
{
|
sort: ['created'],
|
||||||
name: 'stacks',
|
translationKey: 'projectsPage.table.header.created.label',
|
||||||
sort: ['numStacks','name','id'],
|
width: '125',
|
||||||
translationKey: 'generic.stacks',
|
|
||||||
width: 100,
|
|
||||||
classNames: 'text-center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'services',
|
|
||||||
sort: ['numServices','name','id'],
|
|
||||||
translationKey: 'generic.services',
|
|
||||||
width: 100,
|
|
||||||
classNames: 'text-center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'containers',
|
|
||||||
sort: ['numContainers','name','id'],
|
|
||||||
translationKey: 'generic.containers',
|
|
||||||
width: 120,
|
|
||||||
classNames: 'text-center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
sort: false,
|
|
||||||
translationKey: 'clusterRow.loginDefault',
|
|
||||||
width: 60,
|
|
||||||
classNames: 'text-center',
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const headersWithoutCluster = headersWithCluster.filter(x => x.name !== 'cluster');
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
layout,
|
layout,
|
||||||
tagName: '',
|
tagName: '',
|
||||||
showCluster: false,
|
headers,
|
||||||
bulkActions: true,
|
sortBy: 'name',
|
||||||
search: true,
|
|
||||||
|
|
||||||
headers: computed('showCluster', function() {
|
|
||||||
if ( this.get('showCluster') ) {
|
|
||||||
return headersWithCluster;
|
|
||||||
} else {
|
|
||||||
return headersWithoutCluster;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,18 @@
|
||||||
{{#sortable-table
|
{{#sortable-table
|
||||||
tableClassNames="bordered"
|
tableClassNames="bordered"
|
||||||
bulkActions=bulkActions
|
|
||||||
paging=true
|
paging=true
|
||||||
pagingLabel="pagination.project"
|
pagingLabel="pagination.project"
|
||||||
search=search
|
|
||||||
sortBy=sortBy
|
|
||||||
descending=descending
|
|
||||||
headers=headers
|
headers=headers
|
||||||
body=model
|
body=model
|
||||||
|
sortBy=sortBy
|
||||||
fullRows=true
|
fullRows=true
|
||||||
stickyHeader=false
|
|
||||||
as |sortable kind p dt|
|
as |sortable kind p dt|
|
||||||
}}
|
}}
|
||||||
{{#if (eq kind "row")}}
|
{{#if (eq kind "row")}}
|
||||||
{{project-row model=p dt=dt showCluster=showCluster search=search bulkActions=bulkActions}}
|
{{project-row model=p dt=dt}}
|
||||||
{{else if (eq kind "nomatch")}}
|
{{else if (eq kind "nomatch")}}
|
||||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'clusterRow.noMatch'}}</td></tr>
|
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'projectsPage.table.noMatch'}}</td></tr>
|
||||||
{{else if (eq kind "norows")}}
|
{{else if (eq kind "norows")}}
|
||||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'clusterRow.noData'}}</td></tr>
|
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'projectsPage.table.noData'}}</td></tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/sortable-table}}
|
{{/sortable-table}}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ export const getClusterId = function() { return this.get('clusterId'); };
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
const navTree = [
|
const navTree = [
|
||||||
|
{
|
||||||
|
route: 'authenticated.projects.index',
|
||||||
|
localizedLabel: 'projectsPage.header'
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export function addItem(opt) {
|
export function addItem(opt) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'shared/components/new-edit-project/component';
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'shared/components/project-member-row/component';
|
||||||
|
|
@ -497,6 +497,45 @@ certificatesPage:
|
||||||
description:
|
description:
|
||||||
placeholder: e.g. EV cert for mydomain.com
|
placeholder: e.g. EV cert for mydomain.com
|
||||||
|
|
||||||
|
projectsPage:
|
||||||
|
header: Projects
|
||||||
|
addProject: Add Project
|
||||||
|
editProject: Edit Project
|
||||||
|
saveEdit: Edit
|
||||||
|
saveNew: Create
|
||||||
|
table:
|
||||||
|
noMatch: No projects match the current search.
|
||||||
|
noData: This cluster doesn't have any projects yet.
|
||||||
|
header:
|
||||||
|
project:
|
||||||
|
label: Project Name
|
||||||
|
created:
|
||||||
|
label: Created
|
||||||
|
new:
|
||||||
|
form:
|
||||||
|
name:
|
||||||
|
placeholder: e.g. lab
|
||||||
|
label: Project Name
|
||||||
|
members:
|
||||||
|
user: User
|
||||||
|
group: Group
|
||||||
|
serviceaccount: Service Account
|
||||||
|
labelText: Members
|
||||||
|
addUser: Add User
|
||||||
|
addGroup: Add Group
|
||||||
|
addServiceAccount: Add Service Account
|
||||||
|
kind:
|
||||||
|
label: Kind
|
||||||
|
name:
|
||||||
|
label: Name
|
||||||
|
role:
|
||||||
|
label: Role
|
||||||
|
errors:
|
||||||
|
nameReq: Name is requried.
|
||||||
|
nameInExists: Name is already exists. Please use a new project name.
|
||||||
|
memberNameReq: Name is requried for a member
|
||||||
|
memberRoleReq: Role is requried for a member
|
||||||
|
|
||||||
clustersPage:
|
clustersPage:
|
||||||
header: Clusters
|
header: Clusters
|
||||||
newCluster: Add Cluster
|
newCluster: Add Cluster
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue