mirror of
https://github.com/ansible/awx.git
synced 2024-11-02 09:51:09 +03:00
Add partial implementation of drag and drop ssh key support
This commit is contained in:
parent
0ca53024f0
commit
952958a83c
@ -85,7 +85,7 @@ function AtFormController (eventService) {
|
||||
let handled;
|
||||
|
||||
if (err.status === 400) {
|
||||
handled = vm.setValidationErrors(err.data);
|
||||
handled = vm.handleValidationErrors(err.data);
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
@ -93,22 +93,8 @@ function AtFormController (eventService) {
|
||||
}
|
||||
};
|
||||
|
||||
vm.setValidationErrors = errors => {
|
||||
let errorMessageSet = false;
|
||||
|
||||
for (let id in errors) {
|
||||
vm.components
|
||||
.filter(component => component.category === 'input')
|
||||
.forEach(component => {
|
||||
if (component.state._id === id) {
|
||||
errorMessageSet = true;
|
||||
|
||||
component.state._rejected = true;
|
||||
component.state._isValid = false;
|
||||
component.state._message = errors[id].join(' ');
|
||||
}
|
||||
});
|
||||
}
|
||||
vm.handleValidationErrors = errors => {
|
||||
let errorMessageSet = vm.setValidationMessages(errors);
|
||||
|
||||
if (errorMessageSet) {
|
||||
vm.check();
|
||||
@ -117,6 +103,30 @@ function AtFormController (eventService) {
|
||||
return errorMessageSet;
|
||||
};
|
||||
|
||||
vm.setValidationMessages = (errors, errorSet) => {
|
||||
let errorMessageSet = errorSet || false;
|
||||
|
||||
for (let id in errors) {
|
||||
if (!Array.isArray(errors[id]) && typeof errors[id] === 'object') {
|
||||
errorMessageSet = vm.setValidationMessages(errors[id], errorMessageSet);
|
||||
continue;
|
||||
}
|
||||
|
||||
vm.components
|
||||
.filter(component => component.category === 'input')
|
||||
.filter(component => errors[component.state.id])
|
||||
.forEach(component => {
|
||||
errorMessageSet = true;
|
||||
|
||||
component.state._rejected = true;
|
||||
component.state._isValid = false;
|
||||
component.state._message = errors[component.state.id].join(' ');
|
||||
});
|
||||
}
|
||||
|
||||
return errorMessageSet;
|
||||
};
|
||||
|
||||
vm.validate = () => {
|
||||
let isValid = true;
|
||||
|
||||
|
@ -15,8 +15,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputGroup-button {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.at-Input-button {
|
||||
width: 72px;
|
||||
width: @at-input-button-width;
|
||||
display: block;
|
||||
height: 100%;
|
||||
|
||||
&, &:active, &:hover, &:focus {
|
||||
color: @at-gray-dark-3x;
|
||||
@ -36,6 +42,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputFile--hidden {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: @at-input-button-width;
|
||||
z-index: -2;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.at-InputFile--drag {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
|
||||
.at-InputGroup {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@ -64,6 +85,10 @@
|
||||
height: @at-space-6x;
|
||||
}
|
||||
|
||||
.at-InputLabel {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.at-InputLabel-name {
|
||||
color: @at-gray-dark-4x;
|
||||
font-size: @at-font-size-2x;
|
||||
@ -71,6 +96,14 @@
|
||||
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;
|
||||
line-height: @at-line-height-short;
|
||||
}
|
||||
|
||||
.at-InputMessage--rejected {
|
||||
font-size: @at-font-size;
|
||||
color: @at-red;
|
||||
@ -82,8 +115,7 @@
|
||||
color: @at-red;
|
||||
font-weight: @at-font-weight-2x;
|
||||
font-size: @at-font-size-2x;
|
||||
line-height: @at-line-height-short;
|
||||
margin: @at-space-3x @at-space 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.at-InputSelect {
|
||||
@ -123,3 +155,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-Textarea {
|
||||
.at-mixin-FontFixedWidth();
|
||||
}
|
||||
|
@ -75,9 +75,9 @@ function AtInputGroupController ($scope, $compile) {
|
||||
if (input.type === 'string') {
|
||||
if (!input.multiline) {
|
||||
if (input.secret) {
|
||||
config._component = 'at-input-text';
|
||||
} else {
|
||||
config._component = 'at-input-secret';
|
||||
} else {
|
||||
config._component = 'at-input-text';
|
||||
}
|
||||
} else {
|
||||
config._expand = true;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<label class="at-InputLabel at-u-flat">
|
||||
<span ng-if="state.required" class="pull-left at-InputLabel-required">*</span>
|
||||
<span class="pull-left at-InputLabel-name">{{::state.label}}</span>
|
||||
<at-popover class="pull-left" state="state"></at-popover>
|
||||
<label class="at-InputLabel">
|
||||
<span ng-if="state.required" class="at-InputLabel-required">*</span>
|
||||
<span class="at-InputLabel-name">{{::state.label}}</span>
|
||||
<at-popover state="state"></at-popover>
|
||||
<span ng-if="state._hint" class="at-InputLabel-hint">{{::state._hint}}</span>
|
||||
</label>
|
||||
|
@ -1,25 +1,89 @@
|
||||
const DEFAULT_HINT = 'HINT: Drag and drop an SSH private key file on the field below.';
|
||||
|
||||
function atInputTextareaSecretLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
|
||||
if (scope.tab === '1') {
|
||||
element.find('input')[0].focus();
|
||||
element.find('textarea')[0].focus();
|
||||
}
|
||||
|
||||
inputController.init(scope, element, formController);
|
||||
}
|
||||
|
||||
function AtInputTextareaSecretController (baseInputController) {
|
||||
function AtInputTextareaSecretController (baseInputController, eventService) {
|
||||
let vm = this || {};
|
||||
|
||||
vm.init = (scope, element, form) => {
|
||||
baseInputController.call(vm, 'input', scope, element, form);
|
||||
let scope;
|
||||
let textarea;
|
||||
let input;
|
||||
|
||||
vm.init = (_scope_, element, form) => {
|
||||
baseInputController.call(vm, 'input', _scope_, element, form);
|
||||
|
||||
scope = _scope_;
|
||||
textarea = element.find('textarea')[0];
|
||||
|
||||
if (scope.state.format === 'ssh_private_key') {
|
||||
scope.ssh = true;
|
||||
scope.state._hint = scope.state._hint || DEFAULT_HINT;
|
||||
input = element.find('input')[0];
|
||||
vm.setFileListeners(textarea, input);
|
||||
} else {
|
||||
scope.isShown = true;
|
||||
scope.buttonText = 'HIDE';
|
||||
}
|
||||
|
||||
vm.check();
|
||||
};
|
||||
|
||||
vm.setFileListeners = (textarea, input) => {
|
||||
textarea
|
||||
let eventNames = [
|
||||
'drag',
|
||||
'dragstart',
|
||||
'dragend',
|
||||
'dragover',
|
||||
'dragenter',
|
||||
'dragleave',
|
||||
'drop'
|
||||
];
|
||||
|
||||
eventService.addListener(textarea, 'dragenter', event => {
|
||||
console.log('enter');
|
||||
scope.drag = true;
|
||||
});
|
||||
|
||||
eventService.addListener(input, ['dragleave', 'dragover'], event => {
|
||||
console.log('exit');
|
||||
scope.drag = false;
|
||||
});
|
||||
|
||||
eventService.addListener(input, 'drop', event => {
|
||||
vm.readFile(event.originalEvent.dataTransfer.files);
|
||||
});
|
||||
|
||||
eventService.addListener(input, eventNames, event => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
vm.readFile = () => {
|
||||
console.log(file);
|
||||
};
|
||||
|
||||
vm.toggle = () => {
|
||||
if (scope.isShown) {
|
||||
scope.buttonText = 'SHOW';
|
||||
} else {
|
||||
scope.buttonText = 'HIDE';
|
||||
}
|
||||
|
||||
scope.isShown = !scope.isShown;
|
||||
};
|
||||
}
|
||||
|
||||
AtInputTextareaSecretController.$inject = ['BaseInputController'];
|
||||
AtInputTextareaSecretController.$inject = ['BaseInputController', 'EventService'];
|
||||
|
||||
function atInputTextareaSecret (pathService) {
|
||||
return {
|
||||
|
@ -2,14 +2,29 @@
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<textarea class="form-control at-Input"
|
||||
ng-model="state._value"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" /></textarea>
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn at-InputGroup-button">
|
||||
<button class="btn at-ButtonHollow--white at-Input-button"
|
||||
ng-disabled="state._disabled || form.disabled"
|
||||
ng-click="vm.toggle()">
|
||||
{{ buttonText }}
|
||||
</button>
|
||||
</span>
|
||||
<input ng-show="ssh"
|
||||
class="at-InputFile--hidden"
|
||||
ng-class="{'at-InputFile--drag': drag }"
|
||||
type="file"
|
||||
name="files" />
|
||||
<textarea class="form-control at-Input at-Textarea"
|
||||
ng-model="state._value"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<at-input-message></at-input-message>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<textarea class="form-control at-Input"
|
||||
<textarea class="form-control at-Input at-Textarea"
|
||||
ng-model="state._value"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
|
@ -1,6 +1,9 @@
|
||||
.at-Popover {
|
||||
padding: 0 0 0 @at-space-4x;
|
||||
line-height: @at-line-height-short;
|
||||
padding: 0 0 0 @at-space-3x;
|
||||
}
|
||||
|
||||
.at-Popover--inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.at-Popover-icon {
|
||||
|
@ -4,7 +4,7 @@ function atPopoverLink (scope, el, attr, controllers) {
|
||||
let popover = container.getElementsByClassName('at-Popover-container')[0];
|
||||
let icon = container.getElementsByTagName('i')[0];
|
||||
|
||||
popoverController.init(container, icon, popover);
|
||||
popoverController.init(scope, container, icon, popover);
|
||||
}
|
||||
|
||||
function AtPopoverController () {
|
||||
@ -14,9 +14,10 @@ function AtPopoverController () {
|
||||
let icon;
|
||||
let popover;
|
||||
|
||||
vm.init = (_container_, _icon_, _popover_) => {
|
||||
vm.init = (scope, _container_, _icon_, _popover_) => {
|
||||
icon = _icon_;
|
||||
popover = _popover_;
|
||||
scope.inline = scope.state._inline || true;
|
||||
|
||||
icon.addEventListener('click', vm.createDisplayListener());
|
||||
};
|
||||
|
@ -1,4 +1,6 @@
|
||||
<div ng-show="state.help_text" class="at-Popover">
|
||||
<div ng-show="state.help_text"
|
||||
class="at-Popover"
|
||||
ng-class="{ 'at-Popover--inline': inline }">
|
||||
<span class="at-Popover-icon">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</span>
|
||||
|
@ -14,14 +14,22 @@ function EventService () {
|
||||
el
|
||||
};
|
||||
|
||||
listener.el.addEventListener(listener.name, listener.fn);
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach(e => listener.el.addEventListener(e, listener.fn));
|
||||
} else {
|
||||
listener.el.addEventListener(listener.name, listener.fn);
|
||||
}
|
||||
|
||||
return listener;
|
||||
};
|
||||
|
||||
this.remove = listeners => {
|
||||
listeners.forEach(listener => {
|
||||
listener.el.removeEventListener(listener.name, listener.fn);
|
||||
if (Array.isArray(listener.name)) {
|
||||
listener.name.forEach(name => listener.el.removeEventListener(name, listener.fn));
|
||||
} else {
|
||||
listener.el.removeEventListener(listener.name, listener.fn);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -76,3 +76,7 @@
|
||||
color: @at-gray-dark-3x;
|
||||
}
|
||||
}
|
||||
|
||||
.at-mixin-FontFixedWidth () {
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
@ -4,7 +4,8 @@
|
||||
* 1. Colors
|
||||
* 2. Typography
|
||||
* 3. Layout
|
||||
* 4. Misc
|
||||
* 4. Input
|
||||
* 5. Misc
|
||||
*/
|
||||
|
||||
// 1. Colors --------------------------------------------------------------------------------------
|
||||
@ -59,7 +60,10 @@
|
||||
@at-space-5x: 15px;
|
||||
@at-space-6x: 20px;
|
||||
|
||||
// 4. Misc --------------------------------------------------------------------------------------
|
||||
// 4. Input ---------------------------------------------------------------------------------------
|
||||
@at-input-button-width: 72px;
|
||||
|
||||
// 5. Misc ----------------------------------------------------------------------------------------
|
||||
@at-border-radius: 5px;
|
||||
@at-input-height: 30px;
|
||||
@at-popover-width: 320px;
|
||||
|
Loading…
Reference in New Issue
Block a user