Convert organization Select to Lookup

This commit is contained in:
gconsidine
2017-06-22 16:11:04 -04:00
parent d7e78a5884
commit dc1bff9048
20 changed files with 474 additions and 327 deletions

View File

@@ -1,6 +1,6 @@
const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION';
function AddCredentialsController (models, $state) { function AddCredentialsController (models, organizationList, $state) {
let vm = this || {}; let vm = this || {};
let me = models.me; let me = models.me;
@@ -23,6 +23,7 @@ function AddCredentialsController (models, $state) {
omit: ['user', 'team', 'inputs'] omit: ['user', 'team', 'inputs']
}); });
vm.form.organization._model = organization;
vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER; vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER;
vm.form.credential_type._data = credentialType.get('results'); vm.form.credential_type._data = credentialType.get('results');
@@ -52,6 +53,7 @@ function AddCredentialsController (models, $state) {
AddCredentialsController.$inject = [ AddCredentialsController.$inject = [
'resolvedModels', 'resolvedModels',
'OrganizationList',
'$state' '$state'
]; ];

View File

@@ -1,4 +1,6 @@
<at-panel ng-if="$state.current.name === 'credentials.add' || $state.current.name === 'credentials.edit'"> <at-panel ng-if="$state.current.name === 'credentials.add' ||
$state.current.name === 'credentials.edit' ||
$state.current.name === 'credentials.add.organization'">
<at-panel-heading>{{ vm.panelTitle }}</at-panel-heading> <at-panel-heading>{{ vm.panelTitle }}</at-panel-heading>
<at-tab-group> <at-tab-group>

View File

@@ -1,7 +1,4 @@
import PermissionsList from '../../src/access/permissions-list.controller'; import LegacyCredentials from './legacy.credentials';
import CredentialForm from '../../src/credentials/credentials.form';
import CredentialList from '../../src/credentials/credentials.list';
import ListController from '../../src/credentials/list/credentials-list.controller';
import AddController from './add-credentials.controller.js'; import AddController from './add-credentials.controller.js';
import EditController from './edit-credentials.controller.js'; import EditController from './edit-credentials.controller.js';
import { N_ } from '../../src/i18n'; import { N_ } from '../../src/i18n';
@@ -33,42 +30,10 @@ CredentialsResolve.$inject = [
'OrganizationModel' 'OrganizationModel'
]; ];
function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceProvider) { function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider) {
let pathService = pathServiceProvider.$get(); let path = pathProvider.$get();
let stateExtender = $stateExtenderProvider.$get(); let stateExtender = $stateExtenderProvider.$get();
let legacy = legacyProvider.$get();
stateExtender.addState({
name: 'credentials',
route: '/credentials',
ncyBreadcrumb: {
label: N_('CREDENTIALS')
},
views: {
'@': {
templateUrl: pathService.getViewPath('credentials/index')
},
'list@credentials': {
templateProvider: function(CredentialList, generateList) {
let html = generateList.build({
list: CredentialList,
mode: 'edit'
});
return html;
},
controller: ListController
}
},
searchPrefix: 'credential',
resolve: {
Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath',
function(list, qs, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}
]
}
});
stateExtender.addState({ stateExtender.addState({
name: 'credentials.add', name: 'credentials.add',
@@ -78,7 +43,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
}, },
views: { views: {
'add@credentials': { 'add@credentials': {
templateUrl: pathService.getViewPath('credentials/add-edit-credentials'), templateUrl: path.getViewPath('credentials/add-edit-credentials'),
controller: AddController, controller: AddController,
controllerAs: 'vm' controllerAs: 'vm'
} }
@@ -96,7 +61,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
}, },
views: { views: {
'edit@credentials': { 'edit@credentials': {
templateUrl: pathService.getViewPath('credentials/add-edit-credentials'), templateUrl: path.getViewPath('credentials/add-edit-credentials'),
controller: EditController, controller: EditController,
controllerAs: 'vm' controllerAs: 'vm'
} }
@@ -106,178 +71,21 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
} }
}); });
stateExtender.addState({ stateExtender.addState(legacy.getStateConfiguration('list'));
name: "credentials.edit.permissions", stateExtender.addState(legacy.getStateConfiguration('edit-permissions'));
url: "/permissions?{permission_search:queryset}", stateExtender.addState(legacy.getStateConfiguration('add-permissions'));
resolve: { stateExtender.addState(legacy.getStateConfiguration('add-organization'));
ListDefinition: () => {
return {
name: 'permissions',
disabled: '(organization === undefined ? true : false)',
// Do not transition the state if organization is undefined
ngClick: `(organization === undefined ? true : false)||$state.go('credentials.edit.permissions')`,
awToolTip: '{{permissionsTooltip}}',
dataTipWatch: 'permissionsTooltip',
awToolTipTabEnabledInEditMode: true,
dataPlacement: 'right',
basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/',
search: {
order_by: 'username'
},
type: 'collection',
title: N_('Permissions'),
iterator: 'permission',
index: false,
open: false,
actions: {
add: {
ngClick: "$state.go('.add')",
label: 'Add',
awToolTip: N_('Add a permission'),
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ' + N_('ADD'),
ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
}
},
fields: {
username: {
key: true,
label: N_('User'),
linkBase: 'users',
class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4'
},
role: {
label: N_('Role'),
type: 'role',
nosort: true,
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
},
team_roles: {
label: N_('Team Roles'),
type: 'team_roles',
nosort: true,
class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
}
}
};
},
Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => {
let id = $stateParams.credential_id;
let path = `api/v2/credentials/${id}/access_list/`;
return qs.search(path, $stateParams[`permission_search`]);
}
]
},
params: {
permission_search: {
value: {
page_size: "20",
order_by: "username"
},
dynamic:true,
squash:""
}
},
ncyBreadcrumb: {
parent: "credentials.edit",
label: "PERMISSIONS"
},
views: {
'related': {
templateProvider: function(CredentialForm, GenerateForm) {
let html = GenerateForm.buildCollection({
mode: 'edit',
related: `permissions`,
form: typeof(CredentialForm) === 'function' ?
CredentialForm() : CredentialForm
});
return html;
},
controller: 'PermissionsList'
}
}
});
stateExtender.addState({
name: 'credentials.edit.permissions.add',
url: '/add-permissions',
resolve: {
usersDataset: [
'addPermissionsUsersList',
'QuerySet',
'$stateParams',
'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams.user_search);
}
],
teamsDataset: [
'addPermissionsTeamsList',
'QuerySet',
'$stateParams',
'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams.team_search);
}
],
resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => {
return new Credential('get', $stateParams.credential_id)
.then(credential => ({ data: credential.get() }));
}],
},
params: {
user_search: {
value: {
order_by: 'username',
page_size: 5
},
dynamic: true
},
team_search: {
value: {
order_by: 'name',
page_size: 5
},
dynamic: true
}
},
ncyBreadcrumb: {
skip: true
},
views: {
'modal@credentials.edit': {
template: `
<add-rbac-resource
users-dataset="$resolve.usersDataset"
teams-dataset="$resolve.teamsDataset"
selected="allSelected"
resource-data="$resolve.resourceData"
title="Add Users / Teams">
</add-rbac-resource>`
}
},
onExit: $state => {
if ($state.transition) {
$('#add-permissions-modal').modal('hide');
$('.modal-backdrop').remove();
$('body').removeClass('modal-open');
}
}
});
} }
CredentialsConfig.$inject = [ CredentialsConfig.$inject = [
'$stateProvider', '$stateExtenderProvider',
'$stateExtenderProvider', 'LegacyCredentialsServiceProvider',
'PathServiceProvider' 'PathServiceProvider'
]; ];
angular angular
.module('at.features.credentials', []) .module('at.features.credentials', [])
.config(CredentialsConfig) .config(CredentialsConfig)
.controller('AddController', AddController) .controller('AddController', AddController)
.controller('EditController', EditController); .controller('EditController', EditController)
.service('LegacyCredentialsService', LegacyCredentials);

