Add Container Group Form Render and cred type modal pops up

modal render proper cred

WIP

modal rendering properly

card for edit CG renders, no fields

add code mirror and some list styling

address PR issues
This commit is contained in:
Alex Corey 2019-08-23 09:51:55 -04:00 committed by Shane McDonald
parent aab1cd68b0
commit 007f33c186
No known key found for this signature in database
GPG Key ID: 6F374AF6E9EB9374
12 changed files with 455 additions and 68 deletions

View File

@ -209,6 +209,9 @@
width: 100% !important;
padding-right: 0px !important;
}
.containerGroups-codeMirror{
margin: 20px;
}
.Form-formGroup--checkbox{
display: flex;

View File

@ -88,17 +88,14 @@ function AtInputLookupController (baseInputController, $q, $state) {
scope.state._value = null;
return vm.check({ isValid: true });
}
searchParams = searchParams || { [search.key]: scope.state._displayValue };
return model.search(searchParams, search.config)
.then(found => {
if (!found) {
vm.reset();
return;
}
scope[scope.state._resource] = model.get('id');
scope.state._value = model.get('id');
scope.state._displayValue = model.get('name');

View File

@ -241,6 +241,10 @@
align-items: center;
}
.at-Row-rightSide{
justify-content: flex-end;
}
.at-Row-container--wrapped {
display: flex;
flex-wrap: wrap;

View File

@ -0,0 +1,62 @@
function AddContainerGroupController(ToJSON, $scope, $state, models, strings, i18n, DataSet) {
const vm = this || {};
const {
instanceGroup,
credential
} = models;
vm.mode = 'add';
vm.strings = strings;
vm.panelTitle = strings.get('state.ADD_CONTAINER_GROUP_BREADCRUMB_LABEL');
vm.lookUpTitle = strings.get('container.LOOK_UP_TITLE');
vm.form = instanceGroup.createFormSchema('post');
vm.form.name.required = true;
vm.form.credential = {
type: 'field',
label: i18n._('Credential'),
id: 'credential'
};
vm.form.credential._resource = 'credential';
vm.form.credential._route = "instanceGroups.addContainerGroup.credentials";
vm.form.credential._model = credential;
vm.form.credential._placeholder = strings.get('container.CREDENTIAL_PLACEHOLDER');
vm.form.credential.required = true;
vm.form.extraVars = {
label: strings.get('container.POD_SPEC_LABEL'),
value: DataSet.data.actions.POST.pod_spec_override.default,
name: 'extraVars'
};
$scope.variables = vm.form.extraVars.value;
$scope.name = vm.form.extraVars.name;
vm.panelTitle = strings.get('container.PANEL_TITLE');
$scope.$watch('credential', () => {
if ($scope.credential) {
vm.form.credential._idFromModal= $scope.credential;
}
});
vm.form.save = (data) => {
data.pod_spec_override = vm.form.extraVars.value;
return instanceGroup.request('post', { data: data }).then((res) => {
$state.go('instanceGroups.editContainerGroup', { instance_group_id: res.data.id }, { reload: true });
});
};
}
AddContainerGroupController.$inject = [
'ToJSON',
'$scope',
'$state',
'resolvedModels',
'InstanceGroupsStrings',
'i18n',
'DataSet'
];
export default AddContainerGroupController;

View File

@ -0,0 +1,22 @@
<div ui-view="credentials"></div>
<at-panel>
<at-panel-heading title="{{:: vm.panelTitle }}"></at-panel-heading>
<at-panel-body>
<at-form state="vm.form" autocomplete="off">
<at-input-text col="4" tab="1" state="vm.form.name"></at-input-text>
<at-input-lookup col="4" tab="3" state="vm.form.credential" id="containter_groups_credential"></at-input-lookup>
<at-code-mirror
col="4" tab="3"
class="form-group Form-formGroup--fullWidth containerGroups-codeMirror"
variables="vm.form.extraVars.value"
label="{{ vm.form.extraVars.label }}"
name="{{ vm.form.extraVars.name }}"
>
</at-code-mirror>
<at-action-group col="12" pos="right">
<at-form-action type="cancel" to="instanceGroups"></at-form-action>
<at-form-action type="save"></at-form-action>
</at-action-group>
</at-form>
</at-panel-body>
</at-panel>

View File

@ -0,0 +1,65 @@
function EditContainerGroupController($rootScope, $scope, $state, models, strings, i18n, EditContainerGroupDataset) {
const vm = this || {};
const {
instanceGroup,
credential
} = models;
$rootScope.breadcrumb.instance_group_name = instanceGroup.get('name');
vm.mode = 'add';
vm.strings = strings;
vm.panelTitle = EditContainerGroupDataset.data.name;
vm.lookUpTitle = strings.get('container.LOOK_UP_TITLE');
vm.form = instanceGroup.createFormSchema('post');
vm.form.name.required = true;
vm.form.credential = {
type: 'field',
label: i18n._('Credential'),
id: 'credential'
};
vm.form.credential._resource = 'credential';
vm.form.credential._route = "instanceGroups.editContainerGroup.credentials";
vm.form.credential._model = credential;
vm.form.credential._displayValue = EditContainerGroupDataset.data.summary_fields.credential.name;
vm.form.credential.required = true;
vm.form.credential._value = EditContainerGroupDataset.data.summary_fields.credential.id;
vm.podSpec = {
type: 'textarea',
id: 'pod_spec'
};
vm.podSpec.label = strings.get('container.POD_SPEC_LABEL');
vm.form.extraVars = {
label: strings.get('container.POD_SPEC_LABEL'),
value: EditContainerGroupDataset.data.pod_spec_override,
name: 'extraVars'
};
$scope.$watch('credential', () => {
if ($scope.credential) {
vm.form.credential._idFromModal= $scope.credential;
}
});
vm.form.save = (data) => {
data.pod_spec_override = vm.form.extraVars.value;
return instanceGroup.request('put', { data: data }).then((res) => {
$state.go('instanceGroups.editContainerGroup', { instance_group_id: res.data.id }, { reload: true });
} );
};
}
EditContainerGroupController.$inject = [
'$rootScope',
'$scope',
'$state',
'resolvedModels',
'InstanceGroupsStrings',
'i18n',
'EditContainerGroupDataset'
];
export default EditContainerGroupController;

View File

@ -1,4 +1,8 @@
.InstanceGroups {
.at-Row-actions{
width: 700px;
justify-content: flex-end;
}
.BreadCrumb-menuLinkImage:hover {
color: @default-link;
@ -75,3 +79,8 @@
}
}
}
.at-Row-links {
justify-content: flex-end;
display: flex;
flex-grow: 1;
}

View File

@ -2,6 +2,8 @@
<aw-limit-panels max-panels="2" panel-container="instance-groups-panel"></aw-limit-panels>
<div ui-view="add"></div>
<div ui-view="edit"></div>
<div ui-view="addContainerGroup"></div>
<div ui-view="editContainerGroup"></div>
<div ui-view="instanceJobsContainer"></div>

View File

@ -1,13 +1,16 @@
function InstanceGroupsStrings (BaseString) {
function InstanceGroupsStrings(BaseString) {
BaseString.call(this, 'instanceGroups');
const { t } = this;
const {
t
} = this;
const ns = this.instanceGroups;
ns.state = {
INSTANCE_GROUPS_BREADCRUMB_LABEL: t.s('INSTANCE GROUPS'),
INSTANCES_BREADCRUMB_LABEL: t.s('INSTANCES'),
ADD_BREADCRUMB_LABEL: t.s('CREATE INSTANCE GROUP')
ADD_BREADCRUMB_LABEL: t.s('CREATE INSTANCE GROUP'),
ADD_CONTAINER_GROUP_BREADCRUMB_LABEL: t.s('CREATE CONTAINER GROUP')
};
ns.list = {
@ -33,7 +36,8 @@ function InstanceGroupsStrings (BaseString) {
};
ns.instance = {
PANEL_TITLE: t.s('SELECT INSTANCE')
PANEL_TITLE: t.s('SELECT INSTANCE'),
BADGE_TEXT: t.s('Instance Group')
};
ns.capacityBar = {
@ -62,6 +66,13 @@ function InstanceGroupsStrings (BaseString) {
ns.alert = {
MISSING_PARAMETER: t.s('Instance Group parameter is missing.'),
};
ns.container = {
PANEL_TITLE: t.s('Add Container Group'),
LOOK_UP_TITLE: t.s('Add Credential'),
CREDENTIAL_PLACEHOLDER: t.s('SELECT A CREDENTIAL'),
POD_SPEC_LABEL: t.s('Pod Spec Override'),
BADGE_TEXT: t.s('Container Group')
};
}
InstanceGroupsStrings.$inject = ['BaseStringService'];

View File

@ -18,19 +18,20 @@
search-tags="searchTags">
</smart-search>
<div class="at-List-toolbarAction">
<button
type="button"
ui-sref="instanceGroups.add"
class="at-Button--add"
id="button-add"
ng-show="vm.isSuperuser"
aw-tool-tip="{{vm.tooltips.add}}"
data-placement="top"
aria-haspopup="true"
aria-expanded="false">
<button type="button" class="at-Button--add" id="button-add" ng-show="vm.isSuperuser"
data-toggle="dropdown" data-placement="top" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="button-add">
<a class="dropdown-item" ui-sref="instanceGroups.add">
{{:: vm.strings.get('state.ADD_BREADCRUMB_LABEL') }}
</a>
<a class="dropdown-item" ui-sref="instanceGroups.addContainerGroup">
{{:: vm.strings.get('state.ADD_CONTAINER_GROUP_BREADCRUMB_LABEL') }}
</a>
</div>
</div>
</div>
</div>
<at-list-toolbar
ng-if="instance_groups.length > 0"
sort-only="true"
@ -40,46 +41,70 @@
</at-list-toolbar>
<at-list results="instance_groups">
<at-row ng-repeat="instance_group in instance_groups"
ng-class="{'at-Row--active': (instance_group.id === vm.activeId)}">
ng-class="{'at-Row--active': (instance_group.id === vm.activeId)}" >
<div class="at-Row-items">
<at-row-item
header-value="{{ instance_group.name }}"
header-state="instanceGroups.edit({instance_group_id:{{instance_group.id}}})"
header-tag="{{ instance_group.is_isolated ? vm.strings.get('list.ROW_ITEM_LABEL_ISOLATED') : '' }}"
>
</at-row-item>
<div class="at-Row--inline">
<at-row-item
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_INSTANCES') }}"
label-state="instanceGroups.instances({instance_group_id: {{ instance_group.id }}})"
value="{{ instance_group.instances }}"
inline="true"
badge="true">
</at-row-item>
<at-row-item
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_RUNNING_JOBS') }}"
label-state="instanceGroups.jobs({instance_group_id: {{ instance_group.id }}, job_search: {status__in: ['running,waiting']}})"
value="{{ instance_group.jobs_running }}"
inline="true"
badge="true">
</at-row-item>
<at-row-item
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_TOTAL_JOBS') }}"
label-state="instanceGroups.jobs({instance_group_id: {{ instance_group.id }}})"
value="{{ instance_group.jobs_total }}"
inline="true"
badge="true">
</at-row-item>
<div class="at-Row-container">
<div class="at-Row-content">
<at-row-item
ng-if="!instance_group.credential"
header-value="{{ instance_group.name }}"
header-state="instanceGroups.edit({instance_group_id:{{instance_group.id}}})"
header-tag="{{ instance_group.is_isolated ? vm.strings.get('list.ROW_ITEM_LABEL_ISOLATED') : '' }}"
>
</at-row-item>
<at-row-item
ng-if="instance_group.credential"
header-value="{{ instance_group.name }}"
header-state="instanceGroups.editContainerGroup({instance_group_id:{{instance_group.id}}})"
header-tag="{{ instance_group.is_isolated ? vm.strings.get('list.ROW_ITEM_LABEL_ISOLATED') : '' }}"
>
</at-row-item>
<div class="at-RowItem--labels" ng-if="instance_group.credential">
<div class="LabelList-tagContainer">
<div class="LabelList-tag" ng-class="{'LabelList-tag--deletable' : (showDelete && template.summary_fields.user_capabilities.edit)}">
<span class="LabelList-name">{{vm.strings.get('container.BADGE_TEXT') }}</span>
</div>
</div>
</div>
<div class="at-RowItem--labels" ng-if="!instance_group.credential">
<div class="LabelList-tagContainer">
<div class="LabelList-tag" ng-class="{'LabelList-tag--deletable' : (showDelete && template.summary_fields.user_capabilities.edit)}">
<span class="LabelList-name">{{vm.strings.get('instance.BADGE_TEXT') }}</span>
</div>
</div>
</div>
</div>
<div class="at-Row-links">
<at-row-item
ng-if="!instance_group.credential"
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_INSTANCES') }}"
label-state="instanceGroups.instances({instance_group_id: {{ instance_group.id }}})"
value="{{ instance_group.instances }}"
inline="true"
badge="true">
</at-row-item>
<at-row-item
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_RUNNING_JOBS') }}"
label-state="instanceGroups.jobs({instance_group_id: {{ instance_group.id }}, job_search: {status__in: ['running,waiting']}})"
value="{{ instance_group.jobs_running }}"
inline="true"
badge="true">
</at-row-item>
<at-row-item
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_TOTAL_JOBS') }}"
label-state="instanceGroups.jobs({instance_group_id: {{ instance_group.id }}})"
value="{{ instance_group.jobs_total }}"
inline="true"
badge="true">
</at-row-item>
</div>
<div class="at-Row-actions" >
<capacity-bar ng-show="!instance_group.credential" label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_USED_CAPACITY') }}" capacity="instance_group.consumed_capacity" total-capacity="instance_group.capacity"></capacity-bar>
<at-row-action icon="fa-trash" ng-click="vm.deleteInstanceGroup(instance_group)" ng-if="vm.rowAction.trash(instance_group)">
</at-row-action>
</div>
</div>
</div>
<div class="at-Row-actions">
<capacity-bar label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_USED_CAPACITY') }}" capacity="instance_group.consumed_capacity" total-capacity="instance_group.capacity"></capacity-bar>
<at-row-action icon="fa-trash" ng-click="vm.deleteInstanceGroup(instance_group)" ng-if="vm.rowAction.trash(instance_group)">
</at-row-action>
</div>
</at-row>
</at-list>
</at-panel-body>

View File

@ -1,5 +1,10 @@
import { templateUrl } from '../shared/template-url/template-url.factory';
import {
templateUrl
} from '../shared/template-url/template-url.factory';
import CapacityAdjuster from './capacity-adjuster/capacity-adjuster.directive';
import AddContainerGroup from './container-groups/add-container-group.view.html';
import EditContainerGroupController from './container-groups/edit-container-group.controller';
import AddContainerGroupController from './container-groups/add-container-group.controller';
import CapacityBar from './capacity-bar/capacity-bar.directive';
import instanceGroupsMultiselect from '../shared/instance-groups-multiselect/instance-groups.directive';
import instanceGroupsModal from '../shared/instance-groups-multiselect/instance-groups-modal/instance-groups-modal.directive';
@ -25,34 +30,55 @@ import InstanceGroupsStrings from './instance-groups.strings';
import instanceGroupJobsRoute from '~features/jobs/routes/instanceGroupJobs.route.js';
import instanceJobsRoute from '~features/jobs/routes/instanceJobs.route.js';
const MODULE_NAME = 'instanceGroups';
function InstanceGroupsResolve ($q, $stateParams, InstanceGroup, Instance, ProcessErrors, strings) {
function InstanceGroupsResolve($q, $stateParams, InstanceGroup, Credential, Instance, ProcessErrors, strings) {
const instanceGroupId = $stateParams.instance_group_id;
const instanceId = $stateParams.instance_id;
let promises = {};
if (!instanceGroupId && !instanceId) {
promises.instanceGroup = new InstanceGroup(['get', 'options']);
promises.credential = new Credential(['get', 'options']);
return $q.all(promises);
}
if (instanceGroupId && instanceId) {
promises.instance = new Instance(['get', 'options'], [instanceId, instanceId])
.then((instance) => instance.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}));
.then((instance) => instance.extend('get', 'jobs', {
params: {
page_size: "10",
order_by: "-finished"
}
}));
return $q.all(promises);
}
promises.instanceGroup = new InstanceGroup(['get', 'options'], [instanceGroupId, instanceGroupId])
.then((instanceGroup) => instanceGroup.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}))
.then((instanceGroup) => instanceGroup.extend('get', 'instances'));
.then((instanceGroup) => instanceGroup.extend('get', 'jobs', {
params: {
page_size: "10",
order_by: "-finished"
}
}))
.then((instanceGroup) => instanceGroup.extend('get', 'instances'));
promises.credential = new Credential();
return $q.all(promises)
.then(models => models)
.catch(({ data, status, config }) => {
.catch(({
data,
status,
config
}) => {
ProcessErrors(null, data, status, null, {
hdr: strings.get('error.HEADER'),
msg: strings.get('error.CALL', { path: `${config.url}`, status })
msg: strings.get('error.CALL', {
path: `${config.url}`,
status
})
});
return $q.reject();
});
@ -62,12 +88,13 @@ InstanceGroupsResolve.$inject = [
'$q',
'$stateParams',
'InstanceGroupModel',
'CredentialModel',
'InstanceModel',
'ProcessErrors',
'InstanceGroupsStrings'
];
function InstanceGroupsRun ($stateExtender, strings) {
function InstanceGroupsRun($stateExtender, strings) {
$stateExtender.addState({
name: 'instanceGroups',
url: '/instance_groups',
@ -100,7 +127,7 @@ function InstanceGroupsRun ($stateExtender, strings) {
resolve: {
resolvedModels: InstanceGroupsResolve,
Dataset: ['InstanceGroupList', 'QuerySet', '$stateParams', 'GetBasePath',
function(list, qs, $stateParams, GetBasePath) {
function (list, qs, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}
@ -143,6 +170,165 @@ function InstanceGroupsRun ($stateExtender, strings) {
]
}
});
$stateExtender.addState({
name: 'instanceGroups.addContainerGroup',
url: '/container_group',
views: {
'addContainerGroup@instanceGroups': {
templateUrl: AddContainerGroup,
controller: AddContainerGroupController,
controllerAs: 'vm'
}
},
resolve: {
resolvedModels: InstanceGroupsResolve,
DataSet: ['Rest', 'GetBasePath', (Rest, GetBasePath) => {
Rest.setUrl(`${GetBasePath('instance_groups')}`);
return Rest.options();
}]
},
ncyBreadcrumb: {
label: strings.get('state.ADD_CONTAINER_GROUP_BREADCRUMB_LABEL')
},
});
$stateExtender.addState({
name: 'instanceGroups.addContainerGroup.credentials',
url: '/credential?selected',
searchPrefix: 'credential',
params: {
credential_search: {
value: {
order_by: 'name',
page_size: 5,
},
dynamic: true,
squash: ''
}
},
data: {
basePath: 'credentials',
formChildState: true
},
ncyBreadcrumb: {
skip: true
},
views: {
'credentials@instanceGroups.addContainerGroup': {
templateProvider: (ListDefinition, generateList) => {
const html = generateList.build({
mode: 'lookup',
list: ListDefinition,
input_type: 'radio'
});
return `<lookup-modal>${html}</lookup-modal>`;
}
}
},
resolve: {
ListDefinition: ['CredentialList', list => list],
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
const params = {
credential_type__kind: 'kubernetes',
};
const searchPath = GetBasePath('credentials');
return qs.search(
searchPath, params,
$stateParams[`${list.iterator}_search`]
);
}]
},
onExit ($state) {
if ($state.transition) {
$('#form-modal').modal('hide');
$('.modal-backdrop').remove();
$('body').removeClass('modal-open');
}
}
});
$stateExtender.addState({
name: 'instanceGroups.editContainerGroup',
url: '/container_group/edit/:instance_group_id',
views: {
'editContainerGroup@instanceGroups': {
templateUrl: AddContainerGroup,
controller: EditContainerGroupController,
controllerAs: 'vm'
}
},
resolve: {
resolvedModels: InstanceGroupsResolve,
EditContainerGroupDataset: ['GetBasePath', 'QuerySet', '$stateParams',
function (GetBasePath, qs, $stateParams) {
let path = `${GetBasePath('instance_groups')}${$stateParams.instance_group_id}`;
return qs.search(path, $stateParams);
}
],
},
ncyBreadcrumb: {
label: '{{breadcrumb.instance_group_name}}'
},
});
$stateExtender.addState({
name: 'instanceGroups.editContainerGroup.credentials',
url: '/credential?selected',
searchPrefix: 'credential',
params: {
credential_search: {
value: {
order_by: 'name',
page_size: 5,
},
dynamic: true,
squash: ''
}
},
data: {
basePath: 'credentials',
formChildState: true
},
views: {
'credentials@instanceGroups.editContainerGroup': {
templateProvider: (ListDefinition, generateList) => {
const html = generateList.build({
mode: 'lookup',
list: ListDefinition,
input_type: 'radio'
});
return `<lookup-modal>${html}</lookup-modal>`;
}
}
},
resolve: {
ListDefinition: ['CredentialList', list => list],
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
const params = {
credential_type__kind: 'kubernetes',
};
const searchPath = GetBasePath('credentials');
return qs.search(
searchPath, params,
$stateParams[`${list.iterator}_search`]
);
}]
},
onExit ($state) {
if ($state.transition) {
$('#form-modal').modal('hide');
$('.modal-backdrop').remove();
$('body').removeClass('modal-open');
}
}
});
$stateExtender.addState({
name: 'instanceGroups.edit',
@ -207,7 +393,7 @@ function InstanceGroupsRun ($stateExtender, strings) {
resolve: {
resolvedModels: InstanceGroupsResolve,
Dataset: ['GetBasePath', 'QuerySet', '$stateParams',
function(GetBasePath, qs, $stateParams) {
function (GetBasePath, qs, $stateParams) {
let path = `${GetBasePath('instance_groups')}${$stateParams.instance_group_id}/instances`;
return qs.search(path, $stateParams[`instance_search`]);
}
@ -255,7 +441,7 @@ function InstanceGroupsRun ($stateExtender, strings) {
resolve: {
resolvedModels: InstanceGroupsResolve,
Dataset: ['GetBasePath', 'QuerySet', '$stateParams',
function(GetBasePath, qs, $stateParams) {
function (GetBasePath, qs, $stateParams) {
let path = `${GetBasePath('instances')}`;
return qs.search(path, $stateParams[`add_instance_search`]);
}
@ -269,7 +455,8 @@ function InstanceGroupsRun ($stateExtender, strings) {
InstanceGroupsRun.$inject = [
'$stateExtender',
'InstanceGroupsStrings'
'InstanceGroupsStrings',
'Rest'
];
angular.module(MODULE_NAME, [])

View File

@ -74,7 +74,7 @@ export default ['templateUrl', 'i18n', function(templateUrl, i18n) {
}
}
$scope.saveForm = function() {
$scope.saveForm = function () {
eventService.remove(listeners);
let list = $scope.list;
if($scope.currentSelection.name !== null) {
@ -89,7 +89,7 @@ export default ['templateUrl', 'i18n', function(templateUrl, i18n) {
$state.go('^');
};
$scope.toggle_row = function(selectedRow) {
$scope.toggle_row = function (selectedRow) {
let list = $scope.list;
let count = 0;
$scope[list.name].forEach(function(row) {