From cc8b5bc80836f0c7f0299f2edaa8deb158fe9260 Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Fri, 10 Nov 2017 18:08:41 -0500 Subject: [PATCH] add file input component --- .../lib/components/components.strings.js | 4 + awx/ui/client/lib/components/index.js | 2 + .../client/lib/components/input/_index.less | 4 + .../lib/components/input/file.directive.js | 94 +++++++++++++++++++ .../lib/components/input/file.partial.html | 25 +++++ .../lib/components/input/group.directive.js | 2 + awx/ui/client/lib/theme/_variables.less | 2 + 7 files changed, 133 insertions(+) create mode 100644 awx/ui/client/lib/components/input/file.directive.js create mode 100644 awx/ui/client/lib/components/input/file.partial.html diff --git a/awx/ui/client/lib/components/components.strings.js b/awx/ui/client/lib/components/components.strings.js index db27701a46..cd4a573499 100644 --- a/awx/ui/client/lib/components/components.strings.js +++ b/awx/ui/client/lib/components/components.strings.js @@ -16,6 +16,10 @@ function ComponentsStrings (BaseString) { INVALID_INPUT: t.s('Invalid input for this type.') }; + ns.file = { + PLACEHOLDER: t.s('CHOOSE A FILE') + }; + ns.form = { SUBMISSION_ERROR_TITLE: t.s('Unable to Submit'), SUBMISSION_ERROR_MESSAGE: t.s('Unexpected server error. View the console for more information'), diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js index 426b9244cd..3033812739 100644 --- a/awx/ui/client/lib/components/index.js +++ b/awx/ui/client/lib/components/index.js @@ -5,6 +5,7 @@ import divider from '~components/utility/divider.directive'; import form from '~components/form/form.directive'; import formAction from '~components/form/action.directive'; import inputCheckbox from '~components/input/checkbox.directive'; +import inputFile from '~components/input/file.directive'; import inputGroup from '~components/input/group.directive'; import inputLabel from '~components/input/label.directive'; import inputLookup from '~components/input/lookup.directive'; @@ -41,6 +42,7 @@ angular .directive('atForm', form) .directive('atFormAction', formAction) .directive('atInputCheckbox', inputCheckbox) + .directive('atInputFile', inputFile) .directive('atInputGroup', inputGroup) .directive('atInputLabel', inputLabel) .directive('atInputLookup', inputLookup) diff --git a/awx/ui/client/lib/components/input/_index.less b/awx/ui/client/lib/components/input/_index.less index 087eaddfcb..b92692c34e 100644 --- a/awx/ui/client/lib/components/input/_index.less +++ b/awx/ui/client/lib/components/input/_index.less @@ -15,6 +15,10 @@ border-color: @at-color-input-focus; } + &[readonly] { + background: @at-color-input-readonly; + } + &[disabled] { background: @at-color-input-disabled; } diff --git a/awx/ui/client/lib/components/input/file.directive.js b/awx/ui/client/lib/components/input/file.directive.js new file mode 100644 index 0000000000..bdc7b8ecde --- /dev/null +++ b/awx/ui/client/lib/components/input/file.directive.js @@ -0,0 +1,94 @@ +const templateUrl = require('~components/input/file.partial.html'); + +function atInputFileLink (scope, element, attrs, controllers) { + const formController = controllers[0]; + const inputController = controllers[1]; + + if (scope.tab === '1') { + element.find('input')[0].focus(); + } + + inputController.init(scope, element, formController); +} + +function AtInputFileController (baseInputController, eventService) { + const vm = this || {}; + + let input; + let scope; + + vm.init = (_scope_, element, form) => { + baseInputController.call(vm, 'input', _scope_, element, form); + + scope = _scope_; + [input] = element.find('input'); + + vm.listeners = vm.setFileListeners(input); + + vm.check(); + }; + + vm.onButtonClick = () => { + if (scope.state._value) { + vm.removeFile(); + } else { + input.click(); + } + }; + + vm.setFileListeners = inputEl => eventService.addListeners([ + [inputEl, 'change', event => vm.handleFileChangeEvent(inputEl, event)] + ]); + + vm.handleFileChangeEvent = (element, event) => { + if (element.files.length > 0) { + const reader = new FileReader(); + + reader.onload = () => vm.readFile(reader, event); + reader.readAsText(element.files[0]); + } else { + scope.$apply(vm.removeFile); + } + }; + + vm.readFile = (reader, event) => { + scope.$apply(() => { + scope.state._value = reader.result; + scope.state._displayValue = event.target.files[0].name; + + vm.check(); + }); + }; + + vm.removeFile = () => { + delete scope.state._value; + delete scope.state._displayValue; + + input.value = ''; + }; +} + +AtInputFileController.$inject = [ + 'BaseInputController', + 'EventService' +]; + +function atInputFile () { + return { + restrict: 'E', + transclude: true, + replace: true, + require: ['^^atForm', 'atInputFile'], + templateUrl, + controller: AtInputFileController, + controllerAs: 'vm', + link: atInputFileLink, + scope: { + state: '=', + col: '@', + tab: '@' + } + }; +} + +export default atInputFile; diff --git a/awx/ui/client/lib/components/input/file.partial.html b/awx/ui/client/lib/components/input/file.partial.html new file mode 100644 index 0000000000..7e13fcc47e --- /dev/null +++ b/awx/ui/client/lib/components/input/file.partial.html @@ -0,0 +1,25 @@ +
+
+ + +
+ + + + +
+ +
+
diff --git a/awx/ui/client/lib/components/input/group.directive.js b/awx/ui/client/lib/components/input/group.directive.js index c94dd99f04..7e6f1f2426 100644 --- a/awx/ui/client/lib/components/input/group.directive.js +++ b/awx/ui/client/lib/components/input/group.directive.js @@ -99,6 +99,8 @@ function AtInputGroupController ($scope, $compile) { config._component = 'at-input-number'; } else if (input.type === 'boolean') { config._component = 'at-input-checkbox'; + } else if (input.type === 'file') { + config._component = 'at-input-file'; } else if (input.choices) { config._component = 'at-input-select'; config._format = 'array'; diff --git a/awx/ui/client/lib/theme/_variables.less b/awx/ui/client/lib/theme/_variables.less index 5bdbec8fda..2ff0156021 100644 --- a/awx/ui/client/lib/theme/_variables.less +++ b/awx/ui/client/lib/theme/_variables.less @@ -131,6 +131,8 @@ @at-color-input-button: @at-gray-light-3x; @at-color-input-button-hover: @at-gray-light-2x; @at-color-input-disabled: @at-gray-light; +@at-color-input-readonly: @at-color-input-background; + @at-color-input-error: @at-color-error; @at-color-input-focus: @at-color-info; @at-color-input-hint: @at-gray-dark-4x;