mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 20:00:43 -03:30
Merge pull request #6731 from gconsidine/ui/component-hardening
Ui/component hardening
This commit is contained in:
commit
8d39cee5f5
@ -6,7 +6,6 @@ function AddCredentialsController (models, $state) {
|
||||
let me = models.me;
|
||||
let credential = models.credential;
|
||||
let credentialType = models.credentialType;
|
||||
let organization = models.organization;
|
||||
|
||||
vm.panelTitle = 'NEW CREDENTIAL';
|
||||
|
||||
@ -23,22 +22,18 @@ function AddCredentialsController (models, $state) {
|
||||
omit: ['user', 'team', 'inputs']
|
||||
});
|
||||
|
||||
vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER;
|
||||
vm.form.organization._data = organization.get('results');
|
||||
vm.form.organization._format = 'objects';
|
||||
vm.form.organization._exp = 'org as org.name for org in state._data';
|
||||
vm.form.organization._display = 'name';
|
||||
vm.form.organization._key = 'id';
|
||||
vm.form.organization._resource = 'organization';
|
||||
vm.form.organization._route = 'credentials.add.organization';
|
||||
|
||||
vm.form.credential_type._data = credentialType.get('results');
|
||||
vm.form.credential_type._placeholder = 'SELECT A TYPE';
|
||||
vm.form.credential_type._format = 'grouped-object';
|
||||
vm.form.credential_type._display = 'name';
|
||||
vm.form.credential_type._key = 'id';
|
||||
vm.form.credential_type._exp = 'type as type.name group by type.kind for type in state._data';
|
||||
vm.form.credential_type._resource = 'credential_type';
|
||||
vm.form.credential_type._route = 'credentials.add.credentialType';
|
||||
|
||||
vm.form.inputs = {
|
||||
_get: credentialType.mergeInputProperties,
|
||||
_get: id => {
|
||||
let type = credentialType.getById(id);
|
||||
|
||||
return credentialType.mergeInputProperties(type);
|
||||
},
|
||||
_source: vm.form.credential_type,
|
||||
_reference: 'vm.form.inputs',
|
||||
_key: 'inputs'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<at-panel ng-if="$state.current.name === 'credentials.add' || $state.current.name === 'credentials.edit'">
|
||||
<at-panel ng-if="!$state.current.name.includes('permissions')">
|
||||
<at-panel-heading>{{ vm.panelTitle }}</at-panel-heading>
|
||||
|
||||
<at-tab-group>
|
||||
@ -10,27 +10,26 @@
|
||||
<at-form state="vm.form">
|
||||
<at-input-text col="4" tab="1" state="vm.form.name"></at-input-text>
|
||||
<at-input-text col="4" tab="2" state="vm.form.description"></at-input-text>
|
||||
<at-input-select col="4" tab="3" state="vm.form.organization"></at-input-select>
|
||||
<at-input-lookup col="4" tab="3" state="vm.form.organization"></at-input-lookup>
|
||||
|
||||
<at-divider></at-divider>
|
||||
|
||||
<at-input-select col="4" tab="4" state="vm.form.credential_type"></at-input-select>
|
||||
<at-input-lookup col="4" tab="4" state="vm.form.credential_type"></at-input-lookup>
|
||||
|
||||
<at-input-group col="4" tab="4" state="vm.form.inputs">
|
||||
<at-input-group col="4" tab="5" state="vm.form.inputs">
|
||||
Type Details
|
||||
</at-input-group>
|
||||
|
||||
<at-action-group col="12" pos="right">
|
||||
<at-form-action type="cancel"></at-form-action>
|
||||
<at-form-action type="cancel" to="credentials"></at-form-action>
|
||||
<at-form-action type="save"></at-form-action>
|
||||
</at-action-group>
|
||||
</at-form>
|
||||
</at-panel-body>
|
||||
</at-panel>
|
||||
|
||||
<at-panel ng-if="$state.current.name === 'credentials.edit.permissions' ||
|
||||
$state.current.name === 'credentials.edit.permissions.add'">
|
||||
<at-panel-heading>Credentials Permissions</at-panel-heading>
|
||||
<at-panel ng-if="$state.current.name.includes('permissions')">
|
||||
<at-panel-heading>CREDENTIALS PERMISSIONS</at-panel-heading>
|
||||
|
||||
<at-tab-group>
|
||||
<at-tab state="vm.tab.details">Details</at-tab>
|
||||
@ -42,5 +41,5 @@
|
||||
</at-panel-body>
|
||||
</at-panel>
|
||||
|
||||
<div ng-if="$state.current.name === 'credentials.edit.permissions.add'" ui-view="modal"></div>
|
||||
<div ng-if="$state.current.name.includes('permissions.add')" ui-view="modal"></div>
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ function EditCredentialsController (models, $state, $scope) {
|
||||
let me = models.me;
|
||||
let credential = models.credential;
|
||||
let credentialType = models.credentialType;
|
||||
let organization = models.organization;
|
||||
let selectedCredentialType = credentialType.getById(credential.get('credential_type'));
|
||||
|
||||
vm.tab = {
|
||||
details: {
|
||||
@ -21,9 +21,9 @@ function EditCredentialsController (models, $state, $scope) {
|
||||
};
|
||||
|
||||
$scope.$watch('$state.current.name', (value) => {
|
||||
if (value === 'credentials.edit') {
|
||||
if (/credentials.edit($|\.organization$)/.test(value)) {
|
||||
vm.tab.details._active = true;
|
||||
vm.tab.details._permissions = false;
|
||||
vm.tab.permissions._active = false;
|
||||
} else {
|
||||
vm.tab.permissions._active = true;
|
||||
vm.tab.details._active = false;
|
||||
@ -39,23 +39,19 @@ function EditCredentialsController (models, $state, $scope) {
|
||||
omit: ['user', 'team', 'inputs']
|
||||
});
|
||||
|
||||
vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER;
|
||||
vm.form.organization._data = organization.get('results');
|
||||
vm.form.organization._format = 'objects';
|
||||
vm.form.organization._exp = 'org as org.name for org in state._data';
|
||||
vm.form.organization._display = 'name';
|
||||
vm.form.organization._key = 'id';
|
||||
vm.form.organization._value = organization.getById(credential.get('organization'));
|
||||
|
||||
vm.form.credential_type._data = credentialType.get('results');
|
||||
vm.form.credential_type._format = 'grouped-object';
|
||||
vm.form.credential_type._display = 'name';
|
||||
vm.form.credential_type._key = 'id';
|
||||
vm.form.credential_type._exp = 'type as type.name group by type.kind for type in state._data';
|
||||
vm.form.credential_type._value = credentialType.getById(credential.get('credential_type'));
|
||||
vm.form.organization._resource = 'organization';
|
||||
vm.form.organization._route = 'credentials.edit.organization';
|
||||
vm.form.organization._value = credential.get('summary_fields.organization.id');
|
||||
vm.form.organization._displayValue = credential.get('summary_fields.organization.name');
|
||||
|
||||
vm.form.credential_type._resource = 'credential_type';
|
||||
vm.form.credential_type._route = 'credentials.edit.credentialType';
|
||||
vm.form.credential_type._value = selectedCredentialType.id;
|
||||
vm.form.credential_type._displayValue = selectedCredentialType.name;
|
||||
|
||||
vm.form.inputs = {
|
||||
_get (type) {
|
||||
_get (id) {
|
||||
let type = credentialType.getById(id);
|
||||
let inputs = credentialType.mergeInputProperties(type);
|
||||
|
||||
if (type.id === credential.get('credential_type')) {
|
||||
@ -77,7 +73,7 @@ function EditCredentialsController (models, $state, $scope) {
|
||||
};
|
||||
|
||||
vm.form.onSaveSuccess = res => {
|
||||
$state.go('credentials', { reload: true });
|
||||
$state.go('credentials.edit', { credential_id: credential.get('id') }, { reload: true });
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
import PermissionsList from '../../src/access/permissions-list.controller';
|
||||
import CredentialForm from '../../src/credentials/credentials.form';
|
||||
import CredentialList from '../../src/credentials/credentials.list';
|
||||
import ListController from '../../src/credentials/list/credentials-list.controller';
|
||||
import LegacyCredentials from './legacy.credentials';
|
||||
import AddController from './add-credentials.controller.js';
|
||||
import EditController from './edit-credentials.controller.js';
|
||||
import { N_ } from '../../src/i18n';
|
||||
|
||||
function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType, Organization) {
|
||||
function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType) {
|
||||
let id = $stateParams.credential_id;
|
||||
|
||||
let promises = {
|
||||
me: new Me('get'),
|
||||
credentialType: new CredentialType('get'),
|
||||
organization: new Organization('get')
|
||||
credentialType: new CredentialType('get')
|
||||
};
|
||||
|
||||
if (id) {
|
||||
@ -29,46 +25,13 @@ CredentialsResolve.$inject = [
|
||||
'$stateParams',
|
||||
'MeModel',
|
||||
'CredentialModel',
|
||||
'CredentialTypeModel',
|
||||
'OrganizationModel'
|
||||
'CredentialTypeModel'
|
||||
];
|
||||
|
||||
function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceProvider) {
|
||||
let pathService = pathServiceProvider.$get();
|
||||
function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider) {
|
||||
let path = pathProvider.$get();
|
||||
let stateExtender = $stateExtenderProvider.$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`]);
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
let legacy = legacyProvider.$get();
|
||||
|
||||
stateExtender.addState({
|
||||
name: 'credentials.add',
|
||||
@ -78,7 +41,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
|
||||
},
|
||||
views: {
|
||||
'add@credentials': {
|
||||
templateUrl: pathService.getViewPath('credentials/add-edit-credentials'),
|
||||
templateUrl: path.getViewPath('credentials/add-edit-credentials'),
|
||||
controller: AddController,
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
@ -96,7 +59,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
|
||||
},
|
||||
views: {
|
||||
'edit@credentials': {
|
||||
templateUrl: pathService.getViewPath('credentials/add-edit-credentials'),
|
||||
templateUrl: path.getViewPath('credentials/add-edit-credentials'),
|
||||
controller: EditController,
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
@ -106,178 +69,24 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP
|
||||
}
|
||||
});
|
||||
|
||||
stateExtender.addState({
|
||||
name: "credentials.edit.permissions",
|
||||
url: "/permissions?{permission_search:queryset}",
|
||||
resolve: {
|
||||
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: '+ ' + 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');
|
||||
}
|
||||
}
|
||||
});
|
||||
stateExtender.addState(legacy.getStateConfiguration('list'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('edit-permissions'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('add-permissions'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('add-organization'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('edit-organization'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('add-credential-type'));
|
||||
stateExtender.addState(legacy.getStateConfiguration('edit-credential-type'));
|
||||
}
|
||||
|
||||
CredentialsConfig.$inject = [
|
||||
'$stateProvider',
|
||||
'$stateExtenderProvider',
|
||||
'PathServiceProvider'
|
||||
'$stateExtenderProvider',
|
||||
'LegacyCredentialsServiceProvider',
|
||||
'PathServiceProvider'
|
||||
];
|
||||
|
||||
angular
|
||||
.module('at.features.credentials', [])
|
||||
.config(CredentialsConfig)
|
||||
.controller('AddController', AddController)
|
||||
.controller('EditController', EditController);
|
||||
.controller('EditController', EditController)
|
||||
.service('LegacyCredentialsService', LegacyCredentials);
|
||||
|
||||
348
awx/ui/client/features/credentials/legacy.credentials.js
Normal file
348
awx/ui/client/features/credentials/legacy.credentials.js
Normal file
@ -0,0 +1,348 @@
|
||||
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: '+ ' + 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.lookupTemplateProvider = (ListDefinition, generateList) => {
|
||||
let html = generateList.build({
|
||||
mode: 'lookup',
|
||||
list: ListDefinition,
|
||||
input_type: 'radio'
|
||||
});
|
||||
|
||||
return `<lookup-modal>${html}</lookup-modal>`;
|
||||
};
|
||||
|
||||
this.organization = {
|
||||
url: '/organization?selected',
|
||||
searchPrefix: 'organization',
|
||||
params: {
|
||||
organization_search: {
|
||||
value: {
|
||||
page_size: 5,
|
||||
order_by: 'name',
|
||||
role_level: 'admin_role'
|
||||
},
|
||||
dynamic: true,
|
||||
squash: ''
|
||||
}
|
||||
},
|
||||
data: {
|
||||
basePath: 'organizations',
|
||||
formChildState: true
|
||||
},
|
||||
ncyBreadcrumb: {
|
||||
skip: true
|
||||
},
|
||||
views: {},
|
||||
resolve: {
|
||||
ListDefinition: ['OrganizationList', 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.credentialType = {
|
||||
url: '/credential_type?selected',
|
||||
searchPrefix: 'credential_type',
|
||||
params: {
|
||||
credential_type_search: {
|
||||
value: {
|
||||
page_size: 5,
|
||||
order_by: 'name'
|
||||
},
|
||||
dynamic: true,
|
||||
squash: ''
|
||||
}
|
||||
},
|
||||
data: {
|
||||
basePath: 'credential_types',
|
||||
formChildState: true
|
||||
},
|
||||
ncyBreadcrumb: {
|
||||
skip: true
|
||||
},
|
||||
views: {},
|
||||
resolve: {
|
||||
ListDefinition: ['CredentialTypesList', list => {
|
||||
return list;
|
||||
}],
|
||||
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||
(list, qs, $stateParams, GetBasePath) => {
|
||||
return qs.search(
|
||||
GetBasePath('credential_types'),
|
||||
$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.views['organization@credentials.add'] = {
|
||||
templateProvider: this.lookupTemplateProvider
|
||||
};
|
||||
|
||||
return this.organization;
|
||||
case 'edit-organization':
|
||||
this.organization.name = 'credentials.edit.organization';
|
||||
this.organization.views['organization@credentials.edit'] = {
|
||||
templateProvider: this.lookupTemplateProvider
|
||||
};
|
||||
|
||||
return this.organization;
|
||||
case 'add-credential-type':
|
||||
this.credentialType.name = 'credentials.add.credentialType';
|
||||
this.credentialType.views['credential_type@credentials.add'] = {
|
||||
templateProvider: this.lookupTemplateProvider
|
||||
};
|
||||
|
||||
return this.credentialType;
|
||||
case 'edit-credential-type':
|
||||
this.credentialType.name = 'credentials.edit.credentialType';
|
||||
this.credentialType.views['credential_type@credentials.edit'] = {
|
||||
templateProvider: this.lookupTemplateProvider
|
||||
};
|
||||
|
||||
return this.credentialType;
|
||||
|
||||
default:
|
||||
throw new Error(`Legacy state configuration for ${name} does not exist`);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
LegacyCredentialsService.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default LegacyCredentialsService;
|
||||
@ -1,7 +1,7 @@
|
||||
@import 'action/_index';
|
||||
@import 'input/_index';
|
||||
@import 'panel/_index';
|
||||
@import 'modal/_index';
|
||||
@import 'panel/_index';
|
||||
@import 'popover/_index';
|
||||
@import 'tabs/_index';
|
||||
@import 'utility/_index';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.at-ActionGroup {
|
||||
margin-top: @at-space-6x;
|
||||
margin-top: @at-margin-panel;
|
||||
|
||||
button:last-child {
|
||||
margin-left: @at-space-5x;
|
||||
margin-left: @at-margin-panel-inset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,14 +38,14 @@ function atFormActionController ($state) {
|
||||
vm.setCancelDefaults = () => {
|
||||
scope.text = 'CANCEL';
|
||||
scope.fill = 'Hollow';
|
||||
scope.color = 'white';
|
||||
scope.action = () => $state.go('^');
|
||||
scope.color = 'default';
|
||||
scope.action = () => $state.go(scope.to || '^');
|
||||
};
|
||||
|
||||
vm.setSaveDefaults = () => {
|
||||
scope.text = 'SAVE';
|
||||
scope.fill = '';
|
||||
scope.color = 'green';
|
||||
scope.color = 'success';
|
||||
scope.action = () => form.submit();
|
||||
};
|
||||
}
|
||||
@ -64,7 +64,8 @@ function atFormAction (pathService) {
|
||||
link,
|
||||
scope: {
|
||||
state: '=',
|
||||
type: '@'
|
||||
type: '@',
|
||||
to: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,6 +2,9 @@ function atFormLink (scope, el, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let form = el[0];
|
||||
|
||||
scope.ns = 'form';
|
||||
scope[scope.ns] = { modal: {} };
|
||||
|
||||
formController.init(scope, form);
|
||||
}
|
||||
|
||||
@ -9,10 +12,10 @@ function AtFormController (eventService) {
|
||||
let vm = this || {};
|
||||
|
||||
let scope;
|
||||
let modal;
|
||||
let form;
|
||||
|
||||
vm.components = [];
|
||||
vm.modal = {};
|
||||
vm.state = {
|
||||
isValid: false,
|
||||
disabled: false,
|
||||
@ -22,6 +25,7 @@ function AtFormController (eventService) {
|
||||
vm.init = (_scope_, _form_) => {
|
||||
scope = _scope_;
|
||||
form = _form_;
|
||||
modal = scope[scope.ns].modal;
|
||||
|
||||
vm.setListeners();
|
||||
};
|
||||
@ -102,7 +106,7 @@ function AtFormController (eventService) {
|
||||
message = err.data;
|
||||
}
|
||||
|
||||
vm.modal.show('Unable to Submit', `Unexpected Error: ${message}`);
|
||||
modal.show('Unable to Submit', `Unexpected Error: ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -110,7 +114,7 @@ function AtFormController (eventService) {
|
||||
let title = 'Unable to Submit';
|
||||
let message = 'Unexpected server error. View the console for more information';
|
||||
|
||||
vm.modal.show(title, message);
|
||||
modal.show(title, message);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -5,5 +5,5 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<at-modal state="vm.modal"></at-modal>
|
||||
<at-modal></at-modal>
|
||||
</div>
|
||||
|
||||
@ -7,8 +7,6 @@ import inputGroup from './input/group.directive';
|
||||
import inputLabel from './input/label.directive';
|
||||
import inputLookup from './input/lookup.directive';
|
||||
import inputMessage from './input/message.directive';
|
||||
import inputNumber from './input/number.directive';
|
||||
import inputSelect from './input/select.directive';
|
||||
import inputSecret from './input/secret.directive';
|
||||
import inputText from './input/text.directive';
|
||||
import inputTextarea from './input/textarea.directive';
|
||||
@ -34,9 +32,7 @@ angular
|
||||
.directive('atInputLabel', inputLabel)
|
||||
.directive('atInputLookup', inputLookup)
|
||||
.directive('atInputMessage', inputMessage)
|
||||
.directive('atInputNumber', inputNumber)
|
||||
.directive('atInputSecret', inputSecret)
|
||||
.directive('atInputSelect', inputSelect)
|
||||
.directive('atInputText', inputText)
|
||||
.directive('atInputTextarea', inputTextarea)
|
||||
.directive('atInputTextareaSecret', inputTextareaSecret)
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
.at-Input {
|
||||
.at-mixin-Placeholder(@at-gray-dark-3x);
|
||||
.at-mixin-Placeholder(@at-color-input-placeholder);
|
||||
|
||||
height: @at-input-height;
|
||||
background: @at-white;
|
||||
height: @at-height-input;
|
||||
background: @at-color-input-background;
|
||||
border-radius: @at-border-radius;
|
||||
color: @at-gray-dark-5x;
|
||||
color: @at-color-input-text;
|
||||
|
||||
&, &:active {
|
||||
border-color: @at-gray-dark-2x;
|
||||
border-color: @at-color-input-border;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: @at-blue;
|
||||
border-color: @at-color-input-focus;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background: @at-color-input-disabled;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,43 +25,43 @@
|
||||
|
||||
& > label {
|
||||
& > input[type=checkbox] {
|
||||
height: @at-input-height;
|
||||
height: @at-height-input;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
& > p {
|
||||
margin: 0;
|
||||
padding: 0 0 0 @at-space-6x;
|
||||
padding: 0 0 0 @at-padding-panel;
|
||||
line-height: @at-line-height-tall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputContainer {
|
||||
margin-top: @at-space-6x;
|
||||
margin-top: @at-margin-panel;
|
||||
}
|
||||
|
||||
.at-Input-button {
|
||||
min-width: @at-input-button-width;
|
||||
display: block;
|
||||
height: @at-input-height;
|
||||
height: @at-height-button;
|
||||
line-height: 1;
|
||||
|
||||
&, &:active, &:hover, &:focus {
|
||||
color: @at-gray-dark-3x;
|
||||
border-color: @at-gray-dark-2x;
|
||||
background-color: @at-white;
|
||||
color: @at-color-button-text-default;
|
||||
border-color: @at-color-input-border;
|
||||
background-color: @at-color-default;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Input--focus {
|
||||
border-color: @at-blue;
|
||||
border-color: @at-color-input-focus;
|
||||
}
|
||||
|
||||
.at-Input--rejected {
|
||||
&, &:focus {
|
||||
border-color: @at-red;
|
||||
border-color: @at-color-input-error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +70,6 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: @at-input-button-width;
|
||||
z-index: -2;
|
||||
opacity: 0;
|
||||
}
|
||||
@ -77,15 +80,15 @@
|
||||
|
||||
.at-InputGroup {
|
||||
padding: 0;
|
||||
margin: @at-space-6x 0 0 0;
|
||||
margin: @at-margin-panel 0 0 0;
|
||||
}
|
||||
|
||||
.at-InputGroup-border {
|
||||
position: absolute;
|
||||
width: @at-inset-width;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
background: @at-gray-dark;
|
||||
left: -@at-inset-width;
|
||||
background: @at-color-panel-border;
|
||||
left: -5px;
|
||||
}
|
||||
|
||||
.at-InputGroup-button {
|
||||
@ -93,19 +96,22 @@
|
||||
|
||||
& > button {
|
||||
height: 100%;
|
||||
border-right: none;
|
||||
color: @at-color-button-text-default;
|
||||
min-width: @at-input-button-width;
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputGroup-title {
|
||||
.at-mixin-Heading(@at-font-size-2x);
|
||||
margin: 0 0 0 @at-space-5x;
|
||||
.at-mixin-Heading(@at-font-size-panel-inset-heading);
|
||||
margin: 0 0 0 @at-margin-panel-inset;
|
||||
}
|
||||
|
||||
.at-InputGroup-divider {
|
||||
clear: both;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: @at-space-6x;
|
||||
height: @at-height-divider;
|
||||
}
|
||||
|
||||
.at-InputLabel {
|
||||
@ -114,17 +120,17 @@
|
||||
}
|
||||
|
||||
.at-InputLabel-name {
|
||||
color: @at-gray-dark-4x;
|
||||
font-size: @at-font-size-2x;
|
||||
font-weight: @at-font-weight;
|
||||
color: @at-color-form-label;
|
||||
font-size: @at-font-size-form-label;
|
||||
font-weight: @at-font-weight-body;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.at-InputLabel-hint {
|
||||
margin-left: @at-space-4x;
|
||||
color: @at-gray-dark-3x;
|
||||
font-size: @at-font-size;
|
||||
font-weight: @at-font-weight;
|
||||
margin-left: @at-margin-form-label-hint;
|
||||
color: @at-color-input-hint;
|
||||
font-size: @at-font-size-help-text;
|
||||
font-weight: @at-font-weight-body;
|
||||
line-height: @at-line-height-short;
|
||||
}
|
||||
|
||||
@ -137,15 +143,15 @@
|
||||
margin-bottom: 0;
|
||||
|
||||
& > input[type=checkbox] {
|
||||
margin: 0 @at-space 0 0;
|
||||
margin: 0 3px 0 0;
|
||||
position: relative;
|
||||
top: @at-space;
|
||||
top: 3px
|
||||
}
|
||||
|
||||
& > p {
|
||||
font-size: @at-font-size;
|
||||
color: @at-gray-dark-4x;
|
||||
font-weight: @at-font-weight;
|
||||
font-size: @at-font-size-help-text;
|
||||
color: @at-color-form-label;
|
||||
font-weight: @at-font-weight-body;
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@ -153,16 +159,16 @@
|
||||
}
|
||||
|
||||
.at-InputMessage--rejected {
|
||||
font-size: @at-font-size;
|
||||
color: @at-red;
|
||||
margin: @at-space-3x 0 0 0;
|
||||
font-size: @at-font-size-help-text;
|
||||
color: @at-color-error;
|
||||
margin: @at-margin-input-message 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.at-InputLabel-required {
|
||||
color: @at-red;
|
||||
font-weight: @at-font-weight-2x;
|
||||
font-size: @at-font-size-2x;
|
||||
color: @at-color-error;
|
||||
font-weight: @at-font-weight-heading;
|
||||
font-size: @at-font-size-form-label;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -171,13 +177,13 @@
|
||||
width: 100%;
|
||||
|
||||
& > i {
|
||||
font-size: @at-font-size;
|
||||
font-size: @at-font-size-button;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
top: @at-space-4x;
|
||||
right: @at-space-4x;
|
||||
color: @at-gray-dark-2x;
|
||||
top: @at-height-input / 3;
|
||||
right: @at-height-input / 3;
|
||||
color: @at-color-input-icon;
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +194,7 @@
|
||||
}
|
||||
|
||||
.at-InputSelect-select {
|
||||
height: @at-input-height;
|
||||
height: @at-height-input;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
|
||||
@ -49,7 +49,6 @@ function AtInputGroupController ($scope, $compile) {
|
||||
|
||||
vm.insert(group);
|
||||
state._group = group;
|
||||
vm.compile(group);
|
||||
};
|
||||
|
||||
vm.createComponentConfigs = inputs => {
|
||||
@ -138,20 +137,22 @@ function AtInputGroupController ($scope, $compile) {
|
||||
vm.createComponent = (input, index) => {
|
||||
let tabindex = Number(scope.tab) + index;
|
||||
let col = input._expand ? 12 : scope.col;
|
||||
|
||||
return angular.element(
|
||||
let component = angular.element(
|
||||
`<${input._component} col="${col}" tab="${tabindex}"
|
||||
state="${state._reference}._group[${index}]">
|
||||
</${input._component}>`
|
||||
);
|
||||
|
||||
$compile(component)(scope.$parent)
|
||||
|
||||
return component;
|
||||
};
|
||||
|
||||
vm.createDivider = () => {
|
||||
return angular.element('<at-divider></at-divider>');
|
||||
};
|
||||
let divider = angular.element('<at-divider></at-divider>');
|
||||
$compile(divider[0])(scope.$parent);
|
||||
|
||||
vm.compile = group => {
|
||||
group.forEach(component => $compile(component._element[0])(scope.$parent));
|
||||
return divider;
|
||||
};
|
||||
|
||||
vm.clear = () => {
|
||||
|
||||
@ -9,43 +9,46 @@ function atInputLookupLink (scope, element, attrs, controllers) {
|
||||
inputController.init(scope, element, formController);
|
||||
}
|
||||
|
||||
function AtInputLookupController (baseInputController) {
|
||||
function AtInputLookupController (baseInputController, $state, $stateParams) {
|
||||
let vm = this || {};
|
||||
|
||||
vm.lookup = {};
|
||||
let scope;
|
||||
|
||||
vm.init = (scope, element, form) => {
|
||||
baseInputController.call(vm, 'input', scope, element, form);
|
||||
vm.init = (_scope_, element, form) => {
|
||||
baseInputController.call(vm, 'input', _scope_, element, form);
|
||||
|
||||
vm.lookup.modal = {
|
||||
title: 'Select Organization',
|
||||
buttons: [
|
||||
{
|
||||
type: 'cancel'
|
||||
},
|
||||
{
|
||||
type: 'select'
|
||||
}
|
||||
]
|
||||
};
|
||||
scope = _scope_;
|
||||
|
||||
vm.lookup.search = {
|
||||
placeholder: 'test'
|
||||
};
|
||||
|
||||
vm.lookup.table = {
|
||||
|
||||
};
|
||||
scope.$watch(scope.state._resource, vm.watchResource);
|
||||
|
||||
vm.check();
|
||||
};
|
||||
|
||||
vm.watchResource = () => {
|
||||
if (scope[scope.state._resource]) {
|
||||
scope.state._value = scope[scope.state._resource];
|
||||
scope.state._displayValue = scope[`${scope.state._resource}_name`];
|
||||
|
||||
vm.check();
|
||||
}
|
||||
};
|
||||
|
||||
vm.search = () => {
|
||||
vm.modal.show('test');
|
||||
let params = {};
|
||||
|
||||
if (scope.state._value) {
|
||||
params.selected = scope.state._value;
|
||||
}
|
||||
|
||||
$state.go(scope.state._route, params);
|
||||
};
|
||||
}
|
||||
|
||||
AtInputLookupController.$inject = ['BaseInputController'];
|
||||
AtInputLookupController.$inject = [
|
||||
'BaseInputController',
|
||||
'$state',
|
||||
'$stateParams'
|
||||
];
|
||||
|
||||
function atInputLookup (pathService) {
|
||||
return {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn at-ButtonHollow--white at-Input-button"
|
||||
<button class="btn at-ButtonHollow--default at-Input-button"
|
||||
ng-disabled="state._disabled || form.disabled"
|
||||
ng-click="vm.search()">
|
||||
<i class="fa fa-search"></i>
|
||||
@ -13,7 +13,7 @@
|
||||
<input type="text"
|
||||
class="form-control at-Input"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
ng-model="state._displayValue"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
@ -23,8 +23,5 @@
|
||||
<at-input-message></at-input-message>
|
||||
</div>
|
||||
|
||||
<at-modal state="vm.lookup">
|
||||
<at-search></at-search>
|
||||
<at-table></at-table>
|
||||
</at-modal>
|
||||
<div ui-view="{{ state._resource }}"></div>
|
||||
</div>
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
const DEFAULT_STEP = '1';
|
||||
const DEFAULT_MIN = '0';
|
||||
const DEFAULT_MAX = '1000000000';
|
||||
const DEFAULT_PLACEHOLDER = '';
|
||||
|
||||
function atInputNumberLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
|
||||
if (scope.tab === '1') {
|
||||
element.find('input')[0].focus();
|
||||
}
|
||||
|
||||
inputController.init(scope, element, formController);
|
||||
}
|
||||
|
||||
function AtInputNumberController (baseInputController) {
|
||||
let vm = this || {};
|
||||
|
||||
vm.init = (scope, element, form) => {
|
||||
baseInputController.call(vm, 'input', scope, element, form);
|
||||
|
||||
scope.state._step = scope.state._step || DEFAULT_STEP;
|
||||
scope.state._min = scope.state._min || DEFAULT_MIN;
|
||||
scope.state._max = scope.state._max || DEFAULT_MAX;
|
||||
scope.state._placeholder = scope.state._placeholder || DEFAULT_PLACEHOLDER;
|
||||
|
||||
vm.check();
|
||||
};
|
||||
}
|
||||
|
||||
AtInputNumberController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputNumber (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputNumber'],
|
||||
templateUrl: pathService.getPartialPath('components/input/number'),
|
||||
controller: AtInputNumberController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputNumberLink,
|
||||
scope: {
|
||||
state: '=',
|
||||
col: '@',
|
||||
tab: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputNumber.$inject = ['PathService'];
|
||||
|
||||
export default atInputNumber;
|
||||
@ -1,19 +0,0 @@
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<input type="number"
|
||||
class="form-control at-Input"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
ng-attr-min="state._min"
|
||||
ng-attr-max="state._max"
|
||||
ng-attr-step="state._step"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
|
||||
<at-input-message></at-input-message>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,10 +1,28 @@
|
||||
.at-Modal-body {
|
||||
font-size: @at-font-size;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.at-Modal-dismiss {
|
||||
.at-mixin-ButtonIcon();
|
||||
font-size: @at-font-size-modal-dismiss;
|
||||
color: @at-color-icon-dismiss;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.at-Modal-heading {
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
|
||||
& > .at-Modal-dismiss {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Modal-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.at-mixin-Heading(@at-font-size-3x);
|
||||
.at-mixin-Heading(@at-font-size-modal-heading);
|
||||
}
|
||||
|
||||
.at-Modal-body {
|
||||
font-size: @at-font-size;
|
||||
}
|
||||
|
||||
@ -1,45 +1,74 @@
|
||||
const DEFAULT_ANIMATION_DURATION = 150;
|
||||
|
||||
function atModalLink (scope, el, attr, controllers) {
|
||||
function atModalLink (scope, el, attrs, controllers) {
|
||||
let modalController = controllers[0];
|
||||
let container = el[0];
|
||||
let property = `scope.${scope.ns}.modal`;
|
||||
|
||||
modalController.init(scope, container);
|
||||
let done = scope.$watch(property, () => {
|
||||
modalController.init(scope, el);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function AtModalController () {
|
||||
function AtModalController (eventService) {
|
||||
let vm = this;
|
||||
|
||||
let scope;
|
||||
let container;
|
||||
let overlay;
|
||||
let modal;
|
||||
let listeners;
|
||||
|
||||
vm.init = (_scope_, _container_) => {
|
||||
scope = _scope_;
|
||||
container = _container_;
|
||||
vm.init = (scope, el) => {
|
||||
overlay = el[0];
|
||||
modal = el.find('.at-Modal-window')[0];
|
||||
|
||||
scope.state.show = vm.show;
|
||||
scope.state.hide = vm.hide;
|
||||
vm.modal = scope[scope.ns].modal;
|
||||
vm.modal.show = vm.show;
|
||||
vm.modal.hide = vm.hide;
|
||||
};
|
||||
|
||||
vm.show = (title, message) => {
|
||||
scope.title = title;
|
||||
scope.message = message;
|
||||
vm.modal.title = title;
|
||||
vm.modal.message = message;
|
||||
|
||||
container.style.display = 'block';
|
||||
container.style.opacity = 1;
|
||||
event.stopPropagation();
|
||||
|
||||
listeners = eventService.addListeners([
|
||||
[window, 'click', vm.clickToHide]
|
||||
]);
|
||||
|
||||
overlay.style.display = 'block';
|
||||
overlay.style.opacity = 1;
|
||||
};
|
||||
|
||||
vm.hide = () => {
|
||||
container.style.opacity = 0;
|
||||
overlay.style.opacity = 0;
|
||||
|
||||
setTimeout(() => {
|
||||
container.style.display = 'none';
|
||||
scope.message = '';
|
||||
scope.title = '';
|
||||
}, DEFAULT_ANIMATION_DURATION);
|
||||
eventService.remove(listeners);
|
||||
|
||||
setTimeout(() => overlay.style.display = 'none', DEFAULT_ANIMATION_DURATION);
|
||||
};
|
||||
|
||||
vm.clickToHide = event => {
|
||||
if (vm.clickIsOutsideModal(event)) {
|
||||
vm.hide();
|
||||
}
|
||||
};
|
||||
|
||||
vm.clickIsOutsideModal = e => {
|
||||
let m = modal.getBoundingClientRect();
|
||||
let cx = e.clientX;
|
||||
let cy = e.clientY;
|
||||
|
||||
if (cx < m.left || cx > m.right || cy > m.bottom || cy < m.top) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
AtModalController.$inject = ['EventService'];
|
||||
|
||||
function atModal (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
@ -50,9 +79,7 @@ function atModal (pathService) {
|
||||
controller: AtModalController,
|
||||
controllerAs: 'vm',
|
||||
link: atModalLink,
|
||||
scope: {
|
||||
state: '='
|
||||
}
|
||||
scope: true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +1,31 @@
|
||||
<div class="modal at-Modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="vm.hide()">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
<h4 class="modal-title at-Modal-title">{{ title }}</h4>
|
||||
<div class="modal-content at-Modal-window">
|
||||
<div class="row">
|
||||
<div class="col-xs-10">
|
||||
<div class="at-Modal-heading">
|
||||
<h4 class="modal-title at-Modal-title">{{ vm.modal.title }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<div class="at-Modal-dismiss">
|
||||
<i class="fa fa-lg fa-times-circle" ng-click="vm.hide()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body at-Modal-body">
|
||||
<p ng-show="message">{{ message }}</p>
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn at-ButtonHollow--white" ng-click="vm.hide()">
|
||||
OK
|
||||
</button>
|
||||
|
||||
<ng-transclude></ng-transclude>
|
||||
|
||||
<div ng-show="vm.modal.message">
|
||||
<div class="modal-body at-Modal-body">
|
||||
<p>{{ vm.modal.message }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn at-ButtonHollow--default"
|
||||
ng-click="vm.hide()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.at-Panel {
|
||||
margin: @at-space-6x 0 0 0;
|
||||
padding: @at-space-6x;
|
||||
border-color: @at-gray-dark;
|
||||
margin: @at-margin-panel 0 0 0;
|
||||
padding: @at-padding-panel;
|
||||
border-color: @at-color-panel-border;
|
||||
}
|
||||
|
||||
.at-Panel-heading {
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
.at-Panel-dismiss {
|
||||
.at-mixin-ButtonIcon();
|
||||
color: @at-color-icon-dismiss;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@ -20,6 +21,6 @@
|
||||
}
|
||||
|
||||
.at-Panel-headingTitle {
|
||||
.at-mixin-Heading(@at-font-size-3x);
|
||||
.at-mixin-Heading(@at-font-size-panel-heading);
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.at-Popover {
|
||||
padding: 0 0 0 @at-space-3x;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
.at-Popover--inline {
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
.at-Popover-icon {
|
||||
.at-mixin-ButtonIcon();
|
||||
font-size: @at-font-size-4x;
|
||||
color: @at-color-icon-popover;
|
||||
font-size: @at-font-size-icon;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
@ -17,35 +18,35 @@
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
color: @at-white;
|
||||
background-color: @at-gray-dark-4x;
|
||||
max-width: @at-popover-width;
|
||||
padding: @at-space-4x;
|
||||
background-color: @at-color-body-background-dark;
|
||||
max-width: @at-popover-maxwidth;
|
||||
padding: @at-padding-popover;
|
||||
height: auto;
|
||||
position: fixed;
|
||||
z-index: 2000;
|
||||
margin: 0 0 0 @at-space-6x;
|
||||
margin: 0 0 0 18px;
|
||||
border-radius: @at-border-radius;
|
||||
box-shadow: 0 5px 10px rgba(0,0,0, 0.2);
|
||||
transition: opacity .15s linear;
|
||||
font-weight: @at-font-weight
|
||||
font-weight: @at-font-weight-body;
|
||||
}
|
||||
|
||||
.at-Popover-arrow {
|
||||
color: @at-gray-dark-4x;
|
||||
color: @at-color-body-background-dark;
|
||||
position: fixed;
|
||||
z-index: 1999;
|
||||
padding: 0;
|
||||
margin: @at-space-4x 0 0 @at-space;
|
||||
margin: 8px 0 0 3px;
|
||||
}
|
||||
|
||||
.at-Popover-title {
|
||||
.at-mixin-Heading(@at-font-size);
|
||||
color: @at-white;
|
||||
margin-bottom: @at-space-4x;
|
||||
.at-mixin-Heading(@at-font-size-body);
|
||||
color: @at-color-body-text-dark;
|
||||
margin-bottom: @at-margin-popover;
|
||||
}
|
||||
|
||||
.at-Popover-text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: @at-font-size;
|
||||
font-size: @at-font-size-body;
|
||||
}
|
||||
|
||||
@ -1,26 +1,27 @@
|
||||
.at-TabGroup {
|
||||
margin-top: @at-space-6x;
|
||||
margin-top: @at-margin-panel;
|
||||
}
|
||||
|
||||
.at-Tab {
|
||||
margin: 0 @at-space-5x 0 0;
|
||||
font-size: @at-font-size;
|
||||
margin: 0 @at-margin-item-column 0 0;
|
||||
font-size: @at-font-size-body;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.at-Tab--active {
|
||||
&, &:hover, &:active, &:focus {
|
||||
color: @at-white;
|
||||
background-color: @at-gray-dark-3x;
|
||||
border-color: @at-gray-dark-3x;
|
||||
color: @at-color-tab-text-default-active;
|
||||
background-color: @at-color-tab-default-active;
|
||||
border-color: @at-color-tab-border-default-active;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Tab--disabled {
|
||||
&, &:hover, &:active, &:focus {
|
||||
background-color: @at-white;
|
||||
color: @at-gray-dark-2x;
|
||||
border-color: @at-gray-dark-2x;
|
||||
background-color: @at-color-tab-default-disabled;
|
||||
color: @at-color-tab-text-default-disabled;
|
||||
border-color: @at-color-tab-border-default-disabled;
|
||||
opacity: 0.65;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<button class="btn at-ButtonHollow--white at-Tab"
|
||||
<button class="btn at-ButtonHollow--default at-Tab"
|
||||
ng-attr-disabled="{{ state._disabled || undefined }}"
|
||||
ng-class="{ 'at-Tab--active': state._active, 'at-Tab--disabled': state._disabled }"
|
||||
ng-click="vm.go()">
|
||||
|
||||
@ -77,25 +77,24 @@ function httpOptions (resource) {
|
||||
});
|
||||
}
|
||||
|
||||
function get (method, keys) {
|
||||
let model;
|
||||
function options (keys) {
|
||||
return this.find('options', keys);
|
||||
}
|
||||
|
||||
if (keys) {
|
||||
model = this.model[method.toUpperCase()];
|
||||
} else {
|
||||
model = this.model.GET;
|
||||
keys = method;
|
||||
}
|
||||
function get (keys) {
|
||||
return this.find('get', keys);
|
||||
}
|
||||
|
||||
function find (method, keys) {
|
||||
let value = this.model[method.toUpperCase()];
|
||||
|
||||
if (!keys) {
|
||||
return model;
|
||||
return value;
|
||||
}
|
||||
|
||||
keys = keys.split('.');
|
||||
|
||||
let value = model;
|
||||
|
||||
try {
|
||||
keys = keys.split('.');
|
||||
|
||||
keys.forEach(key => {
|
||||
let bracketIndex = key.indexOf('[');
|
||||
let hasArray = bracketIndex !== -1;
|
||||
@ -137,6 +136,8 @@ function getById (id) {
|
||||
function BaseModel (path) {
|
||||
this.model = {};
|
||||
this.get = get;
|
||||
this.options = options;
|
||||
this.find = find;
|
||||
this.normalizePath = normalizePath;
|
||||
this.getById = getById;
|
||||
this.request = request;
|
||||
|
||||
@ -3,7 +3,7 @@ const ENCRYPTED_VALUE = '$encrypted$';
|
||||
let BaseModel;
|
||||
|
||||
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) {
|
||||
config.omit.forEach(key => {
|
||||
|
||||
68
awx/ui/client/lib/theme/_base-variables.less
Normal file
68
awx/ui/client/lib/theme/_base-variables.less
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* All base variables used. These should only be referenced by the contextual variables defined
|
||||
* in the _contextual-variables.less file. In development, unless you are intentionally making a
|
||||
* fundamental change, these variables should not be modified, removed, or added to.
|
||||
*
|
||||
* These variables should not be used directly in development of components or features. If an
|
||||
* alias doesn't exist for the context you're working within, check with UX to create a new alias
|
||||
* or to define a more applicable alias.
|
||||
*
|
||||
* The goal is for UX to define the contexts for the contextual variables, so it's easy to make
|
||||
* modifications like, "Change heading text to be smaller" or "Make all warnings a lighter shade
|
||||
* of orange"
|
||||
*
|
||||
* 1. Colors
|
||||
* 2. Typography
|
||||
* 3. Layout
|
||||
*
|
||||
*/
|
||||
|
||||
// 1. Colors --------------------------------------------------------------------------------------
|
||||
|
||||
@at-gray-light-3x: #fcfcfc;
|
||||
@at-gray-light-2x: #f2f2f2;
|
||||
@at-gray-light: #ebebeb;
|
||||
@at-gray: #e1e1e1;
|
||||
@at-gray-dark: #d7d7d7;
|
||||
@at-gray-dark-2x: #b7b7b7;
|
||||
@at-gray-dark-3x: #A9A9A9;
|
||||
@at-gray-dark-4x: #848992;
|
||||
@at-gray-dark-5x: #707070;
|
||||
@at-gray-dark-6x: #161b1f;
|
||||
|
||||
@at-white: #ffffff;
|
||||
@at-white-hover: #f2f2f2;
|
||||
|
||||
@at-blue: #337ab7;
|
||||
@at-blue-hover: #286090;
|
||||
|
||||
@at-green: #5cb85c;
|
||||
@at-green-hover: #449D44;
|
||||
|
||||
@at-orange: #f0ad4e;
|
||||
@at-orange-hover: #ec971f;
|
||||
|
||||
@at-red: #d9534f;
|
||||
@at-red-hover: #c9302c;
|
||||
|
||||
@at-red-bright: #ff0000;
|
||||
@at-red-bright-hover: #d81f1f;
|
||||
|
||||
// 2. Typography ----------------------------------------------------------------------------------
|
||||
|
||||
@at-font-size: 12px;
|
||||
@at-font-size-2x: 13px;
|
||||
@at-font-size-3x: 14px;
|
||||
@at-font-size-4x: 16px;
|
||||
@at-font-size-5x: 20px;
|
||||
|
||||
@at-font-weight: 400;
|
||||
@at-font-weight-2x: 700;
|
||||
|
||||
// 3. Layout --------------------------------------------------------------------------------------
|
||||
|
||||
@at-space: 5px;
|
||||
@at-space-2x: 10px;
|
||||
@at-space-3x: 15px;
|
||||
@at-space-4x: 20px;
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
/**
|
||||
* For styles that are used in more than one place throughout the application.
|
||||
*
|
||||
* 1. Buttons
|
||||
*
|
||||
*/
|
||||
|
||||
// 1. Buttons -------------------------------------------------------------------------------------
|
||||
|
||||
.at-Button--green {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-green', 'at-white');
|
||||
|
||||
&[disabled] {
|
||||
background: @at-gray-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Button--blue {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-blue', 'at-white');
|
||||
}
|
||||
|
||||
.at-Button--red {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-red', 'at-white');
|
||||
}
|
||||
|
||||
.at-ButtonHollow--white {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonHollow('at-gray-dark-3x', 'at-gray-dark-2x');
|
||||
border-color: @at-gray-dark;
|
||||
}
|
||||
|
||||
.at-ButtonIcon {
|
||||
padding: @at-space-2x @at-space-4x;
|
||||
font-size: @at-font-size-3x;
|
||||
}
|
||||
139
awx/ui/client/lib/theme/_contextual-variables.less
Normal file
139
awx/ui/client/lib/theme/_contextual-variables.less
Normal file
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* All variables used in the UI. Use these variables directly during the development of components
|
||||
* and features. Be sure the context of the variable name applies to the work that's being done.
|
||||
* For example, it wouldn't make sense to use `@at-input-height` to describe the height of a
|
||||
* button. Either add an alias if it makes sense to use the same base variable, or add a new
|
||||
* base variable to reference.
|
||||
*
|
||||
* Keep in mind the goal is to be able to modify an item by referencing its context instead of
|
||||
* an arbitrary variable name. For example, tt should be a simple change when an ask comes in to
|
||||
* "increase the height of inputs"
|
||||
*
|
||||
* 1. Colors
|
||||
* 2. Typography
|
||||
* 3. Layout
|
||||
* 4. Buttons
|
||||
* 5. Misc
|
||||
*
|
||||
*/
|
||||
|
||||
// 1. Colors --------------------------------------------------------------------------------------
|
||||
|
||||
@at-color-default: @at-white;
|
||||
@at-color-default-hover: @at-white-hover;
|
||||
|
||||
@at-color-unreachable: @at-red-bright;
|
||||
@at-color-unreachable-hover: @at-red-bright-hover;
|
||||
|
||||
@at-color-error: @at-red;
|
||||
@at-color-error-hover: @at-red-hover;
|
||||
|
||||
@at-color-warning: @at-orange;
|
||||
@at-color-warning-hover: @at-orange-hover;
|
||||
|
||||
@at-color-info: @at-blue;
|
||||
@at-color-info-hover: @at-blue-hover;
|
||||
|
||||
@at-color-success: @at-green;
|
||||
@at-color-success-hover: @at-green-hover;
|
||||
|
||||
@at-color-disabled: @at-gray-dark;
|
||||
|
||||
@at-color-body-background-dark: @at-gray-dark-5x;
|
||||
@at-color-body-text-dark: @at-white;
|
||||
@at-color-body-background: @at-gray-light-3x;
|
||||
@at-color-body-text: @at-gray-dark-5x;
|
||||
|
||||
@at-color-button-border-default: @at-gray-dark-2x;
|
||||
@at-color-button-text-default: @at-gray-dark-5x;
|
||||
|
||||
@at-color-tab-default-active: @at-gray-dark-2x;
|
||||
@at-color-tab-border-default-active: @at-gray-dark-2x;
|
||||
@at-color-tab-text-default-active: @at-white;
|
||||
|
||||
@at-color-tab-default-disabled: @at-white;
|
||||
@at-color-tab-border-default-disabled: @at-gray-dark-2x;
|
||||
@at-color-tab-text-default-disabled: @at-gray-dark-5x;
|
||||
|
||||
@at-color-form-label: @at-gray-dark-5x;
|
||||
|
||||
@at-color-input-border: @at-gray-dark-2x;
|
||||
@at-color-input-error: @at-color-error;
|
||||
@at-color-input-focus: @at-color-info;
|
||||
@at-color-input-hint: @at-gray-dark-4x;
|
||||
@at-color-input-icon: @at-gray-dark-2x;
|
||||
@at-color-input-placeholder: @at-gray-dark-4x;
|
||||
@at-color-input-text: @at-gray-dark-6x;
|
||||
@at-color-input-background: @at-gray-light-3x;
|
||||
@at-color-input-disabled: @at-gray-light-2x;
|
||||
|
||||
@at-color-icon-dismiss: @at-gray-dark;
|
||||
@at-color-icon-popover: @at-gray-dark-3x;
|
||||
@at-color-icon-hover: @at-gray-dark-5x;
|
||||
|
||||
@at-color-panel-heading: @at-gray-dark-5x;
|
||||
@at-color-panel-border: @at-gray-dark;
|
||||
|
||||
@at-color-search-key-active: @at-blue;
|
||||
|
||||
@at-color-table-header-background: @at-gray-light;
|
||||
@at-color-line-separator: @at-gray;
|
||||
|
||||
// 2. Typography ----------------------------------------------------------------------------------
|
||||
|
||||
@at-font-size-body: @at-font-size-3x;
|
||||
@at-font-size-button: @at-font-size;
|
||||
@at-font-size-breadcrumb: @at-font-size-3x;
|
||||
@at-font-size-form-label: @at-font-size-2x;
|
||||
@at-font-size-help-text: @at-font-size;
|
||||
@at-font-size-icon: @at-font-size-4x;
|
||||
@at-font-size-input: @at-font-size-3x;
|
||||
@at-font-size-panel-heading: @at-font-size-3x;
|
||||
@at-font-size-panel-inset-heading: @at-font-size-2x;
|
||||
@at-font-size-modal-heading: @at-font-size-3x;
|
||||
@at-font-size-modal-dismiss: @at-font-size-3x;
|
||||
@at-font-size-navigation: @at-font-size-3x;
|
||||
@at-font-size-table-heading: @at-font-size-3x;
|
||||
@at-font-size-menu-icon: @at-font-size-5x;
|
||||
|
||||
@at-font-weight-body: @at-font-weight;
|
||||
@at-font-weight-heading: @at-font-weight-2x;
|
||||
|
||||
// 3. Layout --------------------------------------------------------------------------------------
|
||||
|
||||
@at-padding-button-horizontal: @at-space-2x;
|
||||
@at-padding-button-vertical: @at-space;
|
||||
@at-padding-inset: @at-space-3x;
|
||||
@at-padding-panel: @at-space-4x;
|
||||
@at-padding-popover: @at-space-2x;
|
||||
@at-padding-well: @at-space-2x;
|
||||
|
||||
@at-margin-input-message: @at-space;
|
||||
@at-margin-item-column: @at-space-3x;
|
||||
@at-margin-panel: @at-space-4x;
|
||||
@at-margin-panel-inset: @at-space-3x;
|
||||
@at-margin-popover: @at-space-2x;
|
||||
@at-margin-tag: @at-space-2x;
|
||||
@at-margin-form-label: @at-space;
|
||||
@at-margin-form-label-hint: @at-space-2x;
|
||||
|
||||
@at-margin-top-search-key: @at-space-2x;
|
||||
|
||||
@at-height-divider: @at-margin-panel;
|
||||
@at-height-input: 30px;
|
||||
@at-height-button: 30px;
|
||||
@at-height-tab: 30px;
|
||||
|
||||
// 4. Transitions ---------------------------------------------------------------------------------
|
||||
|
||||
@at-transition-icon-button: 0.2s;
|
||||
|
||||
// 5. Misc ----------------------------------------------------------------------------------------
|
||||
|
||||
@at-border-radius: 5px;
|
||||
@at-popover-maxwidth: 320px;
|
||||
@at-line-height-short: 0.9;
|
||||
@at-line-height-tall: 2;
|
||||
@at-line-height: 24px;
|
||||
@at-input-button-width: 72px;
|
||||
|
||||
45
awx/ui/client/lib/theme/_global.less
Normal file
45
awx/ui/client/lib/theme/_global.less
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* For styles that are used in more than one place throughout the application.
|
||||
*
|
||||
* 1. Buttons
|
||||
*
|
||||
*/
|
||||
|
||||
// 1. Buttons -------------------------------------------------------------------------------------
|
||||
|
||||
.at-Button--success {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-color-success', 'at-color-default');
|
||||
|
||||
&[disabled] {
|
||||
background: @at-color-disabled;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Button--info {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-color-info', 'at-color-default');
|
||||
}
|
||||
|
||||
.at-Button--error {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-color-error', 'at-color-default');
|
||||
}
|
||||
|
||||
.at-ButtonHollow--default {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonHollow(
|
||||
'at-color-default',
|
||||
'at-color-button-border-default',
|
||||
'at-color-button-text-default'
|
||||
);
|
||||
}
|
||||
|
||||
.at-ButtonIcon {
|
||||
padding: 4px @at-padding-button-horizontal;
|
||||
font-size: @at-font-size-body;
|
||||
}
|
||||
|
||||
.at-Button--expand {
|
||||
width: 100%;
|
||||
}
|
||||
@ -11,9 +11,9 @@
|
||||
}
|
||||
|
||||
.at-mixin-Heading (@size) {
|
||||
color: @at-gray-dark-4x;
|
||||
color: @at-color-body-text;
|
||||
font-size: @size;
|
||||
font-weight: @at-font-weight-2x;
|
||||
font-weight: @at-font-weight-heading;
|
||||
line-height: @at-line-height-short;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
@ -21,12 +21,13 @@
|
||||
}
|
||||
|
||||
.at-mixin-Button () {
|
||||
height: @at-input-height;
|
||||
padding: @at-space-2x @at-space-4x;
|
||||
font-size: @at-font-size;
|
||||
height: @at-height-input;
|
||||
padding: @at-padding-button-vertical @at-padding-button-horizontal;
|
||||
font-size: @at-font-size-body;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.at-mixin-ButtonColor (@background, @color, @hover: '@{background}--hover') {
|
||||
.at-mixin-ButtonColor (@background, @color, @hover: '@{background}-hover') {
|
||||
background-color: @@background;
|
||||
|
||||
&, &:hover, &:focus {
|
||||
@ -42,21 +43,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-mixin-ButtonHollow (@color, @accent) {
|
||||
background-color: @at-white;
|
||||
color: @@color;
|
||||
border-color: @@color;
|
||||
.at-mixin-ButtonHollow (@bg, @border, @text) {
|
||||
@hover: '@{bg}-hover';
|
||||
|
||||
background-color: @@bg;
|
||||
color: @@text;
|
||||
border-color: @@border;
|
||||
|
||||
&:hover, &:active {
|
||||
color: @@color;
|
||||
background-color: @at-white--hover;
|
||||
color: @@text;
|
||||
background-color: @@hover;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
color: @at-white;
|
||||
background-color: @@accent;
|
||||
border-color: @@accent;
|
||||
color: @@text;
|
||||
background-color: @@hover;
|
||||
border-color: @@border;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@ -67,14 +70,14 @@
|
||||
|
||||
.at-mixin-ButtonIcon () {
|
||||
line-height: @at-line-height-short;
|
||||
color: @at-gray-dark-2x;
|
||||
|
||||
& > i {
|
||||
cursor: pointer;
|
||||
transition: color @at-transition-icon-button;
|
||||
}
|
||||
|
||||
& > i:hover {
|
||||
color: @at-gray-dark-3x;
|
||||
color: @at-color-icon-hover
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* All variables used in the UI.
|
||||
*
|
||||
* 1. Colors
|
||||
* 2. Typography
|
||||
* 3. Layout
|
||||
* 4. Input
|
||||
* 5. Misc
|
||||
*/
|
||||
|
||||
// 1. Colors --------------------------------------------------------------------------------------
|
||||
@at-gray-light-5x: #fcfcfc;
|
||||
@at-gray-light-4x: #fafafa;
|
||||
@at-gray-light-3x: #f6f6f6;
|
||||
@at-gray-light-2x: #f2f2f2;
|
||||
@at-gray-light: #ebebeb;
|
||||
@at-gray: #e1e1e1;
|
||||
@at-gray-dark: #d7d7d7;
|
||||
@at-gray-dark-2x: #b7b7b7;
|
||||
@at-gray-dark-3x: #848992;
|
||||
@at-gray-dark-4x: #707070;
|
||||
@at-gray-dark-5x: #161b1f;
|
||||
|
||||
@at-white: #ffffff;
|
||||
@at-white--hover: #f2f2f2;
|
||||
|
||||
@at-blue: #337ab7;
|
||||
@at-blue--hover: #286090;
|
||||
|
||||
@at-green: #5cb85c;
|
||||
@at-green--hover: #449D44;
|
||||
|
||||
@at-yellow: #f0ad4e;
|
||||
@at-yellow--hover: #ec971f;
|
||||
|
||||
@at-red: #d9534f;
|
||||
@at-red--hover: #c9302c;
|
||||
|
||||
@at-redAlert: #ff0000;
|
||||
@at-redAlert--hover: #d81f1f;
|
||||
|
||||
// 2. Typography ----------------------------------------------------------------------------------
|
||||
@at-font-size: 12px;
|
||||
@at-font-size-2x: 13px;
|
||||
@at-font-size-3x: 14px;
|
||||
@at-font-size-4x: 16px;
|
||||
|
||||
@at-font-weight: 400;
|
||||
@at-font-weight-2x: 700;
|
||||
@at-font-weight-3x: 900;
|
||||
|
||||
@at-line-height-short: 0.9;
|
||||
@at-line-height-tall: 2;
|
||||
@at-line-height: 24px;
|
||||
|
||||
// 3. Layout --------------------------------------------------------------------------------------
|
||||
@at-space: 3px;
|
||||
@at-space-2x: 4px;
|
||||
@at-space-3x: 5px;
|
||||
@at-space-4x: 10px;
|
||||
@at-space-5x: 15px;
|
||||
@at-space-6x: 20px;
|
||||
|
||||
// 4. Input ---------------------------------------------------------------------------------------
|
||||
@at-input-button-width: 72px;
|
||||
@at-input-height: 30px;
|
||||
|
||||
// 5. Misc ----------------------------------------------------------------------------------------
|
||||
@at-border-radius: 5px;
|
||||
@at-popover-width: 320px;
|
||||
@at-inset-width: 5px;
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
// App-wide styles
|
||||
@import '_variables';
|
||||
@import '_base-variables';
|
||||
@import '_contextual-variables';
|
||||
@import '_mixins';
|
||||
@import '_utility';
|
||||
@import '_common';
|
||||
@import '_global';
|
||||
|
||||
// Aggregated component and feature specific styles
|
||||
@import '../components/_index';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user