View File

@@ -0,0 +1,279 @@
import PermissionsList from '../../src/access/permissions-list.controller';
import CredentialForm from '../../src/credentials/credentials.form';
import CredentialList from '../../src/credentials/credentials.list';
import OrganizationList from '../../src/organizations/organizations.list';
import ListController from '../../src/credentials/list/credentials-list.controller';
import { N_ } from '../../src/i18n';
function LegacyCredentialsService (pathService) {
this.list = {
name: 'credentials',
route: '/credentials',
ncyBreadcrumb: {
label: N_('CREDENTIALS')
},
views: {
'@': {
templateUrl: pathService.getViewPath('credentials/index')
},
'list@credentials': {
templateProvider: function(CredentialList, generateList) {
let html = generateList.build({
list: CredentialList,
mode: 'edit'
});
return html;
},
controller: ListController
}
},
searchPrefix: 'credential',
resolve: {
Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath',
function(list, qs, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}
]
}
};
this.editPermissions = {
name: 'credentials.edit.permissions',
url: '/permissions?{permission_search:queryset}',
resolve: {
ListDefinition: () => {
return {
name: 'permissions',
disabled: 'organization === undefined',
ngClick: `organization === undefined || $state.go('credentials.edit.permissions')`,
awToolTip: '{{permissionsTooltip}}',
dataTipWatch: 'permissionsTooltip',
awToolTipTabEnabledInEditMode: true,
dataPlacement: 'right',
basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/',
search: {
order_by: 'username'
},
type: 'collection',
title: N_('Permissions'),
iterator: 'permission',
index: false,
open: false,
actions: {
add: {
ngClick: `$state.go('.add')`,
label: 'Add',
awToolTip: N_('Add a permission'),
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ' + N_('ADD'),
ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
}
},
fields: {
username: {
key: true,
label: N_('User'),
linkBase: 'users',
class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4'
},
role: {
label: N_('Role'),
type: 'role',
nosort: true,
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
},
team_roles: {
label: N_('Team Roles'),
type: 'team_roles',
nosort: true,
class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
}
}
};
},
Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => {
let id = $stateParams.credential_id;
let path = `api/v2/credentials/${id}/access_list/`;
return qs.search(path, $stateParams[`permission_search`]);
}
]
},
params: {
permission_search: {
value: {
page_size: '20',
order_by: 'username'
},
dynamic:true,
squash:''
}
},
ncyBreadcrumb: {
parent: 'credentials.edit',
label: 'PERMISSIONS'
},
views: {
'related': {
templateProvider: function(CredentialForm, GenerateForm) {
let html = GenerateForm.buildCollection({
mode: 'edit',
related: `permissions`,
form: typeof(CredentialForm) === 'function' ?
CredentialForm() : CredentialForm
});
return html;
},
controller: 'PermissionsList'
}
}
};
this.addPermissions = {
name: 'credentials.edit.permissions.add',
url: '/add-permissions',
resolve: {
usersDataset: [
'addPermissionsUsersList',
'QuerySet',
'$stateParams',
'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams.user_search);
}
],
teamsDataset: [
'addPermissionsTeamsList',
'QuerySet',
'$stateParams',
'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams.team_search);
}
],
resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => {
return new Credential('get', $stateParams.credential_id)
.then(credential => ({ data: credential.get() }));
}],
},
params: {
user_search: {
value: {
order_by: 'username',
page_size: 5
},
dynamic: true
},
team_search: {
value: {
order_by: 'name',
page_size: 5
},
dynamic: true
}
},
ncyBreadcrumb: {
skip: true
},
views: {
'modal@credentials.edit': {
template: `
<add-rbac-resource
users-dataset='$resolve.usersDataset'
teams-dataset='$resolve.teamsDataset'
selected='allSelected'
resource-data='$resolve.resourceData'
title='Add Users / Teams'>
</add-rbac-resource>`
}
},
onExit: $state => {
if ($state.transition) {
$('#add-permissions-modal').modal('hide');
$('.modal-backdrop').remove();
$('body').removeClass('modal-open');
}
}
};
this.organization = {
params: {
organization_search: {
value: {
page_size: 5,
order_by: 'name'
},
dynamic:true,
squash:''
}
},
data: {
basePath: 'organizations',
formChildState:true
},
ncyBreadcrumb: {
skip: true
},
views: {
'organization@credentials.add': {
templateProvider: (ListDefinition, generateList) => {
let html = generateList.build({
mode: 'lookup',
list: ListDefinition,
input_type: 'radio'
});
return `<lookup-modal>${html}</lookup-modal>`;
}
}
},
resolve: {
ListDefinition: ['OrganizationList', function(list) {
return list;
}],
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
return qs.search(
GetBasePath('organizations'),
$stateParams[`${list.iterator}_search`]
);
}
]
},
onExit: function($state) {
if ($state.transition) {
$('#form-modal').modal('hide');
$('.modal-backdrop').remove();
$('body').removeClass('modal-open');
}
}
};
this.getStateConfiguration = (name) => {
switch (name) {
case 'list':
return this.list;
case 'edit-permissions':
return this.editPermissions;
case 'add-permissions':
return this.addPermissions;
case 'add-organization':
this.organization.name = 'credentials.add.organization';
this.organization.url = '/organization';
return this.organization;
default:
throw new Error(`Legacy state configuration for ${name} does not exist`);
};
};
}
LegacyCredentialsService.$inject = [
'PathService'
];
export default LegacyCredentialsService;

