mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-06 00:11:50 -05:00
Update project structure
This commit is contained in:
8
awx/ui/client/lib/components/_index.less
Normal file
8
awx/ui/client/lib/components/_index.less
Normal file
@@ -0,0 +1,8 @@
|
||||
@import 'action/_index';
|
||||
@import 'badge/_index';
|
||||
@import 'form/_index';
|
||||
@import 'input/_index';
|
||||
@import 'panel/_index';
|
||||
@import 'popover/_index';
|
||||
@import 'toggle/_index';
|
||||
|
||||
7
awx/ui/client/lib/components/action/_index.less
Normal file
7
awx/ui/client/lib/components/action/_index.less
Normal file
@@ -0,0 +1,7 @@
|
||||
.at-ActionGroup {
|
||||
margin-top: @at-space-6x;
|
||||
|
||||
button:last-child {
|
||||
margin-left: @at-space-5x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
function atActionGroup (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/action/action-group'),
|
||||
scope: {
|
||||
col: '@',
|
||||
pos: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atActionGroup.$inject = ['PathService'];
|
||||
|
||||
export default atActionGroup;
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="col-xs-{{ col }} at-ActionGroup">
|
||||
<div class="pull-{{ pos }}">
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
</div>
|
||||
49
awx/ui/client/lib/components/action/action.directive.js
Normal file
49
awx/ui/client/lib/components/action/action.directive.js
Normal file
@@ -0,0 +1,49 @@
|
||||
let $state;
|
||||
|
||||
function applyCancelProperties (scope) {
|
||||
scope.text = scope.config.text || 'CANCEL';
|
||||
scope.fill = 'Hollow';
|
||||
scope.color = 'white';
|
||||
scope.disabled = false;
|
||||
scope.action = () => $state.go('^');
|
||||
}
|
||||
|
||||
function applySaveProperties (scope) {
|
||||
scope.text = 'SAVE';
|
||||
scope.fill = '';
|
||||
scope.color = 'green';
|
||||
scope.disabled = true;
|
||||
}
|
||||
|
||||
function link (scope, el, attrs, form) {
|
||||
form.use('action', scope, el);
|
||||
|
||||
switch(scope.config.type) {
|
||||
case 'cancel':
|
||||
applyCancelProperties(scope);
|
||||
break;
|
||||
case 'save':
|
||||
applySaveProperties(scope);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function atFormAction (_$state_, pathService) {
|
||||
$state = _$state_;
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: '^^at-form',
|
||||
templateUrl: pathService.getPartialPath('components/action/action'),
|
||||
link,
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atFormAction.$inject = ['$state', 'PathService'];
|
||||
|
||||
export default atFormAction;
|
||||
4
awx/ui/client/lib/components/action/action.partial.html
Normal file
4
awx/ui/client/lib/components/action/action.partial.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<button class="btn at-Button{{ fill }}--{{ color }}" ng-disabled="disabled"
|
||||
ng-class="{ 'at-Button--disabled': disabled }" ng-click="action()">
|
||||
{{ text }}
|
||||
</button>
|
||||
8
awx/ui/client/lib/components/badge/_index.less
Normal file
8
awx/ui/client/lib/components/badge/_index.less
Normal file
@@ -0,0 +1,8 @@
|
||||
.at-Badge {
|
||||
font-size: @at-font-size;
|
||||
padding: 0 @at-space-2x;
|
||||
margin: 0;
|
||||
background-color: @at-gray;
|
||||
color: @at-white;
|
||||
border-radius: @at-border-radius;
|
||||
}
|
||||
12
awx/ui/client/lib/components/badge/badge.directive.js
Normal file
12
awx/ui/client/lib/components/badge/badge.directive.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function atBadge () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: 'static/partials/components/badge/badge.partial.html',
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default atBadge;
|
||||
8
awx/ui/client/lib/components/badge/badge.partial.html
Normal file
8
awx/ui/client/lib/components/badge/badge.partial.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="at-Badge">
|
||||
<div ng-if="config.text">
|
||||
{{ config.text }}
|
||||
</div>
|
||||
|
||||
<ng-if="!config" ng-transclude></ng-transclude>
|
||||
</div>
|
||||
|
||||
1
awx/ui/client/lib/components/form/_index.less
Normal file
1
awx/ui/client/lib/components/form/_index.less
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
90
awx/ui/client/lib/components/form/form.directive.js
Normal file
90
awx/ui/client/lib/components/form/form.directive.js
Normal file
@@ -0,0 +1,90 @@
|
||||
function use (type, componentScope, componentElement) {
|
||||
let vm = this;
|
||||
|
||||
let component;
|
||||
|
||||
switch (type) {
|
||||
case 'input':
|
||||
component = vm.trackInput(componentElement);
|
||||
break;
|
||||
case 'action':
|
||||
component = vm.trackAction(componentElement);
|
||||
break;
|
||||
default:
|
||||
throw new Error('An at-form cannot use component type:', type);
|
||||
}
|
||||
|
||||
componentScope.meta = component;
|
||||
}
|
||||
|
||||
function trackInput (componentElement) {
|
||||
let vm = this;
|
||||
|
||||
let input = {
|
||||
el: componentElement,
|
||||
tabindex: vm.inputs.length + 1
|
||||
};
|
||||
|
||||
if (vm.inputs.length === 0) {
|
||||
input.autofocus = true;
|
||||
componentElement.find('input').focus();
|
||||
}
|
||||
|
||||
vm.inputs.push(input)
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function trackAction (componentElement) {
|
||||
let vm = this;
|
||||
|
||||
let action = {
|
||||
el: componentElement
|
||||
};
|
||||
|
||||
vm.actions.push(action);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
function update () {
|
||||
let vm = this;
|
||||
|
||||
vm.inputs.forEach(input => console.log(input));
|
||||
}
|
||||
|
||||
function remove (id) {
|
||||
let vm = this;
|
||||
|
||||
delete inputs[id];
|
||||
}
|
||||
|
||||
function AtFormController () {
|
||||
let vm = this;
|
||||
|
||||
vm.inputs = [];
|
||||
vm.actions = [];
|
||||
|
||||
vm.use = use;
|
||||
vm.trackInput = trackInput;
|
||||
vm.trackAction = trackAction;
|
||||
vm.update = update;
|
||||
vm.remove = remove;
|
||||
}
|
||||
|
||||
function atForm (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/form/form'),
|
||||
controller: AtFormController,
|
||||
controllerAs: 'vm',
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atForm.$inject = ['PathService'];
|
||||
|
||||
export default atForm;
|
||||
5
awx/ui/client/lib/components/form/form.partial.html
Normal file
5
awx/ui/client/lib/components/form/form.partial.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<form>
|
||||
<div class="row">
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
</form>
|
||||
33
awx/ui/client/lib/components/index.js
Normal file
33
awx/ui/client/lib/components/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import action from './action/action.directive';
|
||||
import actionGroup from './action/action-group.directive';
|
||||
import badge from './badge/badge.directive';
|
||||
import form from './form/form.directive';
|
||||
import inputLabel from './input/label.directive';
|
||||
import inputSearch from './input/search.directive';
|
||||
import inputSelect from './input/select.directive';
|
||||
import inputText from './input/text.directive';
|
||||
import panel from './panel/panel.directive';
|
||||
import panelHeading from './panel/heading.directive';
|
||||
import panelBody from './panel/body.directive';
|
||||
import popover from './popover/popover.directive';
|
||||
import toggleButton from './toggle/button.directive';
|
||||
import toggleContent from './toggle/content.directive';
|
||||
|
||||
angular
|
||||
.module('at.lib.components', [])
|
||||
.directive('atAction', action)
|
||||
.directive('atActionGroup', actionGroup)
|
||||
.directive('atBadge', badge)
|
||||
.directive('atForm', form)
|
||||
.directive('atInputLabel', inputLabel)
|
||||
.directive('atInputSearch', inputSearch)
|
||||
.directive('atInputSelect', inputSelect)
|
||||
.directive('atInputText', inputText)
|
||||
.directive('atPanel', panel)
|
||||
.directive('atPanelHeading', panelHeading)
|
||||
.directive('atPanelBody', panelBody)
|
||||
.directive('atPopover', popover)
|
||||
.directive('atToggleButton', toggleButton)
|
||||
.directive('atToggleContent', toggleContent);
|
||||
|
||||
|
||||
65
awx/ui/client/lib/components/input/_index.less
Normal file
65
awx/ui/client/lib/components/input/_index.less
Normal file
@@ -0,0 +1,65 @@
|
||||
.at-Input {
|
||||
.at-mixin-Placeholder(@at-gray-dark-3x);
|
||||
|
||||
background: @at-white;
|
||||
border-radius: @at-border-radius;
|
||||
color: @at-gray-dark-5x;
|
||||
|
||||
&, &:active {
|
||||
border-color: @at-gray-dark-2x;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: @at-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Input--focus {
|
||||
border-color: @at-blue;
|
||||
}
|
||||
|
||||
.at-InputLabel {
|
||||
color: @at-gray-dark-4x;
|
||||
font-size: @at-font-size-2x;
|
||||
font-weight: @at-font-weight;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.at-InputLabel-required {
|
||||
color: @at-red;
|
||||
font-weight: @at-font-weight-2x;
|
||||
font-size: @at-font-size-4x;
|
||||
line-height: @at-line-height-short;
|
||||
margin: @at-space @at-space 0 0;
|
||||
}
|
||||
|
||||
.at-InputGroup {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
& > i {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
right: @at-space-4x;
|
||||
top: @at-space-4x;
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputSelect {
|
||||
height: @at-input-height;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.at-InputSelect-input {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.at-InputSelect-select {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
}
|
||||
15
awx/ui/client/lib/components/input/label.directive.js
Normal file
15
awx/ui/client/lib/components/input/label.directive.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function atInputLabel (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/input/label'),
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputLabel.$inject = ['PathService'];
|
||||
|
||||
export default atInputLabel;
|
||||
5
awx/ui/client/lib/components/input/label.partial.html
Normal file
5
awx/ui/client/lib/components/input/label.partial.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<label class="at-InputLabel at-u-flat">
|
||||
<span ng-if="config.required" class="pull-left at-InputLabel-required">*</span>
|
||||
<span class="pull-left">{{ config.text }}</span>
|
||||
<at-popover class="pull-left" config="config.popover"></at-popover>
|
||||
</label>
|
||||
22
awx/ui/client/lib/components/input/search.directive.js
Normal file
22
awx/ui/client/lib/components/input/search.directive.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// TODO: i18n
|
||||
|
||||
function atInputSearch (pathService) {
|
||||
function link (scope) {
|
||||
scope.config = scope.config || {};
|
||||
scope.config.placeholder = scope.config.placeholder || 'SEARCH';
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/input/search'),
|
||||
link,
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputSearch.$inject = ['PathService'];
|
||||
|
||||
export default atInputSearch;
|
||||
10
awx/ui/client/lib/components/input/search.partial.html
Normal file
10
awx/ui/client/lib/components/input/search.partial.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="input-group at-InputSearch">
|
||||
<input type="text"
|
||||
class="form-control at-InputSearch-field"
|
||||
placeholder="{{ config.placeholder }}" />
|
||||
<div class="input-group-btn">
|
||||
<button class="btn at-Button--default at-Button--icon" type="button">
|
||||
<span class="fa fa-search"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
55
awx/ui/client/lib/components/input/select.directive.js
Normal file
55
awx/ui/client/lib/components/input/select.directive.js
Normal file
@@ -0,0 +1,55 @@
|
||||
let eventService;
|
||||
let pathService;
|
||||
|
||||
function link (scope, el, attrs, form) {
|
||||
form.use('input', scope, el); // avoid passing scope? assign to scope.meta instead or reference form properties in view
|
||||
|
||||
let input = el.find('input')[0];
|
||||
let select = el.find('select')[0];
|
||||
|
||||
let listeners = eventService.addListeners(scope, [
|
||||
[input, 'focus', () => select.focus()],
|
||||
[select, 'mousedown', () => scope.open = !scope.open],
|
||||
[select, 'focus', () => input.classList.add('at-Input--focus')],
|
||||
[select, 'change', () => scope.open = false],
|
||||
[select, 'blur', () => {
|
||||
input.classList.remove('at-Input--focus');
|
||||
scope.open = scope.open && false;
|
||||
}]
|
||||
]);
|
||||
|
||||
scope.$on('$destroy', () => eventService.remove(listeners));
|
||||
|
||||
/*
|
||||
* Should notify form on:
|
||||
* - valid (required, passes validation) state change
|
||||
*
|
||||
* Should get from form:
|
||||
* - display as disabled
|
||||
*/
|
||||
}
|
||||
|
||||
function atInputSelect (_eventService_, _pathService_) {
|
||||
eventService = _eventService_;
|
||||
pathService = _pathService_;
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: '^^at-form',
|
||||
templateUrl: pathService.getPartialPath('components/input/select'),
|
||||
link,
|
||||
scope: {
|
||||
config: '=',
|
||||
col: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputSelect.$inject = [
|
||||
'EventService',
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default atInputSelect;
|
||||
20
awx/ui/client/lib/components/input/select.partial.html
Normal file
20
awx/ui/client/lib/components/input/select.partial.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<div class="col-sm-{{ col }}">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label config="config.label"></at-input-label>
|
||||
<div class="at-InputGroup at-InputSelect">
|
||||
<input type="text" class="form-control at-Input at-InputSelect-input"
|
||||
ng-attr-autofocus="{{ meta.autofocus || undefined }}"
|
||||
placeholder="{{ config.placeholder | uppercase }}" ng-model="config.input" />
|
||||
|
||||
<select class="form-control at-InputSelect-select" ng-model="config.input"
|
||||
tabindex="{{ meta.tabindex }}">
|
||||
<optgroup ng-repeat="group in config.data" label="{{ group.category | uppercase }}">
|
||||
<option ng-repeat="item in group.data" value="{{ item.name }}">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<i class="fa" ng-class="{ 'fa-caret-down': !open, 'fa-caret-up': open }"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
22
awx/ui/client/lib/components/input/text.directive.js
Normal file
22
awx/ui/client/lib/components/input/text.directive.js
Normal file
@@ -0,0 +1,22 @@
|
||||
function link (scope, el, attrs, form) {
|
||||
form.use('input', scope, el);
|
||||
}
|
||||
|
||||
function atInputText (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: '^^at-form',
|
||||
templateUrl: pathService.getPartialPath('components/input/text'),
|
||||
link,
|
||||
scope: {
|
||||
config: '=',
|
||||
col: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputText.$inject = ['PathService'];
|
||||
|
||||
export default atInputText;
|
||||
8
awx/ui/client/lib/components/input/text.partial.html
Normal file
8
awx/ui/client/lib/components/input/text.partial.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="col-sm-{{ col }}">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label config="config.label"></at-input-label>
|
||||
<input type="text" class="form-control at-Input" ng-model="config.input"
|
||||
ng-attr-autofocus="{{ meta.autofocus || undefined }}" tabindex="{{ meta.tabindex }}"
|
||||
placeholder="{{ config.placeholder }}" />
|
||||
</div>
|
||||
</div>
|
||||
0
awx/ui/client/lib/components/list/list.directive.js
Normal file
0
awx/ui/client/lib/components/list/list.directive.js
Normal file
30
awx/ui/client/lib/components/panel/_index.less
Normal file
30
awx/ui/client/lib/components/panel/_index.less
Normal file
@@ -0,0 +1,30 @@
|
||||
.at-Panel {
|
||||
margin: @at-space-6x 0 0 0;
|
||||
padding: @at-space-6x;
|
||||
border-color: @at-gray-dark;
|
||||
}
|
||||
|
||||
.at-Panel-heading {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.at-Panel-dismiss {
|
||||
.at-mixin-ButtonIcon();
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.at-Panel-body {
|
||||
margin: @at-space-6x 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.at-Panel-headingTitle {
|
||||
color: @at-gray-dark-4x;
|
||||
font-size: @at-font-size-3x;
|
||||
font-weight: @at-font-weight-2x;
|
||||
line-height: @at-line-height-short;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
12
awx/ui/client/lib/components/panel/body.directive.js
Normal file
12
awx/ui/client/lib/components/panel/body.directive.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function atPanelBody (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: '^^atPanel',
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/body'),
|
||||
};
|
||||
}
|
||||
|
||||
atPanelBody.$inject = ['PathService'];
|
||||
|
||||
export default atPanelBody;
|
||||
3
awx/ui/client/lib/components/panel/body.partial.html
Normal file
3
awx/ui/client/lib/components/panel/body.partial.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div class="panel-body at-Panel-body">
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
20
awx/ui/client/lib/components/panel/heading.directive.js
Normal file
20
awx/ui/client/lib/components/panel/heading.directive.js
Normal file
@@ -0,0 +1,20 @@
|
||||
function link (scope, el, attrs, panel) {
|
||||
panel.use(scope);
|
||||
}
|
||||
|
||||
function atPanelHeading (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: '^^atPanel',
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/heading'),
|
||||
link,
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atPanelHeading.$inject = ['PathService'];
|
||||
|
||||
export default atPanelHeading;
|
||||
12
awx/ui/client/lib/components/panel/heading.partial.html
Normal file
12
awx/ui/client/lib/components/panel/heading.partial.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-10">
|
||||
<h3 class="at-Panel-headingTitle">
|
||||
{{ config.text }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<div class="at-Panel-dismiss">
|
||||
<i class="fa fa-times fa-lg" ng-click="dismiss()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
33
awx/ui/client/lib/components/panel/panel.directive.js
Normal file
33
awx/ui/client/lib/components/panel/panel.directive.js
Normal file
@@ -0,0 +1,33 @@
|
||||
function use (scope) {
|
||||
scope.dismiss = this.dismiss;
|
||||
}
|
||||
|
||||
function dismiss ($state) {
|
||||
$state.go('^');
|
||||
}
|
||||
|
||||
function controller ($state) {
|
||||
let vm = this;
|
||||
|
||||
vm.dismiss = dismiss.bind(vm, $state);
|
||||
vm.use = use;
|
||||
}
|
||||
|
||||
controller.$inject = ['$state'];
|
||||
|
||||
function atPanel (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/panel'),
|
||||
controller,
|
||||
controllerAs: 'vm',
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atPanel.$inject = ['PathService'];
|
||||
|
||||
export default atPanel;
|
||||
3
awx/ui/client/lib/components/panel/panel.partial.html
Normal file
3
awx/ui/client/lib/components/panel/panel.partial.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div class="panel panel-default at-Panel">
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
30
awx/ui/client/lib/components/popover/_index.less
Normal file
30
awx/ui/client/lib/components/popover/_index.less
Normal file
@@ -0,0 +1,30 @@
|
||||
.at-Popover-icon {
|
||||
.at-mixin-ButtonIcon();
|
||||
font-size: @at-font-size-3x;
|
||||
padding: 0 0 0 @at-space-2x;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.at-Popover-container {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
color: @at-white;
|
||||
background-color: @at-gray-dark-4x;
|
||||
max-width: @at-popover-width;
|
||||
padding: @at-space-4x;
|
||||
height: auto;
|
||||
position: fixed;
|
||||
z-index: 2000;
|
||||
margin: 0 0 0 @at-space-6x;
|
||||
border-radius: @at-border-radius;
|
||||
box-shadow: 0 5px 10px rgba(0,0,0, 0.2);
|
||||
transition: opacity .15s linear;
|
||||
}
|
||||
|
||||
.at-Popover-arrow {
|
||||
color: @at-gray-dark-4x;
|
||||
position: fixed;
|
||||
z-index: 1999;
|
||||
padding: 0;
|
||||
margin: -@at-space 0 0 0;
|
||||
}
|
||||
72
awx/ui/client/lib/components/popover/popover.directive.js
Normal file
72
awx/ui/client/lib/components/popover/popover.directive.js
Normal file
@@ -0,0 +1,72 @@
|
||||
let pathService;
|
||||
|
||||
function link (scope, el, attr) {
|
||||
let icon = el[0];
|
||||
let popover = icon.getElementsByClassName('at-Popover-container')[0];
|
||||
|
||||
el.on('click', createDisplayListener(icon, popover));
|
||||
}
|
||||
|
||||
function createDisplayListener (icon, popover) {
|
||||
return event => {
|
||||
let arrow = popover.getElementsByClassName('at-Popover-arrow')[0];
|
||||
|
||||
let iPos = icon.getBoundingClientRect();
|
||||
let pPos = popover.getBoundingClientRect();
|
||||
|
||||
let wHeight = window.clientHeight;
|
||||
let pHeight = pPos.height;
|
||||
|
||||
let cx = Math.floor(iPos.left + (iPos.width / 2));
|
||||
let cy = Math.floor(iPos.top + (iPos.height / 2));
|
||||
|
||||
if (cy < (pHeight / 2)) {
|
||||
popover.style.top = '10px';
|
||||
} else {
|
||||
popover.style.top = (cy - pHeight / 2) + 'px';
|
||||
}
|
||||
|
||||
popover.style.left = cx + 'px';
|
||||
|
||||
arrow.style.top = iPos.top + 'px';
|
||||
arrow.style.left = iPos.left + 20 + 'px';
|
||||
|
||||
popover.style.visibility = 'visible';
|
||||
popover.style.opacity = 1;
|
||||
|
||||
let dismissListener = createDismissListener(popover);
|
||||
|
||||
window.addEventListener('mousedown', dismissListener);
|
||||
window.addEventListener('resize', dismissListener);
|
||||
};
|
||||
}
|
||||
|
||||
function createDismissListener (popover) {
|
||||
return function dismissListener () {
|
||||
popover.style.visibility = 'hidden';
|
||||
popover.style.opacity = 0;
|
||||
|
||||
window.removeEventListener('mousedown', dismissListener);
|
||||
};
|
||||
}
|
||||
|
||||
function atPopover (_pathService_) {
|
||||
pathService = _pathService_;
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/popover/popover'),
|
||||
link,
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atPopover.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default atPopover;
|
||||
11
awx/ui/client/lib/components/popover/popover.partial.html
Normal file
11
awx/ui/client/lib/components/popover/popover.partial.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div ng-show="config" class="at-Popover">
|
||||
<span class="at-Popover-icon">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</span>
|
||||
<div class="at-Popover-container">
|
||||
<div class="at-Popover-arrow">
|
||||
<i class="fa fa-caret-left fa-2x"></i>
|
||||
</div>
|
||||
<div class="at-Popover-content">{{ config.text }}</div>
|
||||
</div>
|
||||
</div>
|
||||
0
awx/ui/client/lib/components/tabs/tab.directive.js
Normal file
0
awx/ui/client/lib/components/tabs/tab.directive.js
Normal file
32
awx/ui/client/lib/components/toggle/_index.less
Normal file
32
awx/ui/client/lib/components/toggle/_index.less
Normal file
@@ -0,0 +1,32 @@
|
||||
.at-ToggleButton {
|
||||
&, &:focus {
|
||||
border-color: @at-gray-light;
|
||||
background-color: @at-white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @at-gray-light-2x;
|
||||
}
|
||||
|
||||
& > span:hover {
|
||||
border-color: @at-gray-light;
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.at-ToggleButton--show {
|
||||
&, &:hover, &:focus {
|
||||
background-color: @at-blue;
|
||||
border-color: @at-blue;
|
||||
color: @at-white;
|
||||
}
|
||||
}
|
||||
|
||||
.at-ToggleContent-well {
|
||||
margin: @at-space-2x 0 0 0;
|
||||
padding: @at-space-3x;
|
||||
border-radius: @at-border-radius;
|
||||
border: 1px solid transparent;
|
||||
background-color: @at-gray-light-2x;
|
||||
color: @at-gray-dark-2x;
|
||||
}
|
||||
12
awx/ui/client/lib/components/toggle/button.directive.js
Normal file
12
awx/ui/client/lib/components/toggle/button.directive.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function atToggleButton () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: 'static/partials/components/toggle/button.partial.html',
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default atToggleButton;
|
||||
9
awx/ui/client/lib/components/toggle/button.partial.html
Normal file
9
awx/ui/client/lib/components/toggle/button.partial.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<button class="btn btn-default at-Button at-ToggleButton"
|
||||
ng-class="{ 'at-ToggleButton--show': config.show }"
|
||||
ng-click="config.show = !config.show">
|
||||
<span ng-if="config.button">
|
||||
{{ config.button.text }}
|
||||
</span>
|
||||
|
||||
<ng-transclude ng-if="!config.button"></ng-transclude>
|
||||
</button>
|
||||
12
awx/ui/client/lib/components/toggle/content.directive.js
Normal file
12
awx/ui/client/lib/components/toggle/content.directive.js
Normal file
@@ -0,0 +1,12 @@
|
||||
function atToggleContent () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: 'static/partials/component/toggle/content.partial.html',
|
||||
scope: {
|
||||
config: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default atToggleContent;
|
||||
10
awx/ui/client/lib/components/toggle/content.partial.html
Normal file
10
awx/ui/client/lib/components/toggle/content.partial.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div ng-show="config.show" class="row">
|
||||
<div ng-if="config.content" class="col-sm-12">
|
||||
<div class="well at-ToggleContent-well">
|
||||
{{ config.content.text }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-transclude ng-if="!config.content"></ng-transclude>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
function listenWith (scope) {
|
||||
return fn => apply(scope, fn);
|
||||
}
|
||||
|
||||
function apply (scope, fn) {
|
||||
return () => scope.$apply(fn);
|
||||
}
|
||||
|
||||
function EventService () {
|
||||
return {
|
||||
listenWith,
|
||||
apply
|
||||
};
|
||||
}
|
||||
|
||||
export default EventService;
|
||||
30
awx/ui/client/lib/models/Base.js
Normal file
30
awx/ui/client/lib/models/Base.js
Normal file
@@ -0,0 +1,30 @@
|
||||
function get () {
|
||||
return this.model.get().$promise
|
||||
.then(response => {
|
||||
this.response = response;
|
||||
this.data = this.response.results;
|
||||
});
|
||||
}
|
||||
|
||||
function normalizePath (resource) {
|
||||
let version = '/api/v2/';
|
||||
|
||||
return `${version}${resource}/`;
|
||||
}
|
||||
|
||||
function Base ($resource) {
|
||||
return (resource, params, actions) => {
|
||||
let path = normalizePath(resource);
|
||||
|
||||
return {
|
||||
data: null,
|
||||
response: null,
|
||||
model: $resource(path, params, actions),
|
||||
get
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Base.$inject = ['$resource'];
|
||||
|
||||
export default Base;
|
||||
0
awx/ui/client/lib/models/Credential.js
Normal file
0
awx/ui/client/lib/models/Credential.js
Normal file
25
awx/ui/client/lib/models/CredentialType.js
Normal file
25
awx/ui/client/lib/models/CredentialType.js
Normal file
@@ -0,0 +1,25 @@
|
||||
function categorizeByKind () {
|
||||
let group = {};
|
||||
|
||||
this.data.forEach(result => {
|
||||
group[result.kind] = group[result.kind] || [];
|
||||
group[result.kind].push(result);
|
||||
});
|
||||
|
||||
return Object.keys(group).map(category => ({
|
||||
data: group[category],
|
||||
category
|
||||
}));
|
||||
}
|
||||
|
||||
function CredentialType (Base) {
|
||||
let base = Base('credential_types');
|
||||
|
||||
return Object.assign(base, {
|
||||
categorizeByKind
|
||||
});
|
||||
}
|
||||
|
||||
CredentialType.$inject = ['Base'];
|
||||
|
||||
export default CredentialType;
|
||||
15
awx/ui/client/lib/models/index.js
Normal file
15
awx/ui/client/lib/models/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Base from './Base';
|
||||
import CredentialType from './CredentialType';
|
||||
|
||||
function config ($resourceProvider) {
|
||||
$resourceProvider.defaults.stripTrailingSlashes = false;
|
||||
}
|
||||
|
||||
config.$inject = ['$resourceProvider'];
|
||||
|
||||
angular
|
||||
.module('at.lib.models', [])
|
||||
.config(config)
|
||||
.factory('Base', Base)
|
||||
.factory('CredentialType', CredentialType);
|
||||
|
||||
38
awx/ui/client/lib/services/event.service.js
Normal file
38
awx/ui/client/lib/services/event.service.js
Normal file
@@ -0,0 +1,38 @@
|
||||
function addListeners (scope, list) {
|
||||
let listeners = [];
|
||||
|
||||
list.forEach(args => {
|
||||
listeners.push(addListener.call(null, scope, ...args));
|
||||
});
|
||||
|
||||
return listeners;
|
||||
}
|
||||
|
||||
function addListener (scope, el, name, fn, type) {
|
||||
type = type || '$apply';
|
||||
|
||||
let listener = {
|
||||
fn: () => scope[type](fn),
|
||||
name,
|
||||
el
|
||||
};
|
||||
|
||||
listener.el.addEventListener(listener.name, listener.fn);
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
function remove (listeners) {
|
||||
listeners.forEach(listener => {
|
||||
listener.el.removeEventListener(listener.name, listener.fn);
|
||||
});
|
||||
}
|
||||
|
||||
function EventService () {
|
||||
return {
|
||||
addListeners,
|
||||
remove
|
||||
};
|
||||
}
|
||||
|
||||
export default EventService;
|
||||
@@ -2,6 +2,6 @@ import EventService from './event.service';
|
||||
import PathService from './path.service';
|
||||
|
||||
angular
|
||||
.module('at.lib', [])
|
||||
.module('at.lib.services', [])
|
||||
.factory('EventService', EventService)
|
||||
.factory('PathService', PathService);
|
||||
40
awx/ui/client/lib/theme/_common.less
Normal file
40
awx/ui/client/lib/theme/_common.less
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
|
||||
.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-4x', 'at-gray-dark-2x');
|
||||
|
||||
border-color: @at-gray-dark-2x;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: @at-gray-dark-4x;
|
||||
background-color: @at-white--hover;
|
||||
}
|
||||
}
|
||||
|
||||
.at-ButtonIcon {
|
||||
padding: @at-space-2x @at-space-4x;
|
||||
font-size: @at-font-size-3x;
|
||||
}
|
||||
63
awx/ui/client/lib/theme/_mixins.less
Normal file
63
awx/ui/client/lib/theme/_mixins.less
Normal file
@@ -0,0 +1,63 @@
|
||||
.at-mixin-Placeholder (@color) {
|
||||
&:-moz-placeholder {
|
||||
color: @color;
|
||||
}
|
||||
&:-ms-input-placeholder {
|
||||
color: @color;
|
||||
}
|
||||
&::-webkit-input-placeholder {
|
||||
color: @color;
|
||||
}
|
||||
}
|
||||
|
||||
.at-mixin-Button () {
|
||||
padding: @at-space-2x @at-space-4x;
|
||||
}
|
||||
|
||||
.at-mixin-ButtonColor (@background, @color, @hover: '@{background}--hover') {
|
||||
background-color: @@background;
|
||||
|
||||
&, &:hover, &:focus {
|
||||
color: @@color;
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: @@hover;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background-color: fade(@@background, 60%);
|
||||
}
|
||||
}
|
||||
|
||||
.at-mixin-ButtonHollow (@color, @hover: '@{color}--hover') {
|
||||
background-color: @at-white;
|
||||
|
||||
color: @@color;
|
||||
border-color: @@color;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: @@hover;
|
||||
border-color: @@hover;
|
||||
background-color: @at-white;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background-color: fade(@@color, 30%);
|
||||
border-color: fade(@@color, 30%);
|
||||
color: @at-white;
|
||||
}
|
||||
}
|
||||
|
||||
.at-mixin-ButtonIcon () {
|
||||
line-height: @at-line-height-short;
|
||||
color: @at-gray-dark-2x;
|
||||
|
||||
& > i {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
& > i:hover {
|
||||
color: @at-gray-dark-3x;
|
||||
}
|
||||
}
|
||||
5
awx/ui/client/lib/theme/_temporary-overrides.less
Normal file
5
awx/ui/client/lib/theme/_temporary-overrides.less
Normal file
@@ -0,0 +1,5 @@
|
||||
// TODO (remove override on cleanup):
|
||||
|
||||
.at-Panel-heading:hover {
|
||||
cursor: default;
|
||||
}
|
||||
13
awx/ui/client/lib/theme/_utility.less
Normal file
13
awx/ui/client/lib/theme/_utility.less
Normal file
@@ -0,0 +1,13 @@
|
||||
.at-u-flat {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.at-u-thin {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
65
awx/ui/client/lib/theme/_variables.less
Normal file
65
awx/ui/client/lib/theme/_variables.less
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* All variables used in the UI.
|
||||
*
|
||||
* 1. Colors
|
||||
* 2. Typography
|
||||
* 3. Layout
|
||||
* 4. 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: #8f8992;
|
||||
@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: 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. Misc --------------------------------------------------------------------------------------
|
||||
@at-border-radius: 5px;
|
||||
@at-input-height: 34px;
|
||||
@at-popover-width: 320px;
|
||||
15
awx/ui/client/lib/theme/index.less
Normal file
15
awx/ui/client/lib/theme/index.less
Normal file
@@ -0,0 +1,15 @@
|
||||
// App-wide styles
|
||||
@import '_variables';
|
||||
@import '_mixins';
|
||||
@import '_utility';
|
||||
@import '_common';
|
||||
|
||||
// Aggregated component and feature specific styles
|
||||
@import '../components/_index';
|
||||
@import '../../features/_index';
|
||||
|
||||
/*
|
||||
* Temporary overrides used only during the transition away from old style
|
||||
* structure to new style structure. Overrides unwanted/uneeded rules.
|
||||
*/
|
||||
@import '_temporary-overrides';
|
||||
Reference in New Issue
Block a user