Refine recently added components

This commit is contained in:
gconsidine
2017-05-04 16:58:01 -04:00
parent 2509c573a5
commit f741470365
25 changed files with 211 additions and 165 deletions

View File

@@ -1,32 +1,42 @@
function track (element) { function use (componentScope, componentElement) {
let vm = this; let vm = this;
let input = { let input = vm.track(componentElement);
el: element,
tabindex: vm.form.inputs.length + 1,
autofocus: vm.form.inputs.length === 0
};
vm.form.inputs.push(input); componentScope.meta = input;
}
return input; function track (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 controller () { function controller () {
let vm = this; let vm = this;
vm.form = { vm.inputs = [];
inputs: [] vm.use = use;
};
vm.track = track; vm.track = track;
} }
function atForm () { function atForm (pathService) {
return { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/form/form.partial.html', templateUrl: pathService.getPartialPath('components/form/form'),
controller, controller,
controllerAs: 'vm', controllerAs: 'vm',
scope: { scope: {
@@ -35,4 +45,6 @@ function atForm () {
}; };
} }
atForm.$inject = ['PathService'];
export default atForm; export default atForm;

View File

@@ -1,6 +1,5 @@
import badge from './badge/badge.directive'; import badge from './badge/badge.directive';
import form from './form/form.directive'; import form from './form/form.directive';
import inputDropdown from './input/dropdown.directive';
import inputSearch from './input/search.directive'; import inputSearch from './input/search.directive';
import inputSelect from './input/select.directive'; import inputSelect from './input/select.directive';
import inputText from './input/text.directive'; import inputText from './input/text.directive';
@@ -14,7 +13,6 @@ angular
.module('at.components', []) .module('at.components', [])
.directive('atBadge', badge) .directive('atBadge', badge)
.directive('atForm', form) .directive('atForm', form)
.directive('atInputDropdown', inputDropdown)
.directive('atInputSearch', inputSearch) .directive('atInputSearch', inputSearch)
.directive('atInputSelect', inputSelect) .directive('atInputSelect', inputSelect)
.directive('atInputText', inputText) .directive('atInputText', inputText)

View File

@@ -42,25 +42,25 @@
& > i { & > i {
position: absolute; position: absolute;
z-index: 4; z-index: 3;
pointer-events: none; pointer-events: none;
right: @at-padding-sm; right: @at-padding-sm;
top: @at-padding-sm; top: @at-padding-sm;
} }
} }
.at-Dropdown { .at-Select {
height: @at-input-height-md; height: @at-input-height-md;
position: relative; position: relative;
} }
.at-Dropdown-input { .at-Select-input {
position: relative; position: relative;
z-index: 2; z-index: 2;
pointer-events: none; pointer-events: none;
} }
.at-Dropdown-select { .at-Select-select {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
top: 0; top: 0;

View File

@@ -1,41 +0,0 @@
function link (scope, el, attrs, form) {
scope.form = form.track(el);
scope.open = false;
let input = el.find('input')[0];
let select = el.find('select')[0];
input.addEventListener('focus', () => select.focus());
select.addEventListener('focus', () => input.classList.add('at-Input--focus'));
select.addEventListener('mousedown', () => {
scope.open = true;
});
select.addEventListener('blur', () => {
input.classList.remove('at-Input--focus');
scope.open = false;
});
select.addEventListener('change', () => {
scope.open = false;
});
}
function atInputDropdown () {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^^at-form',
templateUrl: 'static/partials/components/input/dropdown.partial.html',
link,
scope: {
config: '=',
col: '@'
}
};
}
export default atInputDropdown;

View File

@@ -1,24 +0,0 @@
<div class="col-sm-{{ col }}">
<div class="form-group">
<label class="at-Input-label">
<span ng-if="config.required" class="at-Input-label--required">*</span>
<span>{{ config.label }}</span>
</label>
<div class="at-InputGroup at-Dropdown">
<input type="text" class="form-control at-Input at-Dropdown-input"
ng-attr-autofocus="{{ form.autofocus || undefined }}"
placeholder="{{ config.placeholder | uppercase }}" ng-model="config.input" />
<select class="form-control at-Dropdown-select" ng-model="config.input"
tabindex="{{ form.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 ng-hide="open" class="fa fa-caret-down"></i>
<i ng-show="open" class="fa fa-caret-up"></i>
</div>
</div>
</div>

View File

@@ -1,6 +1,6 @@
// TODO: i18n // TODO: i18n
function atInputSearch () { function atInputSearch (pathService) {
function link (scope) { function link (scope) {
scope.config = scope.config || {}; scope.config = scope.config || {};
scope.config.placeholder = scope.config.placeholder || 'SEARCH'; scope.config.placeholder = scope.config.placeholder || 'SEARCH';
@@ -9,7 +9,7 @@ function atInputSearch () {
return { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/input/search.partial.html', templateUrl: pathService.getPartialPath('components/input/search'),
link, link,
scope: { scope: {
config: '=' config: '='
@@ -17,4 +17,6 @@ function atInputSearch () {
}; };
} }
atInputSearch.$inject = ['PathService'];
export default atInputSearch; export default atInputSearch;

View File

@@ -1,18 +1,34 @@
// TODO: i18n function link (scope, el, attrs, form) {
form.use(scope, el);
function atInputSelect () { let input = el.find('input')[0];
function link (scope, element, attrs) { let select = el.find('select')[0];
}
input.addEventListener('focus', () => select.focus());
select.addEventListener('focus', () => input.classList.add('at-Input--focus'));
select.addEventListener('mousedown', () => scope.open = !scope.open);
select.addEventListener('change', () => scope.open = false );
select.addEventListener('blur', () => {
input.classList.remove('at-Input--focus')
scope.open = scope.open && false;
});
}
function atInputSelect (pathService) {
return { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/input/select.partial.html', replace: true,
require: '^^at-form',
templateUrl: pathService.getPartialPath('components/input/select'),
link, link,
scope: { scope: {
config: '=' config: '=',
col: '@'
} }
}; };
} }
atInputSelect.$inject = ['PathService'];
export default atInputSelect; export default atInputSelect;

View File

@@ -1,25 +1,23 @@
<div class="form-group"> <div class="col-sm-{{ col }}">
<label class="at-Input-label"> <div class="form-group at-u-flat">
<span ng-if="config.required" class="at-Input-label--required">*</span> <label class="at-Input-label">
<span>{{ config.label }}</span> <span ng-if="config.required" class="at-Input-label--required">*</span>
</label> <span>{{ config.label }}</span>
<div class="input-group"> </label>
<select class="form-control at-Input at-Select" ng-model="config.input" <div class="at-InputGroup at-Select">
ng-mousedown="opened = opened || true" <input type="text" class="form-control at-Input at-Select-input"
ng-class="{ 'at-Input--placeholder': input === undefined && !opened }"> ng-attr-autofocus="{{ meta.autofocus || undefined }}"
<option class="at-Select-option--placeholder" value="" disabled selected> placeholder="{{ config.placeholder | uppercase }}" ng-model="config.input" />
SELECT A TYPE
</option> <select class="form-control at-Select-select" ng-model="config.input"
<optgroup ng-repeat="group in config.data" label="{{ group.category | uppercase }}"> tabindex="{{ meta.tabindex }}">
<option ng-repeat="item in group.data" value="{{ item.id }}"> <optgroup ng-repeat="group in config.data" label="{{ group.category | uppercase }}">
{{ item.name }} <option ng-repeat="item in group.data" value="{{ item.name }}">
</option> {{ item.name }}
</optgroup> </option>
</select> </optgroup>
<span class="input-group-btn"> </select>
<button class="btn at-Button--default at-Select-button"> <i class="fa" ng-class="{ 'fa-caret-down': !open, 'fa-caret-up': open }"></i>
<i class="fa fa-caret-down"></i> </div>
</button>
</span>
</div> </div>
</div> </div>

View File

@@ -1,15 +1,14 @@
function link (scope, el, attrs, form) { function link (scope, el, attrs, form) {
scope.form = form.track(el); form.use(scope, el);
console.log('text', scope.form);
} }
function atInputText () { function atInputText (pathService) {
return { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
replace: true, replace: true,
require: '^^at-form', require: '^^at-form',
templateUrl: 'static/partials/components/input/text.partial.html', templateUrl: pathService.getPartialPath('components/input/text'),
link, link,
scope: { scope: {
config: '=', config: '=',
@@ -18,4 +17,6 @@ function atInputText () {
}; };
} }
atInputText.$inject = ['PathService'];
export default atInputText; export default atInputText;

View File

@@ -1,11 +1,11 @@
<div class="col-sm-{{ col }}"> <div class="col-sm-{{ col }}">
<div class="form-group"> <div class="form-group at-u-flat">
<label class="at-Input-label"> <label class="at-Input-label">
<span ng-if="config.required" class="at-Input-label--required">*</span> <span ng-if="config.required" class="at-Input-label--required">*</span>
<span>{{ config.label | uppercase }}</span> <span>{{ config.label | uppercase }}</span>
</label> </label>
<input type="text" class="form-control at-Input" ng-model="config.input" <input type="text" class="form-control at-Input" ng-model="config.input"
ng-attr-autofocus="{{ form.autofocus || undefined }}" tabindex="{{ form.tabindex }}" ng-attr-autofocus="{{ meta.autofocus || undefined }}" tabindex="{{ meta.tabindex }}"
placeholder="{{ config.placeholder }}" /> placeholder="{{ config.placeholder }}" />
</div> </div>
</div> </div>

View File

@@ -8,7 +8,31 @@
padding: 0; padding: 0;
} }
.at-Panel-dismiss {
line-height: 0.9;
text-align: right;
color: @at-gray-light;
& > i {
cursor: pointer;
}
& > i:hover {
color: @at-gray;
}
}
.at-Panel-body { .at-Panel-body {
margin: @at-margin-md 0 0 0; margin: @at-margin-md 0 0 0;
padding: 0; padding: 0;
} }
.at-Panel-headingTitle {
color: @at-gray-dark;
font-size: @at-font-md;
font-weight: bold;
line-height: 0.9;
text-transform: uppercase;
margin: 0;
padding: 0;
}

View File

@@ -1,9 +1,12 @@
function atPanelBody () { function atPanelBody (pathService) {
return { return {
restrict: 'E', restrict: 'E',
require: '^^atPanel',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/panel/body.partial.html' templateUrl: pathService.getPartialPath('components/panel/body'),
}; };
} }
atPanelBody.$inject = ['PathService'];
export default atPanelBody; export default atPanelBody;

View File

@@ -1,12 +1,20 @@
function atPanelHeading () { function link (scope, el, attrs, panel) {
panel.use(scope);
}
function atPanelHeading (pathService) {
return { return {
restrict: 'E', restrict: 'E',
require: '^^atPanel',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/panel/heading.partial.html', templateUrl: pathService.getPartialPath('components/panel/heading'),
link,
scope: { scope: {
config: '=' config: '='
} }
}; };
} }
atPanelHeading.$inject = ['PathService'];
export default atPanelHeading; export default atPanelHeading;

View File

@@ -1,8 +1,12 @@
<div class="panel-heading at-Panel-heading"> <div class="row">
<div class="at-Title-row"> <div class="col-xs-11">
<div class="at-Title-text"> <h3 class="at-Panel-headingTitle">
<ng-transclude></ng-transclude> {{ config.text }}
</h3>
</div>
<div class="col-xs-1">
<div class="at-Panel-dismiss">
<i class="fa fa-times-circle fa-lg" ng-click="dismiss()"></i>
</div>
</div> </div>
</div>
</div> </div>

View File

@@ -1,9 +1,33 @@
function atPanel () { 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 { return {
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
templateUrl: 'static/partials/components/panel/panel.partial.html' templateUrl: pathService.getPartialPath('components/panel/panel'),
controller,
controllerAs: 'vm',
scope: {
config: '='
}
}; };
} }
atPanel.$inject = ['PathService'];
export default atPanel; export default atPanel;

View File

@@ -0,0 +1,5 @@
import PathService from './path.service';
angular
.module('at.lib', [])
.factory('PathService', PathService);

View File

@@ -0,0 +1,16 @@
function getPartialPath (path) {
return `/static/partials/${path}.partial.html`;
}
function getViewPath (path) {
return `/static/views/${path}.view.html`;
}
function PathService () {
return {
getPartialPath,
getViewPath
};
}
export default PathService;

View File

@@ -74,6 +74,7 @@ import instanceGroups from './instance-groups/main';
import '../components'; import '../components';
import '../models'; import '../models';
import '../lib';
import './credentials'; import './credentials';
var tower = angular.module('Tower', [ var tower = angular.module('Tower', [
@@ -138,6 +139,7 @@ var tower = angular.module('Tower', [
'ngResource', 'ngResource',
'at.components', 'at.components',
'at.models', 'at.models',
'at.lib',
'at.features.credentials' 'at.features.credentials'
]) ])

View File

@@ -10,6 +10,10 @@ function AddCredentialsController (credentialType) {
label: 'Description' label: 'Description'
}; };
vm.heading = {
text: 'Create Credentials'
};
vm.kind = { vm.kind = {
label: 'Type', label: 'Type',
placeholder: 'Select a Type', placeholder: 'Select a Type',

View File

@@ -1,13 +1,12 @@
<at-panel> <at-panel config="vm.panel">
<at-panel-heading> <at-panel-heading config="vm.heading">
Create Credentials
</at-panel-heading> </at-panel-heading>
<at-panel-body> <at-panel-body>
<at-form> <at-form>
<at-input-text col="4" config="vm.name"></at-input-text> <at-input-text col="4" config="vm.name"></at-input-text>
<at-input-text col="4" config="vm.description"></at-input-text> <at-input-text col="4" config="vm.description"></at-input-text>
<at-input-dropdown col="4" config="vm.kind"></at-input-dropdown> <at-input-select col="4" config="vm.kind"></at-input-select>
</at-form> </at-form>
</at-panel-body> </at-panel-body>
</at-panel> </at-panel>

View File

@@ -3,7 +3,8 @@ import ListController from './list/credentials-list.controller';
import AddController from './add-credentials.controller.js'; import AddController from './add-credentials.controller.js';
import { N_ } from '../i18n'; import { N_ } from '../i18n';
function config ($stateExtenderProvider) { function config ($stateExtenderProvider, pathServiceProvider) {
let pathService = pathServiceProvider.$get();
let stateExtender = $stateExtenderProvider.$get(); let stateExtender = $stateExtenderProvider.$get();
stateExtender.addState({ stateExtender.addState({
@@ -14,7 +15,7 @@ function config ($stateExtenderProvider) {
}, },
views: { views: {
'@': { '@': {
templateUrl: '/static/views/credentials/index.view.html', templateUrl: pathService.getViewPath('credentials/index')
}, },
'list@credentials': { 'list@credentials': {
templateProvider: function(CredentialList, generateList) { templateProvider: function(CredentialList, generateList) {
@@ -47,14 +48,14 @@ function config ($stateExtenderProvider) {
}, },
views: { views: {
'add@credentials': { 'add@credentials': {
templateUrl: '/static/views/credentials/add-credentials.view.html', templateUrl: pathService.getViewPath('credentials/add-credentials'),
controller: AddController, controller: AddController,
controllerAs: 'vm' controllerAs: 'vm'
} }
}, },
resolve: { resolve: {
credentialType: ['CredentialType', CredentialType => { credentialType: ['CredentialType', credentialType => {
return CredentialType.get().then(() => CredentialType); return credentialType.get().then(() => credentialType);
}] }]
} }
}); });
@@ -76,7 +77,8 @@ function config ($stateExtenderProvider) {
} }
config.$inject = [ config.$inject = [
'$stateExtenderProvider' '$stateExtenderProvider',
'PathServiceProvider'
]; ];
angular angular

View File

@@ -1,28 +1,11 @@
/** /**
* For styles that are used in more than one place throughout the application. * For styles that are used in more than one place throughout the application.
* *
* 1. Content * 1. Buttons
* 2. Buttons
* *
*/ */
// 1. Content // 1. Buttons
// ------------------------------------------------------------------------------------------------
.at-Title-row {
align-items: center;
flex: 1 0 auto;
display: flex;
}
.at-Title-text {
color: @at-gray-dark;
font-size: @at-font-md;
font-weight: bold;
margin-right: @at-margin-sm;
text-transform: uppercase;
}
// 2. Buttons
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
.at-Button--success { .at-Button--success {
.at-Button(@at-success, @at-white); .at-Button(@at-success, @at-white);

View File

@@ -1,3 +1,13 @@
.at-u-noPadding { .at-u-flat {
padding: 0; 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;
} }