View File

@@ -3,6 +3,7 @@
@import 'modal/_index'; @import 'modal/_index';
@import 'panel/_index'; @import 'panel/_index';
@import 'popover/_index'; @import 'popover/_index';
@import 'search/_index';
@import 'tabs/_index'; @import 'tabs/_index';
@import 'table/_index'; @import 'table/_index';
@import 'utility/_index'; @import 'utility/_index';

View File

@@ -10,7 +10,6 @@ import inputMessage from './input/message.directive';
import inputNumber from './input/number.directive'; import inputNumber from './input/number.directive';
import inputSelect from './input/select.directive'; import inputSelect from './input/select.directive';
import inputSecret from './input/secret.directive'; import inputSecret from './input/secret.directive';
import inputSearch from './input/search.directive';
import inputText from './input/text.directive'; import inputText from './input/text.directive';
import inputTextarea from './input/textarea.directive'; import inputTextarea from './input/textarea.directive';
import inputTextareaSecret from './input/textarea-secret.directive'; import inputTextareaSecret from './input/textarea-secret.directive';
@@ -19,6 +18,8 @@ import panel from './panel/panel.directive';
import panelHeading from './panel/heading.directive'; import panelHeading from './panel/heading.directive';
import panelBody from './panel/body.directive'; import panelBody from './panel/body.directive';
import popover from './popover/popover.directive'; import popover from './popover/popover.directive';
import search from './search/search.directive';
import searchKey from './search/key.directive';
import tab from './tabs/tab.directive'; import tab from './tabs/tab.directive';
import tabGroup from './tabs/group.directive'; import tabGroup from './tabs/group.directive';
import table from './table/table.directive'; import table from './table/table.directive';
@@ -39,7 +40,6 @@ angular
.directive('atInputNumber', inputNumber) .directive('atInputNumber', inputNumber)
.directive('atInputSecret', inputSecret) .directive('atInputSecret', inputSecret)
.directive('atInputSelect', inputSelect) .directive('atInputSelect', inputSelect)
.directive('atInputSearch', inputSearch)
.directive('atInputText', inputText) .directive('atInputText', inputText)
.directive('atInputTextarea', inputTextarea) .directive('atInputTextarea', inputTextarea)
.directive('atInputTextareaSecret', inputTextareaSecret) .directive('atInputTextareaSecret', inputTextareaSecret)
@@ -48,6 +48,8 @@ angular
.directive('atPanelHeading', panelHeading) .directive('atPanelHeading', panelHeading)
.directive('atPanelBody', panelBody) .directive('atPanelBody', panelBody)
.directive('atPopover', popover) .directive('atPopover', popover)
.directive('atSearch', search)
.directive('atSearchKey', searchKey)
.directive('atTab', tab) .directive('atTab', tab)
.directive('atTabGroup', tabGroup) .directive('atTabGroup', tabGroup)
.directive('atTable', table) .directive('atTable', table)

