mirror of https://github.com/rancher/ui.git
commit
b3b0375c48
|
|
@ -1,10 +1,10 @@
|
|||
import { computed } from '@ember/object';
|
||||
import { get, computed, set } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Controller from '@ember/controller';
|
||||
|
||||
export default Controller.extend({
|
||||
access: service(),
|
||||
sortBy: 'name',
|
||||
sortBy: null,
|
||||
headers: computed('isLocal', function() {
|
||||
let out = [
|
||||
{
|
||||
|
|
@ -26,6 +26,11 @@ export default Controller.extend({
|
|||
return out;
|
||||
}),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
set(this, 'sortBy', get(this, 'isLocal') ? 'username' : 'name');
|
||||
},
|
||||
|
||||
isLocal: computed('access.provider', function() {
|
||||
return true; // TODO 2.0
|
||||
// return this.get('access.provider') === 'localauthconfig';
|
||||
|
|
|
|||
|
|
@ -24,14 +24,4 @@ export default Route.extend({
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
this._super(...arguments);
|
||||
|
||||
controller.set('errors', null);
|
||||
|
||||
let bindings = (get(model,'cluster.clusterRoleTemplateBindings')||[]).slice();
|
||||
bindings = bindings.filter(x =>get(x, 'name') !== 'creator');
|
||||
set(controller, 'memberArray', bindings);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,10 +21,9 @@
|
|||
}}
|
||||
{{form-members
|
||||
creator=model.me
|
||||
editing=false
|
||||
memberArray=memberArray
|
||||
editing=true
|
||||
memberConfig=memberConfig
|
||||
project=primaryResource
|
||||
primaryResource=primaryResource
|
||||
roles=model.roles
|
||||
users=model.users
|
||||
type="cluster"
|
||||
|
|
|
|||
|
|
@ -112,9 +112,8 @@
|
|||
{{form-members
|
||||
creator=model.me
|
||||
editing=false
|
||||
memberArray=memberArray
|
||||
memberConfig=memberConfig
|
||||
project=primaryResource
|
||||
primaryResource=primaryResource
|
||||
roles=model.roles
|
||||
users=model.users
|
||||
type="cluster"
|
||||
|
|
|
|||
|
|
@ -1,54 +1,115 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
import { computed, observer, get, set } from '@ember/object';
|
||||
import { on } from '@ember/object/evented';
|
||||
import { computed, get, set, setProperties } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { all as PromiseAll } from 'rsvp';
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
globalStore: service(),
|
||||
access: service(),
|
||||
globalStore: service(),
|
||||
access: service(),
|
||||
|
||||
editing: false,
|
||||
memberArray: null,
|
||||
memberConfig: null,
|
||||
model: null,
|
||||
project: null,
|
||||
roles: null,
|
||||
type: null,
|
||||
users: null,
|
||||
creator: null,
|
||||
showCreator: true,
|
||||
|
||||
toAdd: null,
|
||||
toUpdate: null,
|
||||
toRemove: null,
|
||||
editing: false,
|
||||
memberArray: null,
|
||||
memberConfig: null,
|
||||
model: null,
|
||||
primaryResource: null,
|
||||
roles: null,
|
||||
type: null,
|
||||
users: null,
|
||||
creator: null,
|
||||
showCreator: true,
|
||||
toAddCustom: null,
|
||||
_bindings: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
set(this, 'toAdd', []);
|
||||
set(this, 'toUpdate', []);
|
||||
set(this, 'toRemove', []);
|
||||
this.buildUpdateList(get(this,'primaryResource'))
|
||||
this.sendAction('initAlert', this.primaryResourceSaved.bind(this));
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
let ma = get(this, 'memberArray').filter(( m ) => {
|
||||
return get(m, 'roleTemplateId').indexOf('-owner') < 0 && !get(this, 'toAdd').includes(m);
|
||||
});
|
||||
if (ma && get(ma, 'length') > 0) {
|
||||
set(this, 'toUpdate', ma);
|
||||
buildUpdateList(resource) {
|
||||
let bindingType = `${get(resource, 'type')}RoleTemplateBindings`;
|
||||
let bindings = get(resource, bindingType).filter(b => b.name !== 'creator');
|
||||
let existing = [];
|
||||
let grouped = {};
|
||||
set(this, "_bindings", bindings.slice());
|
||||
if (bindings && get(this, 'editing')) {
|
||||
bindings.forEach((b) => {
|
||||
if (grouped[get(b, 'subjectName')]) {
|
||||
grouped[get(b, 'subjectName')].push(b);
|
||||
} else {
|
||||
grouped[get(b, 'subjectName')] = [b];
|
||||
}
|
||||
});
|
||||
|
||||
if (grouped) {
|
||||
Object.keys(grouped).forEach((g) => {
|
||||
if (grouped[g].length >1) {
|
||||
let idsOut = [];
|
||||
grouped[g].forEach((m) => {
|
||||
idsOut.push(get(m, 'roleTemplateId'))
|
||||
});
|
||||
let config = get(this, 'memberConfig');
|
||||
set(config, 'subjectKind', 'User'); //should be upper but make sure
|
||||
set(config, 'subjectName', g);
|
||||
let record = get(this,'globalStore').createRecord(config);
|
||||
|
||||
let out = {
|
||||
role: record,
|
||||
toUpdate: false,
|
||||
toAdd: false,
|
||||
toDelete: false,
|
||||
customRolesExisting: idsOut
|
||||
}
|
||||
|
||||
existing.push(out);
|
||||
} else {
|
||||
existing.push({
|
||||
role: grouped[g][0],
|
||||
toUpdate: true,
|
||||
toAdd: false,
|
||||
toDelete: false,
|
||||
id: Math.random()
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
set(this, 'memberArray', existing);
|
||||
},
|
||||
|
||||
primaryResourceSaved: function() {
|
||||
// returns a promise of all the adds/removes/updates to the parent
|
||||
const pr = get(this, 'project');
|
||||
const pr = get(this, 'primaryResource');
|
||||
const resourceId = get(pr, 'id');
|
||||
const add = (get(this, 'toAdd')||[]);
|
||||
const update = get(this, 'toUpdate')||[];
|
||||
const remove = get(this, 'toRemove')||[];
|
||||
const memberArray = get(this, 'memberArray').slice();
|
||||
|
||||
const customToAdd = memberArray.filterBy('customRolesToAdd');
|
||||
const customToRemove = memberArray.filterBy('customRolesToRemove');
|
||||
|
||||
const add = get(this, 'memberArray').filter(r => get(r, 'toAdd') && !get(r, 'customRolesToAdd')).map(a => a.role);
|
||||
const update = get(this, 'memberArray').filterBy('toUpdate', true).map(u => u.role);
|
||||
const remove = get(this, 'memberArray').filterBy('toDelete', true).map(r => r.role);
|
||||
|
||||
customToRemove.forEach((rm) => {
|
||||
// custom obj from custom
|
||||
get(rm, 'customRolesToRemove').forEach((roleTempId) => {
|
||||
let match = get(this, '_bindings').find((binding) => {
|
||||
if (get(binding, 'roleTemplateId') === roleTempId) {
|
||||
return binding;
|
||||
}
|
||||
});
|
||||
remove.push(match);
|
||||
});
|
||||
});
|
||||
customToAdd.forEach((m) => {
|
||||
get(m, 'customRolesToAdd').forEach((a) => {
|
||||
let role = get(m, 'role').clone();
|
||||
set(role, 'roleTemplateId', a);
|
||||
add.addObject(role);
|
||||
})
|
||||
});
|
||||
|
||||
add.forEach((x) => {
|
||||
x.set(`${get(this, 'type')}Id`, resourceId);
|
||||
|
|
@ -58,6 +119,7 @@ export default Component.extend({
|
|||
return PromiseAll(add.map(x => x.save())).then(() => {
|
||||
return PromiseAll(update.map(x => x.save())).then(() => {
|
||||
return PromiseAll(remove.map(x => x.delete())).then(() => {
|
||||
set(this, 'memberArray', []);
|
||||
return pr;
|
||||
});
|
||||
});
|
||||
|
|
@ -65,6 +127,11 @@ export default Component.extend({
|
|||
},
|
||||
|
||||
actions: {
|
||||
setCustomToAdd(member, customIds, customIdsRemove) {
|
||||
set(member, 'customRolesToAdd', customIds);
|
||||
set(member, 'customRolesToRemove', customIdsRemove);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.goBack();
|
||||
},
|
||||
|
|
@ -74,18 +141,37 @@ export default Component.extend({
|
|||
set(config, 'subjectKind', kind.capitalize()); //should be upper but make sure
|
||||
// not setting the name correctly
|
||||
let record = get(this,'globalStore').createRecord(config);
|
||||
get(this,'memberArray').pushObject(record);
|
||||
get(this, 'toAdd').pushObject(record);
|
||||
let out = {
|
||||
role: record,
|
||||
toAdd: true,
|
||||
toUpate: false,
|
||||
toDelete: false,
|
||||
id: Math.random()
|
||||
};
|
||||
get(this,'memberArray').pushObject(out);
|
||||
},
|
||||
|
||||
removeMember(obj) {
|
||||
get(this,'memberArray').removeObject(obj);
|
||||
get(this, 'toRemove').pushObject(obj);
|
||||
let exists = get(this, 'memberArray').findBy('id', get(obj, 'id'));
|
||||
if (get(obj, 'toAdd') && exists) {
|
||||
// we just added and should remove it because the record has not been persisted yet
|
||||
get(this,'memberArray').removeObject(obj);
|
||||
} else if (exists) {
|
||||
setProperties(exists, {
|
||||
toAdd: false,
|
||||
toUpdate: false,
|
||||
toDelete: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
filteredUsers: computed('users.@each.{id,state}', function() {
|
||||
return get(this, 'users').sortBy('displayName');
|
||||
let users = get(this, 'users');
|
||||
if (get(this, 'editing')) {
|
||||
users = users.filter(u => !u.hasOwnProperty('me'));
|
||||
}
|
||||
return users.sortBy('displayName');
|
||||
}),
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,9 +10,25 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{project-member-row member=member roles=roles users=users owner=creator type=type}}
|
||||
{{project-member-row
|
||||
roles=roles
|
||||
users=users
|
||||
owner=creator
|
||||
type=type
|
||||
}}
|
||||
{{#each memberArray as |member|}}
|
||||
{{project-member-row member=member roles=roles users=filteredUsers remove="removeMember" }}
|
||||
{{#unless member.toDelete}}
|
||||
{{project-member-row
|
||||
member=member
|
||||
editing=editing
|
||||
resource=primaryResource
|
||||
roles=roles
|
||||
users=filteredUsers
|
||||
pageType=primaryResource.type
|
||||
remove="removeMember"
|
||||
alertNewCustoms=(action "setCustomToAdd")
|
||||
}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
{{#accordion-list-item
|
||||
title=(t 'formScopedRoles.title' type=cTyped)
|
||||
detail=(t 'formScopedRoles.description')
|
||||
detail=(t 'formScopedRoles.description' type=cTyped)
|
||||
expandOnInit=true
|
||||
showExpand=false
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import Component from '@ember/component';
|
||||
import ModalBase from 'shared/mixins/modal-base';
|
||||
import layout from './template';
|
||||
import { get, set } from '@ember/object';
|
||||
import { alias } from 'ember-computed';
|
||||
|
||||
export default Component.extend(ModalBase, {
|
||||
layout,
|
||||
classNames: ['small-modal'],
|
||||
type: alias('modalOpts.type'),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
let custom = get(this, 'modalOpts.roles').filterBy('hidden', false).filter((role) => {
|
||||
return role.get('id') !== `${get(this, 'type')}-owner` && role.get('id') !== `${get(this, 'type')}-member`;
|
||||
}).map((role) => {
|
||||
let binding = null;
|
||||
if ( get(this, 'modalOpts.current') ) {
|
||||
binding = get(this, 'modalOpts.current').findBy('roleTemplateId', get(role, 'id'));
|
||||
}
|
||||
return {
|
||||
role,
|
||||
active: !!binding,
|
||||
existing: binding,
|
||||
}
|
||||
});
|
||||
set(this, 'custom', custom)
|
||||
},
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
get(this, 'modalOpts.done')(get(this, 'custom'));
|
||||
this.get('modalService').toggleModal();
|
||||
},
|
||||
|
||||
completed() {
|
||||
this.get('modalService').toggleModal();
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.get('modalService').toggleModal();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<section class="header">
|
||||
<h1>Custom Roles</h1>
|
||||
</section>
|
||||
<section>
|
||||
{{#accordion-list-item
|
||||
title=(t 'formScopedRoles.title' type=type)
|
||||
detail=(t 'formScopedRoles.description' type=type)
|
||||
expandOnInit=true
|
||||
showExpand=false
|
||||
}}
|
||||
<div class="pl-20">
|
||||
{{#each custom as |row|}}
|
||||
<div class="box p-10 mt-5 mb-5">
|
||||
<label>
|
||||
{{input type="checkbox" checked=row.active}} {{row.role.displayName}}
|
||||
<p class="help-block">{{row.role.detail}}</p>
|
||||
</label>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/accordion-list-item}}
|
||||
</section>
|
||||
|
||||
{{save-cancel save="save" cancel="goBack" createLabel="generic.save"}}
|
||||
|
|
@ -33,9 +33,8 @@
|
|||
{{form-members
|
||||
creator=creator
|
||||
editing=editing
|
||||
memberArray=memberArray
|
||||
memberConfig=memberConfig
|
||||
project=primaryResource
|
||||
primaryResource=primaryResource
|
||||
roles=model.roles
|
||||
users=model.users
|
||||
type="project"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,23 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
import { computed, observer, get, set } from '@ember/object';
|
||||
import { computed, get, observer, set, setProperties } from '@ember/object';
|
||||
import { on } from '@ember/object/evented';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
const BASIC_ROLES = [
|
||||
{
|
||||
label: 'Standard User',
|
||||
value: 'member',
|
||||
},
|
||||
{
|
||||
label: 'Admin',
|
||||
value: 'owner',
|
||||
},
|
||||
{
|
||||
label: 'Custom',
|
||||
value: 'custom',
|
||||
},
|
||||
];
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
|
|
@ -12,23 +28,77 @@ export default Component.extend({
|
|||
roles: null,
|
||||
owner: null,
|
||||
type: null,
|
||||
pageType: null,
|
||||
modalService: service('modal'),
|
||||
hasCustom: false,
|
||||
customRoles: null,
|
||||
|
||||
actions: {
|
||||
showEdit(member) {
|
||||
if (get(member, 'role.roleTemplateId') === 'custom'){
|
||||
this.openModal();
|
||||
} else {
|
||||
set(member, 'role.roleTemplateId', 'custom');
|
||||
}
|
||||
},
|
||||
remove: function () {
|
||||
this.sendAction('remove', get(this,'member'));
|
||||
}
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._super(...arguments);
|
||||
set(this, 'choices', get(this,'roles').filterBy('hidden', false).map(role => {
|
||||
return {
|
||||
label: role.name,
|
||||
value: role.id,
|
||||
};
|
||||
}));
|
||||
doneAdding(customs) {
|
||||
setProperties(this, {
|
||||
hasCustom: true,
|
||||
customRoles: customs
|
||||
});
|
||||
let customIds = [];
|
||||
let customIdsRemove = [];
|
||||
customs.forEach((c) => {
|
||||
if (get(c, 'active') && !get(c, 'existing')) {
|
||||
customIds.push(get(c, 'role.id'));
|
||||
}
|
||||
if (get(c, 'existing') && !get(c, 'active')) {
|
||||
customIdsRemove.push(get(c, 'role.id'));
|
||||
}
|
||||
});
|
||||
this.alertNewCustoms(get(this, 'member'), customIds, customIdsRemove);
|
||||
},
|
||||
|
||||
openModal() {
|
||||
let current = null;
|
||||
if (get(this, 'member.customRolesExisting')) {
|
||||
current = get(this, `resource.${get(this, 'pageType')}RoleTemplateBindings`);
|
||||
}
|
||||
// append roletemplate ids from the modal to the custom field. split that field in the add promise of form-members?
|
||||
get(this,'modalService').toggleModal('modal-add-custom-roles', {
|
||||
model: get(this, 'member'),
|
||||
roles: get(this, 'roles'),
|
||||
done: this.doneAdding.bind(this),
|
||||
current: current,
|
||||
type: get(this, 'pageType')
|
||||
});
|
||||
},
|
||||
|
||||
openCustomModal: on('init', observer('member.role.roleTemplateId', function() {
|
||||
if (get(this, 'member.role.roleTemplateId') === 'custom') {
|
||||
this.openModal();
|
||||
}
|
||||
})),
|
||||
|
||||
choices: computed('roles.[]', 'pageType', function() {
|
||||
let pt = get(this, 'pageType');
|
||||
if (pt) {
|
||||
return BASIC_ROLES.map((r) => {
|
||||
return {
|
||||
label: r.label,
|
||||
value: r.value.indexOf('custom') >= 0 ? 'custom' : `${pt}-${r.value}`
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
|
||||
userList: computed('users.[]', function() {
|
||||
return (get(this, 'users')||[]).map(( user ) =>{
|
||||
return {
|
||||
|
|
@ -38,11 +108,11 @@ export default Component.extend({
|
|||
});
|
||||
}),
|
||||
|
||||
kind: computed('member.subjectKind', function () {
|
||||
kind: computed('member.role.subjectKind', function () {
|
||||
if (get(this, 'owner')) {
|
||||
return `projectsPage.new.form.members.${get(this,'owner.type').toLowerCase()}`; // TODO translations
|
||||
} else {
|
||||
return `projectsPage.new.form.members.${get(this,'member.subjectKind').toLowerCase()}`
|
||||
return `projectsPage.new.form.members.${get(this,'member.role.subjectKind').toLowerCase()}`
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,26 @@
|
|||
<td class="pr-20">
|
||||
{{#if owner}}
|
||||
{{owner.displayName}}
|
||||
{{else if editing}}
|
||||
{{member.role.user.displayName}}
|
||||
{{else}}
|
||||
{{searchable-select content=userList value=member.subjectName disabled=true}}
|
||||
{{searchable-select content=userList value=member.role.subjectName}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="pr-20">
|
||||
{{#if owner}}
|
||||
{{if (eq type 'project') 'Project Owner' 'Cluster Owner'}}
|
||||
{{else if (or hasCustom member.customRolesExisting)}}
|
||||
Multple Roles <span class="edit btn-sm hand" {{action "showEdit" member}}><i class="icon icon-edit"></i></span>
|
||||
{{else}}
|
||||
{{searchable-select content=choices value=member.roleTemplateId}}
|
||||
{{searchable-select content=choices value=member.role.roleTemplateId}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td> </td>
|
||||
<div class="input-group-btn">
|
||||
<button class="btn bg-primary btn-sm" {{action "remove"}} disabled={{if owner 'true' null}}>
|
||||
<i class="icon icon-minus" />
|
||||
</button>
|
||||
{{#unless owner}}
|
||||
<button class="btn bg-primary btn-sm" {{action "remove"}}>
|
||||
<i class="icon icon-minus" />
|
||||
</button>
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'shared/components/modal-add-custom-roles/component';
|
||||
|
|
@ -2240,7 +2240,7 @@ formGlobalRoles:
|
|||
|
||||
formScopedRoles:
|
||||
title: '{type} Permissions'
|
||||
description: TBD.
|
||||
description: 'Controls what access users have to the {type}.'
|
||||
mode:
|
||||
admin:
|
||||
label: Owner
|
||||
|
|
|
|||
Loading…
Reference in New Issue