View File

@@ -172,42 +172,6 @@
margin: 0; margin: 0;
} }
.at-InputSearch-group--left {
padding-right: @at-margin-item-column;
}
.at-InputSearch-group--right {
padding-left: 0;
}
.at-InputSearch-well {
margin: @at-margin-top-search-key 0 0 0;
padding: @at-padding-well;
}
.at-InputSearch-well {
margin: @at-margin-top-search-key 0 0 0;
padding: @at-padding-well;
}
.at-InputSearch-toggle {
width: 100%;
&, &:focus, &:visited, &:active {
background: @at-color-default;
cursor: pointer;
}
}
.at-InputSearch-toggle--active {
&, &:hover, &:focus, &:visited, &:active {
border: @at-color-search-key-active;
background: @at-color-search-key-active;
color: @at-color-default;
cursor: pointer;
}
}
.at-InputSelect { .at-InputSelect {
position: relative; position: relative;
width: 100%; width: 100%;

View File

@@ -3,11 +3,7 @@ function atInputLookupLink (scope, element, attrs, controllers) {
let inputController = controllers[1]; let inputController = controllers[1];
scope.ns = 'lookup'; scope.ns = 'lookup';
scope[scope.ns] = { scope[scope.ns] = { modal: {} };
modal: {},
search: {},
table: {}
};
if (scope.tab === '1') { if (scope.tab === '1') {
element.find('input')[0].focus(); element.find('input')[0].focus();
@@ -16,32 +12,38 @@ function atInputLookupLink (scope, element, attrs, controllers) {
inputController.init(scope, element, formController); inputController.init(scope, element, formController);
} }
function AtInputLookupController (baseInputController) { function AtInputLookupController (baseInputController, $state) {
let vm = this || {}; let vm = this || {};
let scope; let scope;
let modal; let modal;
let search;
let table;
vm.init = (_scope_, element, form) => { vm.init = (_scope_, element, form) => {
baseInputController.call(vm, 'input', _scope_, element, form); baseInputController.call(vm, 'input', _scope_, element, form);
scope = _scope_; scope = _scope_;
scope.$watch('organization', () => {
if (scope.organization) {
scope.state._value = scope.organization;
scope.state._displayValue = scope.organization_name;
}
});
modal = scope.lookup.modal; modal = scope.lookup.modal;
search = scope.lookup.search;
table = scope.lookup.table;
vm.check(); vm.check();
}; };
vm.search = () => { vm.search = () => {
modal.show(`Select ${scope.state.label}`); $state.go('credentials.add.organization');
}; };
} }
AtInputLookupController.$inject = ['BaseInputController']; AtInputLookupController.$inject = [
'BaseInputController',
'$state'
];
function atInputLookup (pathService) { function atInputLookup (pathService) {
return { return {

View File

@@ -13,7 +13,7 @@
<input type="text" <input type="text"
class="form-control at-Input" class="form-control at-Input"
ng-class="{ 'at-Input--rejected': state.rejected }" ng-class="{ 'at-Input--rejected': state.rejected }"
ng-model="state._value" ng-model="state._displayValue"
ng-attr-tabindex="{{ tab || undefined }}" ng-attr-tabindex="{{ tab || undefined }}"
ng-attr-placeholder="{{::state._placeholder || undefined }}" ng-attr-placeholder="{{::state._placeholder || undefined }}"
ng-change="vm.check()" ng-change="vm.check()"
@@ -23,8 +23,5 @@
<at-input-message></at-input-message> <at-input-message></at-input-message>
</div> </div>
<at-modal> <div ui-view="organization"></div>
<at-input-search></at-input-search>
<at-table namespace></at-table>
</at-modal>
</div> </div>

View File

@@ -2,11 +2,10 @@ const DEFAULT_ANIMATION_DURATION = 150;
function atModalLink (scope, el, attrs, controllers) { function atModalLink (scope, el, attrs, controllers) {
let modalController = controllers[0]; let modalController = controllers[0];
let container = el[0];
let property = `scope.${scope.ns}.modal`; let property = `scope.${scope.ns}.modal`;
let done = scope.$watch(property, () => { let done = scope.$watch(property, () => {
modalController.init(scope, container); modalController.init(scope, el);
done(); done();
}); });
} }
@@ -14,11 +13,13 @@ function atModalLink (scope, el, attrs, controllers) {
function AtModalController (eventService) { function AtModalController (eventService) {
let vm = this; let vm = this;
let container; let overlay;
let modal;
let listeners; let listeners;
vm.init = (scope, _container_) => { vm.init = (scope, el) => {
container = _container_; overlay = el[0];
modal = el.find('.at-Modal-window')[0];
vm.modal = scope[scope.ns].modal; vm.modal = scope[scope.ns].modal;
vm.modal.show = vm.show; vm.modal.show = vm.show;
@@ -35,36 +36,34 @@ function AtModalController (eventService) {
[window, 'click', vm.clickToHide] [window, 'click', vm.clickToHide]
]); ]);
container.style.display = 'block'; overlay.style.display = 'block';
container.style.opacity = 1; overlay.style.opacity = 1;
}; };
vm.hide = () => { vm.hide = () => {
container.style.opacity = 0; overlay.style.opacity = 0;
eventService.remove(listeners); eventService.remove(listeners);
setTimeout(() => { setTimeout(() => overlay.style.display = 'none', DEFAULT_ANIMATION_DURATION);
container.style.display = 'none';
vm.modal.message = '';
vm.modal.title = '';
}, DEFAULT_ANIMATION_DURATION);
}; };
vm.clickToHide = event => { vm.clickToHide = event => {
if (vm.clickIsOutsideContainer(event)) { if (vm.clickIsOutsideModal(event)) {
console.log('outside'); vm.hide();
} else {
console.log('inside');
} }
}; };
vm.clickIsOutsideContainer = e => { vm.clickIsOutsideModal = e => {
let pos = container.getBoundingClientRect(); let m = modal.getBoundingClientRect();
let ex = e.clientX; let cx = e.clientX;
let ey = e.clientY; let cy = e.clientY;
if (cx < m.left || cx > m.right || cy > m.bottom || cy < m.top) {
return true;
}
console.log(e, pos); return false;
}; };
} }

View File

@@ -1,6 +1,6 @@
<div class="modal at-Modal fade" tabindex="-1" role="dialog"> <div class="modal at-Modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content at-Modal-window">
<div class="row"> <div class="row">
<div class="col-xs-10"> <div class="col-xs-10">
<div class="at-Modal-heading"> <div class="at-Modal-heading">
@@ -8,8 +8,8 @@
</div> </div>
</div> </div>
<div class="col-xs-2"> <div class="col-xs-2">
<div type="button" class="at-Modal-dismiss" ng-click="vm.hide()"> <div class="at-Modal-dismiss">
<i class="fa fa-lg fa-times-circle"></i> <i class="fa fa-lg fa-times-circle" ng-click="vm.hide()"></i>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,37 @@
.at-Search-group--left {
padding-right: @at-margin-item-column;
}
.at-Search-group--right {
padding-left: 0;
}
.at-Search-well {
margin: @at-margin-top-search-key 0 0 0;
padding: @at-padding-well;
}
.at-Search-well {
margin: @at-margin-top-search-key 0 0 0;
padding: @at-padding-well;
}
.at-Search-toggle {
width: 100%;
&, &:focus, &:visited, &:active {
background: @at-color-default;
cursor: pointer;
}
}
.at-Search-toggle--active {
&, &:hover, &:focus, &:visited, &:active {
border: @at-color-search-key-active;
background: @at-color-search-key-active;
color: @at-color-default;
cursor: pointer;
}
}

View File

@@ -0,0 +1,38 @@
function atSearchKeyLink (scope, element, attrs, controllers) {
let searchController = controllers[0];
let property = `scope.${scope.ns}.search`;
let done = scope.$watch(property, () => {
searchController.init(scope, element);
done();
});
}
function AtSearchKeyController () {
let vm = this || {};
vm.init = (scope, element) => {
/*
*vm.placeholder = DEFAULT_PLACEHOLDER;
*vm.search = scope[scope.ns].search;
*/
};
}
function atSearchKey (pathService) {
return {
restrict: 'E',
transclude: true,
replace: true,
require: ['atSearchKey'],
templateUrl: pathService.getPartialPath('components/search/key'),
controller: AtSearchKeyController,
controllerAs: 'vm',
link: atSearchKeyLink,
scope: true
};
}
atSearchKey.$inject = ['PathService'];
export default atSearchKey;

View File

@@ -0,0 +1,23 @@
<div class="col-xs-12">
<div class="well at-Search-well">
<div class="">
<h4>EXAMPLES:</h4>
<span></span>
</div>
<div class="">
<h4>FIELDS:</h4>
<div></div>
</div>
<div>
<h4>RELATED FIELDS:</h4>
<div></div>
</div>
<div class="">
<h4>ADDITIONAL INFORMATION:</h4>
<p>
For additional information on advanced search search syntax please see the
Ansible Tower <at-doc resource="search_sort">documentation</at-doc>.
</p>
</div>
</div>
</div>

View File

@@ -1,30 +1,28 @@
const DEFAULT_PLACEHOLDER = 'SEARCH'; const DEFAULT_PLACEHOLDER = 'SEARCH';
function atInputSearchLink (scope, element, attrs, controllers) { function atSearchLink (scope, element, attrs, controllers) {
let inputController = controllers[0]; let inputController = controllers[0];
let property = `scope.${scope.ns}.search`; let property = `scope.${scope.ns}.search`;
let done = scope.$watch(property, () => { let done = scope.$watch(property, () => {
inputController.init(scope, element); inputController.init(scope, element);
scope.ready = true;
done(); done();
}); });
} }
function AtInputSearchController (baseInputController) { function AtSearchController () {
let vm = this || {}; let vm = this || {};
let toggleButton; let toggleButton;
let input; let input;
vm.init = (scope, element) => { vm.init = (scope, element) => {
toggleButton = element.find('.at-InputSearch-toggle')[0]; toggleButton = element.find('.at-Search-toggle')[0];
input = element.find('.at-Input')[0]; input = element.find('.at-Input')[0];
vm.placeholder = DEFAULT_PLACEHOLDER; vm.placeholder = DEFAULT_PLACEHOLDER;
vm.search = scope[scope.ns].search; vm.search = scope[scope.ns].search;
// baseInputController.call(vm, 'input', scope, element, form);
//vm.check();
}; };
vm.toggle = () => { vm.toggle = () => {
@@ -33,22 +31,20 @@ function AtInputSearchController (baseInputController) {
}; };
} }
AtInputSearchController.$inject = ['BaseInputController']; function atSearch (pathService) {
function atInputSearch (pathService) {
return { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
replace: true, replace: true,
require: ['atInputSearch'], require: ['atSearch'],
templateUrl: pathService.getPartialPath('components/input/search'), templateUrl: pathService.getPartialPath('components/search/search'),
controller: AtInputSearchController, controller: AtSearchController,
controllerAs: 'vm', controllerAs: 'vm',
link: atInputSearchLink, link: atSearchLink,
scope: true scope: true
}; };
} }
atInputSearch.$inject = ['PathService']; atSearch.$inject = ['PathService'];
export default atInputSearch; export default atSearch;

View File

@@ -1,6 +1,6 @@
<div class="at-InputContainer"> <div class="at-InputContainer">
<div class="row"> <div class="row">
<div class="col-xs-10 at-InputSearch-group--left"> <div class="col-xs-10 at-Search-group--left">
<div class="form-group at-u-flat"> <div class="form-group at-u-flat">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control at-Input" <input type="text" class="form-control at-Input"
@@ -13,19 +13,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-xs-2 at-InputSearch-group--right"> <div class="col-xs-2 at-Search-group--right">
<button class="btn at-ButtonHollow--default at-InputSearch-toggle" <button class="btn at-ButtonHollow--default at-Search-toggle"
ng-class="{ 'at-InputSearch-toggle--active': vm.isToggleActive }" ng-class="{ 'at-Search-toggle--active': vm.isToggleActive }"
ng-click="vm.toggle()"> ng-click="vm.toggle()">
KEY KEY
</button> </button>
</div> </div>
</div> </div>
<div class="row" ng-show="vm.isToggleActive"> <div class="row" ng-show="vm.isToggleActive">
<div class="col-xs-12"> <at-search-key></at-search-key>
<div class="well at-InputSearch-well">
<p>Some info here</p>
</div>
</div>
</div> </div>
</div> </div>

View File

@@ -77,25 +77,24 @@ function httpOptions (resource) {
}); });
} }
function get (method, keys) { function options (keys) {
let model; return this.find('options', keys);
}
if (keys) { function get (keys) {
model = this.model[method.toUpperCase()]; return this.find('get', keys);
} else { }
model = this.model.GET;
keys = method; function find (method, keys) {
} let value = this.model[method.toUpperCase()];
if (!keys) { if (!keys) {
return model; return value;
} }
keys = keys.split('.');
let value = model;
try { try {
keys = keys.split('.');
keys.forEach(key => { keys.forEach(key => {
let bracketIndex = key.indexOf('['); let bracketIndex = key.indexOf('[');
let hasArray = bracketIndex !== -1; let hasArray = bracketIndex !== -1;
@@ -137,6 +136,8 @@ function getById (id) {
function BaseModel (path) { function BaseModel (path) {
this.model = {}; this.model = {};
this.get = get; this.get = get;
this.options = options;
this.find = find;
this.normalizePath = normalizePath; this.normalizePath = normalizePath;
this.getById = getById; this.getById = getById;
this.request = request; this.request = request;

View File

@@ -3,7 +3,7 @@ const ENCRYPTED_VALUE = '$encrypted$';
let BaseModel; let BaseModel;
function createFormSchema (method, config) { function createFormSchema (method, config) {
let schema = Object.assign({}, this.get('options', `actions.${method.toUpperCase()}`)); let schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`));
if (config && config.omit) { if (config && config.omit) {
config.omit.forEach(key => { config.omit.forEach(key => {