Merge pull request #6820 from gconsidine/ui/credentials-translation

Add translation for components and credentials
This commit is contained in:
Greg Considine
2017-07-05 12:11:13 -04:00
committed by GitHub
28 changed files with 337 additions and 117 deletions

View File

@@ -1,21 +1,19 @@
const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; function AddCredentialsController (models, $state, strings) {
function AddCredentialsController (models, $state) {
let vm = this || {}; let vm = this || {};
let me = models.me; let me = models.me;
let credential = models.credential; let credential = models.credential;
let credentialType = models.credentialType; let credentialType = models.credentialType;
let organization = models.organization;
vm.panelTitle = 'NEW CREDENTIAL'; vm.mode = 'add';
vm.strings = strings.credentials;
vm.panelTitle = vm.strings[vm.mode].PANEL_TITLE;
vm.tab = { vm.tab = {
details: { details: { _active: true },
_active: true permissions:{ _disabled: true }
},
permissions:{
_disabled: true
}
}; };
vm.form = credential.createFormSchema('post', { vm.form = credential.createFormSchema('post', {
@@ -24,9 +22,13 @@ function AddCredentialsController (models, $state) {
vm.form.organization._resource = 'organization'; vm.form.organization._resource = 'organization';
vm.form.organization._route = 'credentials.add.organization'; vm.form.organization._route = 'credentials.add.organization';
vm.form.organization._model = organization;
vm.form.organization._placeholder = vm.strings.inputs.ORGANIZATION_PLACEHOLDER;
vm.form.credential_type._resource = 'credential_type'; vm.form.credential_type._resource = 'credential_type';
vm.form.credential_type._route = 'credentials.add.credentialType'; vm.form.credential_type._route = 'credentials.add.credentialType';
vm.form.credential_type._model = credentialType;
vm.form.credential_type._placeholder = vm.strings.inputs.CREDENTIAL_TYPE_PLACEHOLDER;
vm.form.inputs = { vm.form.inputs = {
_get: id => { _get: id => {
@@ -52,7 +54,8 @@ function AddCredentialsController (models, $state) {
AddCredentialsController.$inject = [ AddCredentialsController.$inject = [
'resolvedModels', 'resolvedModels',
'$state' '$state',
'CredentialsStrings'
]; ];
export default AddCredentialsController; export default AddCredentialsController;

View File

@@ -2,8 +2,8 @@
<at-panel-heading>{{ vm.panelTitle }}</at-panel-heading> <at-panel-heading>{{ vm.panelTitle }}</at-panel-heading>
<at-tab-group> <at-tab-group>
<at-tab state="vm.tab.details">Details</at-tab> <at-tab state="vm.tab.details">{{ vm.strings.tab.DETAILS }}</at-tab>
<at-tab state="vm.tab.permissions">Permissions</at-tab> <at-tab state="vm.tab.permissions">{{ vm.strings.tab.PERMISSIONS }}</at-tab>
</at-tab-group> </at-tab-group>
<at-panel-body> <at-panel-body>
@@ -17,7 +17,7 @@
<at-input-lookup col="4" tab="4" state="vm.form.credential_type"></at-input-lookup> <at-input-lookup col="4" tab="4" state="vm.form.credential_type"></at-input-lookup>
<at-input-group col="4" tab="5" state="vm.form.inputs"> <at-input-group col="4" tab="5" state="vm.form.inputs">
Type Details {{ vm.strings.inputs.GROUP_TITLE }}
</at-input-group> </at-input-group>
<at-action-group col="12" pos="right"> <at-action-group col="12" pos="right">
@@ -29,11 +29,11 @@
</at-panel> </at-panel>
<at-panel ng-if="$state.current.name.includes('permissions')"> <at-panel ng-if="$state.current.name.includes('permissions')">
<at-panel-heading>CREDENTIALS PERMISSIONS</at-panel-heading> <at-panel-heading>{{ vm.strings.permissions.TITLE }}</at-panel-heading>
<at-tab-group> <at-tab-group>
<at-tab state="vm.tab.details">Details</at-tab> <at-tab state="vm.tab.details">{{ vm.strings.tab.DETAILS }}</at-tab>
<at-tab state="vm.tab.permissions">Permissions</at-tab> <at-tab state="vm.tab.permissions">{{ vm.strings.tab.PERMISSIONS }}</at-tab>
</at-tab-group> </at-tab-group>
<at-panel-body> <at-panel-body>

View File

@@ -0,0 +1,34 @@
function CredentialsStrings (BaseString) {
BaseString.call(this, 'credentials');
let t = this.t;
let ns = this.credentials;
ns.state = {
ADD_BREADCRUMB_LABEL: t('CREATE CREDENTIAL'),
EDIT_BREADCRUMB_LABEL: t('EDIT CREDENTIAL')
};
ns.tab = {
DETAILS: t('Details'),
PERMISSIONS: t('Permissions')
};
ns.inputs = {
GROUP_TITLE: t('Type Details'),
ORGANIZATION_PLACEHOLDER: t('SELECT AN ORGANIZATION'),
CREDENTIAL_TYPE_PLACEHOLDER: t('SELECT A CREDENTIAL TYPE')
};
ns.add = {
PANEL_TITLE: t('NEW CREDENTIAL')
};
ns.permissions = {
TITLE: t('CREDENTIALS PERMISSIONS')
};
}
CredentialsStrings.$inject = ['BaseStringService'];
export default CredentialsStrings;

View File

@@ -1,12 +1,15 @@
const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; function EditCredentialsController (models, $state, $scope, strings) {
function EditCredentialsController (models, $state, $scope) {
let vm = this || {}; let vm = this || {};
let me = models.me; let me = models.me;
let credential = models.credential; let credential = models.credential;
let credentialType = models.credentialType; let credentialType = models.credentialType;
let selectedCredentialType = credentialType.getById(credential.get('credential_type')); let organization = models.organization;
let selectedCredentialType = models.selectedCredentialType;
vm.mode = 'edit';
vm.strings = strings.credentials;
vm.panelTitle = credential.get('name');
vm.tab = { vm.tab = {
details: { details: {
@@ -33,21 +36,23 @@ function EditCredentialsController (models, $state, $scope) {
// Only exists for permissions compatibility // Only exists for permissions compatibility
$scope.credential_obj = credential.get(); $scope.credential_obj = credential.get();
vm.panelTitle = credential.get('name');
vm.form = credential.createFormSchema('put', { vm.form = credential.createFormSchema('put', {
omit: ['user', 'team', 'inputs'] omit: ['user', 'team', 'inputs']
}); });
vm.form.organization._resource = 'organization'; vm.form.organization._resource = 'organization';
vm.form.organization._model = organization;
vm.form.organization._route = 'credentials.edit.organization'; vm.form.organization._route = 'credentials.edit.organization';
vm.form.organization._value = credential.get('summary_fields.organization.id'); vm.form.organization._value = credential.get('summary_fields.organization.id');
vm.form.organization._displayValue = credential.get('summary_fields.organization.name'); vm.form.organization._displayValue = credential.get('summary_fields.organization.name');
vm.form.organization._placeholder = vm.strings.inputs.ORGANIZATION_PLACEHOLDER;
vm.form.credential_type._resource = 'credential_type'; vm.form.credential_type._resource = 'credential_type';
vm.form.credential_type._model = credentialType;
vm.form.credential_type._route = 'credentials.edit.credentialType'; vm.form.credential_type._route = 'credentials.edit.credentialType';
vm.form.credential_type._value = selectedCredentialType.id; vm.form.credential_type._value = selectedCredentialType.get('id');
vm.form.credential_type._displayValue = selectedCredentialType.name; vm.form.credential_type._displayValue = selectedCredentialType.get('name');
vm.form.credential_type._placeholder = vm.strings.inputs.CREDENTIAL_TYPE_PLACEHOLDER;
vm.form.inputs = { vm.form.inputs = {
_get (id) { _get (id) {
@@ -80,7 +85,8 @@ function EditCredentialsController (models, $state, $scope) {
EditCredentialsController.$inject = [ EditCredentialsController.$inject = [
'resolvedModels', 'resolvedModels',
'$state', '$state',
'$scope' '$scope',
'CredentialsStrings'
]; ];
export default EditCredentialsController; export default EditCredentialsController;

View File

@@ -1,23 +1,38 @@
import LegacyCredentials from './legacy.credentials'; import LegacyCredentials from './legacy.credentials';
import AddController from './add-credentials.controller.js'; import AddController from './add-credentials.controller';
import EditController from './edit-credentials.controller.js'; import EditController from './edit-credentials.controller';
import { N_ } from '../../src/i18n'; import CredentialsStrings from './credentials.strings'
function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType) { function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType, Organization) {
let id = $stateParams.credential_id; let id = $stateParams.credential_id;
let models;
let promises = { let promises = {
me: new Me('get'), me: new Me('get'),
credentialType: new CredentialType('get') credentialType: new CredentialType('get'),
organization: new Organization('get')
}; };
if (id) { if (!id) {
promises.credential = new Credential(['get', 'options'], [id, id]);
} else {
promises.credential = new Credential('options'); promises.credential = new Credential('options');
return $q.all(promises)
} }
return $q.all(promises); promises.credential = new Credential(['get', 'options'], [id, id]);
return $q.all(promises)
.then(_models_ => {
models = _models_;
let credentialTypeId = models.credential.get('credential_type');
return models.credentialType.graft(credentialTypeId);
})
.then(selectedCredentialType => {
models.selectedCredentialType = selectedCredentialType;
return models;
});
} }
CredentialsResolve.$inject = [ CredentialsResolve.$inject = [
@@ -25,19 +40,23 @@ CredentialsResolve.$inject = [
'$stateParams', '$stateParams',
'MeModel', 'MeModel',
'CredentialModel', 'CredentialModel',
'CredentialTypeModel' 'CredentialTypeModel',
'OrganizationModel'
]; ];
function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider) { function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider, stringProvider) {
let path = pathProvider.$get(); let path = pathProvider.$get();
let stateExtender = $stateExtenderProvider.$get(); let stateExtender = $stateExtenderProvider.$get();
let legacy = legacyProvider.$get(); let legacy = legacyProvider.$get();
let strings = stringProvider.$get();
strings = strings.credentials.state;
stateExtender.addState({ stateExtender.addState({
name: 'credentials.add', name: 'credentials.add',
route: '/add', route: '/add',
ncyBreadcrumb: { ncyBreadcrumb: {
label: N_('CREATE CREDENTIALS') label: strings.ADD_BREADCRUMB_LABEL
}, },
views: { views: {
'add@credentials': { 'add@credentials': {
@@ -55,7 +74,7 @@ function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider
name: 'credentials.edit', name: 'credentials.edit',
route: '/:credential_id', route: '/:credential_id',
ncyBreadcrumb: { ncyBreadcrumb: {
label: N_('EDIT') label: strings.EDIT_BREADCRUMB_LABEL
}, },
views: { views: {
'edit@credentials': { 'edit@credentials': {
@@ -81,7 +100,8 @@ function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider
CredentialsConfig.$inject = [ CredentialsConfig.$inject = [
'$stateExtenderProvider', '$stateExtenderProvider',
'LegacyCredentialsServiceProvider', 'LegacyCredentialsServiceProvider',
'PathServiceProvider' 'PathServiceProvider',
'CredentialsStringsProvider'
]; ];
angular angular
@@ -89,4 +109,5 @@ angular
.config(CredentialsConfig) .config(CredentialsConfig)
.controller('AddController', AddController) .controller('AddController', AddController)
.controller('EditController', EditController) .controller('EditController', EditController)
.service('LegacyCredentialsService', LegacyCredentials); .service('LegacyCredentialsService', LegacyCredentials)
.service('CredentialsStrings', CredentialsStrings);

View File

@@ -113,7 +113,7 @@ function LegacyCredentialsService (pathService) {
}, },
ncyBreadcrumb: { ncyBreadcrumb: {
parent: 'credentials.edit', parent: 'credentials.edit',
label: 'PERMISSIONS' label: N_('PERMISSIONS')
}, },
views: { views: {
'related': { 'related': {
@@ -336,7 +336,7 @@ function LegacyCredentialsService (pathService) {
return this.credentialType; return this.credentialType;
default: default:
throw new Error(`Legacy state configuration for ${name} does not exist`); throw new Error(N_(`Legacy state configuration for ${name} does not exist`));
}; };
}; };
} }

View File

@@ -0,0 +1,49 @@
function ComponentsStrings (BaseString) {
BaseString.call(this, 'components');
let t = this.t;
let ns = this.components;
ns.REPLACE = t('REPLACE');
ns.REVERT = t('REVERT');
ns.ENCRYPTED = t('ENCRYPTED');
ns.OPTIONS = t('OPTIONS');
ns.SHOW = t('SHOW');
ns.HIDE = t('HIDE');
ns.message = {
REQUIRED_INPUT_MISSING: t('Please enter a value.'),
INVALID_INPUT: t('Invalid input for this type.')
};
ns.form = {
SUBMISSION_ERROR_TITLE: t('Unable to Submit'),
SUBMISSION_ERROR_MESSAGE:t('Unexpected server error. View the console for more information'),
SUBMISSION_ERROR_PREFACE: t('Unexpected Error')
};
ns.group = {
UNSUPPORTED_ERROR_PREFACE: t('Unsupported input type')
};
ns.label = {
PROMPT_ON_LAUNCH: t('Prompt on launch')
};
ns.select = {
UNSUPPORTED_TYPE_ERROR: t('Unsupported display model type'),
EMPTY_PLACEHOLDER: t('NO OPTIONS AVAILABLE')
};
ns.textarea = {
SSH_KEY_HINT: t('HINT: Drag and drop an SSH private key file on the field below.')
};
ns.lookup = {
NOT_FOUND: t('That value was not found. Please enter or select a valid value.')
};
}
ComponentsStrings.$inject = ['BaseStringService'];
export default ComponentsStrings;

View File

@@ -5,7 +5,7 @@ function link (scope, element, attrs, controllers) {
actionController.init(formController, element, scope); actionController.init(formController, element, scope);
} }
function atFormActionController ($state) { function atFormActionController ($state, strings) {
let vm = this || {}; let vm = this || {};
let element; let element;
@@ -36,21 +36,21 @@ function atFormActionController ($state) {
}; };
vm.setCancelDefaults = () => { vm.setCancelDefaults = () => {
scope.text = 'CANCEL'; scope.text = strings.CANCEL;
scope.fill = 'Hollow'; scope.fill = 'Hollow';
scope.color = 'default'; scope.color = 'default';
scope.action = () => $state.go(scope.to || '^'); scope.action = () => $state.go(scope.to || '^');
}; };
vm.setSaveDefaults = () => { vm.setSaveDefaults = () => {
scope.text = 'SAVE'; scope.text = strings.SAVE;
scope.fill = ''; scope.fill = '';
scope.color = 'success'; scope.color = 'success';
scope.action = () => form.submit(); scope.action = () => form.submit();
}; };
} }
atFormAction.$inject = ['$state']; atFormActionController.$inject = ['$state', 'ComponentsStrings'];
function atFormAction (pathService) { function atFormAction (pathService) {
return { return {

View File

@@ -8,13 +8,15 @@ function atFormLink (scope, el, attrs, controllers) {
formController.init(scope, form); formController.init(scope, form);
} }
function AtFormController (eventService) { function AtFormController (eventService, strings) {
let vm = this || {}; let vm = this || {};
let scope; let scope;
let modal; let modal;
let form; let form;
strings = strings.components.forms;
vm.components = []; vm.components = [];
vm.state = { vm.state = {
isValid: false, isValid: false,
@@ -99,6 +101,8 @@ function AtFormController (eventService) {
if (!handled) { if (!handled) {
let message; let message;
let title = strings.SUBMISSION_ERROR_TITLE;
let preface = strings.SUBMISSION_ERROR_PREFACE;
if (typeof err.data === 'object') { if (typeof err.data === 'object') {
message = JSON.stringify(err.data); message = JSON.stringify(err.data);
@@ -106,13 +110,13 @@ function AtFormController (eventService) {
message = err.data; message = err.data;
} }
modal.show('Unable to Submit', `Unexpected Error: ${message}`); modal.show(title, `${preface}: ${message}`)
} }
}; };
vm.handleUnexpectedError = err => { vm.handleUnexpectedError = err => {
let title = 'Unable to Submit'; let title = strings.SUBMISSION_ERROR_TITLE;
let message = 'Unexpected server error. View the console for more information'; let message = strings.SUBMISSION_ERROR_MESSAGE;
modal.show(title, message); modal.show(title, message);
@@ -190,7 +194,7 @@ function AtFormController (eventService) {
}; };
} }
AtFormController.$inject = ['EventService']; AtFormController.$inject = ['EventService', 'ComponentsStrings'];
function atForm (pathService) { function atForm (pathService) {
return { return {

View File

@@ -8,6 +8,7 @@ import inputLabel from './input/label.directive';
import inputLookup from './input/lookup.directive'; import inputLookup from './input/lookup.directive';
import inputMessage from './input/message.directive'; import inputMessage from './input/message.directive';
import inputSecret from './input/secret.directive'; import inputSecret from './input/secret.directive';
import inputSelect from './input/select.directive';
import inputText from './input/text.directive'; import inputText from './input/text.directive';
import inputTextarea from './input/textarea.directive'; import inputTextarea from './input/textarea.directive';
import inputTextareaSecret from './input/textarea-secret.directive'; import inputTextareaSecret from './input/textarea-secret.directive';
@@ -20,6 +21,7 @@ import tab from './tabs/tab.directive';
import tabGroup from './tabs/group.directive'; import tabGroup from './tabs/group.directive';
import BaseInputController from './input/base.controller'; import BaseInputController from './input/base.controller';
import ComponentsStrings from './components.strings';
angular angular
.module('at.lib.components', []) .module('at.lib.components', [])
@@ -33,6 +35,7 @@ angular
.directive('atInputLookup', inputLookup) .directive('atInputLookup', inputLookup)
.directive('atInputMessage', inputMessage) .directive('atInputMessage', inputMessage)
.directive('atInputSecret', inputSecret) .directive('atInputSecret', inputSecret)
.directive('atInputSelect', inputSelect)
.directive('atInputText', inputText) .directive('atInputText', inputText)
.directive('atInputTextarea', inputTextarea) .directive('atInputTextarea', inputTextarea)
.directive('atInputTextareaSecret', inputTextareaSecret) .directive('atInputTextareaSecret', inputTextareaSecret)
@@ -43,6 +46,7 @@ angular
.directive('atPopover', popover) .directive('atPopover', popover)
.directive('atTab', tab) .directive('atTab', tab)
.directive('atTabGroup', tabGroup) .directive('atTabGroup', tabGroup)
.service('BaseInputController', BaseInputController); .service('BaseInputController', BaseInputController)
.service('ComponentsStrings', ComponentsStrings);

View File

@@ -1,17 +1,19 @@
const REQUIRED_INPUT_MISSING_MESSAGE = 'Please enter a value.'; function BaseInputController (strings) {
const DEFAULT_INVALID_INPUT_MESSAGE = 'Invalid input for this type.'; // Default values are universal. Don't translate.
const PROMPT_ON_LAUNCH_VALUE = 'ASK'; const PROMPT_ON_LAUNCH_VALUE = 'ASK';
const ENCRYPTED_VALUE = '$encrypted$'; const ENCRYPTED_VALUE = '$encrypted$';
function BaseInputController () {
return function extend (type, scope, element, form) { return function extend (type, scope, element, form) {
let vm = this; let vm = this;
vm.strings = strings;
scope.state = scope.state || {}; scope.state = scope.state || {};
scope.state._touched = false;
scope.state._required = scope.state.required || false; scope.state._required = scope.state.required || false;
scope.state._isValid = scope.state.isValid || false; scope.state._isValid = scope.state._isValid || false;
scope.state._disabled = scope.state.disabled || false; scope.state._disabled = scope.state._disabled || false;
scope.state._activeModel = '_value'; scope.state._activeModel = '_value';
if (scope.state.ask_at_runtime) { if (scope.state.ask_at_runtime) {
@@ -43,17 +45,19 @@ function BaseInputController () {
let isValid = true; let isValid = true;
let message = ''; let message = '';
if (scope.state._required && !scope.state._value) { if (scope.state._value || scope.state._displayValue) {
isValid = false; scope.state._touched = true;
message = REQUIRED_INPUT_MISSING_MESSAGE;
} }
if (scope.state.validate) { if (scope.state._required && !scope.state._value && !scope.state._displayValue) {
isValid = false;
message = vm.strings.components.message.REQUIRED_INPUT_MISSING;
} else if (scope.state._validate) {
let result = scope.state._validate(scope.state._value); let result = scope.state._validate(scope.state._value);
if (!result.isValid) { if (!result.isValid) {
isValid = false; isValid = false;
message = result.message || DEFAULT_INVALID_INPUT_MESSAGE; message = result.message || vm.strings.components.message.INVALID_INPUT;
} }
} }
@@ -66,7 +70,7 @@ function BaseInputController () {
vm.check = () => { vm.check = () => {
let result = vm.validate(); let result = vm.validate();
if (result.isValid !== scope.state._isValid) { if (scope.state._touched || !scope.state._required) {
scope.state._rejected = !result.isValid; scope.state._rejected = !result.isValid;
scope.state._isValid = result.isValid; scope.state._isValid = result.isValid;
scope.state._message = result.message; scope.state._message = result.message;
@@ -79,14 +83,14 @@ function BaseInputController () {
scope.state._isBeingReplaced = !scope.state._isBeingReplaced; scope.state._isBeingReplaced = !scope.state._isBeingReplaced;
if (!scope.state._isBeingReplaced) { if (!scope.state._isBeingReplaced) {
scope.state._buttonText = 'REPLACE'; scope.state._buttonText = vm.strings.components.REPLACE;
scope.state._disabled = true; scope.state._disabled = true;
scope.state._enableToggle = true; scope.state._enableToggle = true;
scope.state._value = scope.state._preEditValue; scope.state._value = scope.state._preEditValue;
scope.state._activeModel = '_displayValue'; scope.state._activeModel = '_displayValue';
scope.state._placeholder = 'ENCRYPTED'; scope.state._placeholder = vm.strings.components.ENCRYPTED;
} else { } else {
scope.state._buttonText = 'REVERT'; scope.state._buttonText = vm.strings.components.REVERT;
scope.state._disabled = false; scope.state._disabled = false;
scope.state._enableToggle = false; scope.state._enableToggle = false;
scope.state._activeModel = '_value'; scope.state._activeModel = '_value';
@@ -118,4 +122,6 @@ function BaseInputController () {
}; };
} }
BaseInputController.$inject = ['ComponentsStrings'];
export default BaseInputController; export default BaseInputController;

View File

@@ -15,7 +15,7 @@ function AtInputCheckboxController (baseInputController) {
vm.init = (scope, element, form) => { vm.init = (scope, element, form) => {
baseInputController.call(vm, 'input', scope, element, form); baseInputController.call(vm, 'input', scope, element, form);
scope.label = scope.state.label; scope.label = scope.state.label;
scope.state.label = 'OPTIONS'; scope.state.label = vm.strings.components.OPTIONS;
vm.check(); vm.check();
}; };

View File

@@ -34,14 +34,14 @@ function AtInputGroupController ($scope, $compile) {
}; };
vm.update = () => { vm.update = () => {
if (!vm.isValidSource()) {
return;
}
if (state._group) { if (state._group) {
vm.clear(); vm.clear();
} }
if (!vm.isValidSource()) {
return;
}
state._value = source._value; state._value = source._value;
let inputs = state._get(source._value); let inputs = state._get(source._value);
@@ -101,7 +101,8 @@ function AtInputGroupController ($scope, $compile) {
config._data = input.choices; config._data = input.choices;
config._exp = 'index as choice for (index, choice) in state._data'; config._exp = 'index as choice for (index, choice) in state._data';
} else { } else {
throw new Error('Unsupported input type: ' + input.type) let preface = vm.strings.components.UNSUPPORTED_ERROR_PREFACE;
throw new Error(`${preface}: ${input.type}`)
} }
return config; return config;
@@ -158,6 +159,8 @@ function AtInputGroupController ($scope, $compile) {
vm.clear = () => { vm.clear = () => {
form.deregisterInputGroup(state._group); form.deregisterInputGroup(state._group);
element.innerHTML = ''; element.innerHTML = '';
state._group = undefined;
state._value = undefined;
}; };
} }

View File

@@ -1,4 +1,4 @@
<div ng-show="state._value" class="col-sm-12 at-InputGroup"> <div ng-show="state._group" class="col-sm-12 at-InputGroup">
<div class="at-InputGroup-border"></div> <div class="at-InputGroup-border"></div>
<div class="at-InputGroup-inset"> <div class="at-InputGroup-inset">
<div class="row"> <div class="row">

View File

@@ -8,7 +8,7 @@
<input type="checkbox" <input type="checkbox"
ng-model="state._promptOnLaunch" ng-model="state._promptOnLaunch"
ng-change="vm.togglePromptOnLaunch()" /> ng-change="vm.togglePromptOnLaunch()" />
<p>Prompt on launch</p> <p>{{ vm.strings.components.label.PROMPT_ON_LAUNCH }}</p>
</label> </label>
</div> </div>
</label> </label>

View File

@@ -20,12 +20,13 @@ function AtInputLookupController (baseInputController, $state, $stateParams) {
scope = _scope_; scope = _scope_;
scope.$watch(scope.state._resource, vm.watchResource); scope.$watch(scope.state._resource, vm.watchResource);
scope.state._validate = vm.checkOnInput;
vm.check(); vm.check();
}; };
vm.watchResource = () => { vm.watchResource = () => {
if (scope[scope.state._resource]) { if (scope[scope.state._resource] !== scope.state._value) {
scope.state._value = scope[scope.state._resource]; scope.state._value = scope[scope.state._resource];
scope.state._displayValue = scope[`${scope.state._resource}_name`]; scope.state._displayValue = scope[`${scope.state._resource}_name`];
@@ -33,15 +34,43 @@ function AtInputLookupController (baseInputController, $state, $stateParams) {
} }
}; };
vm.search = () => { vm.lookup = () => {
let params = {}; let params = {};
if (scope.state._value) { if (scope.state._value && scope.state._isValid) {
params.selected = scope.state._value; params.selected = scope.state._value;
} }
$state.go(scope.state._route, params); $state.go(scope.state._route, params);
}; };
vm.reset = () => {
scope.state._value = undefined;
scope[scope.state._resource] = undefined;
};
vm.checkOnInput = () => {
if (!scope.state._touched) {
return { isValid: true };
}
let result = scope.state._model.match('get', 'name', scope.state._displayValue);
if (result) {
scope[scope.state._resource] = result.id;
scope.state._value = result.id;
scope.state._displayValue = result.name;
return { isValid: true };
}
vm.reset();
return {
isValid: false,
message: vm.strings.components.lookup.NOT_FOUND
};
};
} }
AtInputLookupController.$inject = [ AtInputLookupController.$inject = [

View File

@@ -6,13 +6,13 @@
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn at-ButtonHollow--default at-Input-button" <button class="btn at-ButtonHollow--default at-Input-button"
ng-disabled="state._disabled || form.disabled" ng-disabled="state._disabled || form.disabled"
ng-click="vm.search()"> ng-click="vm.lookup()">
<i class="fa fa-search"></i> <i class="fa fa-search"></i>
</button> </button>
</span> </span>
<input type="text" <input type="text"
class="form-control at-Input" class="form-control at-Input"
ng-class="{ 'at-Input--rejected': state.rejected }" ng-class="{ 'at-Input--rejected': state._rejected }"
ng-model="state._displayValue" ng-model="state._displayValue"
ng-attr-tabindex="{{ tab || undefined }}" ng-attr-tabindex="{{ tab || undefined }}"
ng-attr-placeholder="{{::state._placeholder || undefined }}" ng-attr-placeholder="{{::state._placeholder || undefined }}"

View File

@@ -20,13 +20,13 @@ function AtInputSecretController (baseInputController) {
scope = _scope_; scope = _scope_;
if (!scope.state._value || scope.state._promptOnLaunch) { if (!scope.state._value || scope.state._promptOnLaunch) {
scope.state._buttonText = 'SHOW'; scope.state._buttonText = vm.strings.components.SHOW;
scope.type = 'password'; scope.type = 'password';
vm.toggle = vm.toggleShowHide; vm.toggle = vm.toggleShowHide;
} else { } else {
scope.state._buttonText = 'REPLACE'; scope.state._buttonText = vm.strings.components.REPLACE;
scope.state._placeholder = 'ENCRYPTED'; scope.state._placeholder = vm.strings.components.ENCRYPTED;
vm.toggle = vm.toggleRevertReplace; vm.toggle = vm.toggleRevertReplace;
} }
@@ -36,10 +36,10 @@ function AtInputSecretController (baseInputController) {
vm.toggleShowHide = () => { vm.toggleShowHide = () => {
if (scope.type === 'password') { if (scope.type === 'password') {
scope.type = 'text'; scope.type = 'text';
scope.state._buttonText = 'HIDE'; scope.state._buttonText = vm.strings.components.HIDE;
} else { } else {
scope.type = 'password'; scope.type = 'password';
scope.state._buttonText = 'SHOW'; scope.state._buttonText = vm.strings.components.SHOW;
} }
}; };
} }

View File

@@ -1,5 +1,3 @@
const DEFAULT_EMPTY_PLACEHOLDER = 'NO OPTIONS AVAILABLE';
function atInputSelectLink (scope, element, attrs, controllers) { function atInputSelectLink (scope, element, attrs, controllers) {
let formController = controllers[0]; let formController = controllers[0];
let inputController = controllers[1]; let inputController = controllers[1];
@@ -11,7 +9,7 @@ function atInputSelectLink (scope, element, attrs, controllers) {
inputController.init(scope, element, formController); inputController.init(scope, element, formController);
} }
function AtInputSelectController (baseInputController, eventService) { function AtInputSelectController (baseInputController, eventService) {
let vm = this || {}; let vm = this || {};
let scope; let scope;
@@ -29,7 +27,7 @@ function AtInputSelectController (baseInputController, eventService) {
if (!scope.state._data || scope.state._data.length === 0) { if (!scope.state._data || scope.state._data.length === 0) {
scope.state._disabled = true; scope.state._disabled = true;
scope.state._placeholder = DEFAULT_EMPTY_PLACEHOLDER; scope.state._placeholder = vm.strings.components.EMPTY_PLACEHOLDER;
} }
vm.setListeners(); vm.setListeners();
@@ -67,7 +65,7 @@ function AtInputSelectController (baseInputController, eventService) {
} else if (scope.state._format === 'grouped-object') { } else if (scope.state._format === 'grouped-object') {
scope.displayModel = scope.state._value[scope.state._display]; scope.displayModel = scope.state._value[scope.state._display];
} else { } else {
throw new Error('Unsupported display model type'); throw new Error(vm.strings.components.UNSUPPORTED_TYPE_ERROR);
} }
}; };
} }

View File

@@ -1,5 +1,3 @@
const DEFAULT_HINT = 'HINT: Drag and drop an SSH private key file on the field below.';
function atInputTextareaSecretLink (scope, element, attrs, controllers) { function atInputTextareaSecretLink (scope, element, attrs, controllers) {
let formController = controllers[0]; let formController = controllers[0];
let inputController = controllers[1]; let inputController = controllers[1];
@@ -28,13 +26,13 @@ function AtInputTextareaSecretController (baseInputController, eventService) {
if (scope.state.format === 'ssh_private_key') { if (scope.state.format === 'ssh_private_key') {
scope.ssh = true; scope.ssh = true;
scope.state._hint = scope.state._hint || DEFAULT_HINT; scope.state._hint = scope.state._hint || vm.strings.components.textarea.SSH_KEY_HINT;
input = element.find('input')[0]; input = element.find('input')[0];
} }
if (scope.state._value) { if (scope.state._value) {
scope.state._buttonText = 'REPLACE'; scope.state._buttonText = vm.strings.components.REPLACE;
scope.state._placeholder = 'ENCRYPTED'; scope.state._placeholder = vm.strings.components.ENCRYPTED;
} else { } else {
if (scope.state.format === 'ssh_private_key') { if (scope.state.format === 'ssh_private_key') {
vm.listeners = vm.setFileListeners(textarea, input); vm.listeners = vm.setFileListeners(textarea, input);
@@ -54,7 +52,7 @@ function AtInputTextareaSecretController (baseInputController, eventService) {
vm.listeners = vm.setFileListeners(textarea, input); vm.listeners = vm.setFileListeners(textarea, input);
} else { } else {
scope.state._displayHint = false; scope.state._displayHint = false;
scope.state._placeholder = 'ENCRYPTED'; scope.state._placeholder = vm.strings.components.ENCRYPTED;
eventService.remove(vm.listeners); eventService.remove(vm.listeners);
} }
}; };
@@ -92,7 +90,11 @@ function AtInputTextareaSecretController (baseInputController, eventService) {
}; };
} }
AtInputTextareaSecretController.$inject = ['BaseInputController', 'EventService']; AtInputTextareaSecretController.$inject = [
'BaseInputController',
'EventService',
'ComponentsStrings'
];
function atInputTextareaSecret (pathService) { function atInputTextareaSecret (pathService) {
return { return {

View File

@@ -23,7 +23,7 @@
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn at-ButtonHollow--default" <button type="button" class="btn at-ButtonHollow--default"
ng-click="vm.hide()"> ng-click="vm.hide()">
OK {{ vm.strings.OK }}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -18,16 +18,8 @@ function AtTabGroupController ($state) {
}; };
vm.register = tab => { vm.register = tab => {
tab.active = true; tab.active = true;
/*
* if (vm.tabs.length === 0) {
* tab.active = true;
* } else {
* tab.disabled = true;
* }
*
*/
vm.tabs.push(tab); vm.tabs.push(tab);
}; };
} }

View File

@@ -12,8 +12,10 @@ function request (method, resource) {
} }
function httpGet (resource) { function httpGet (resource) {
this.method = this.method || 'GET';
let req = { let req = {
method: 'GET', method: this.method,
url: this.path url: this.path
}; };
@@ -85,6 +87,26 @@ function get (keys) {
return this.find('get', keys); return this.find('get', keys);
} }
function match (method, key, value) {
let model = this.model[method.toUpperCase()];
if (!model) {
return null;
}
if (!model.results) {
if (model[key] === value) {
return model;
}
return null;
}
let result = model.results.filter(result => result[key] === value);
return result.length === 0 ? null : result[0];
}
function find (method, keys) { function find (method, keys) {
let value = this.model[method.toUpperCase()]; let value = this.model[method.toUpperCase()];
@@ -138,6 +160,7 @@ function BaseModel (path) {
this.get = get; this.get = get;
this.options = options; this.options = options;
this.find = find; this.find = find;
this.match = match;
this.normalizePath = normalizePath; this.normalizePath = normalizePath;
this.getById = getById; this.getById = getById;
this.request = request; this.request = request;

View File

@@ -26,11 +26,18 @@ function mergeInputProperties (type) {
}); });
} }
function graft (id) {
let data = this.getById(id);
return new CredentialTypeModel('get', data);
}
function CredentialTypeModel (method, id) { function CredentialTypeModel (method, id) {
BaseModel.call(this, 'credential_types'); BaseModel.call(this, 'credential_types');
this.categorizeByKind = categorizeByKind.bind(this); this.categorizeByKind = categorizeByKind.bind(this);
this.mergeInputProperties = mergeInputProperties.bind(this); this.mergeInputProperties = mergeInputProperties.bind(this);
this.graft = graft.bind(this);
return this.request(method, id) return this.request(method, id)
.then(() => this); .then(() => this);

View File

@@ -0,0 +1,23 @@
let i18n;
function BaseStringService (namespace) {
let t = i18n._;
this.t = t;
this[namespace] = {};
this.CANCEL = t('CANCEL');
this.SAVE = t('SAVE');
this.OK = t('OK');
}
function BaseStringServiceLoader (_i18n_) {
i18n = _i18n_;
return BaseStringService;
}
BaseStringServiceLoader.$inject = ['i18n'];
export default BaseStringServiceLoader;

View File

@@ -1,7 +1,9 @@
import EventService from './event.service'; import EventService from './event.service';
import PathService from './path.service'; import PathService from './path.service';
import BaseStringService from './base-string.service';
angular angular
.module('at.lib.services', []) .module('at.lib.services', [])
.service('EventService', EventService) .service('EventService', EventService)
.service('PathService', PathService); .service('PathService', PathService)
.service('BaseStringService', BaseStringService);

View File

@@ -1,6 +1,7 @@
/* jshint ignore:start */ /* jshint ignore:start */
var sprintf = require('sprintf-js').sprintf; var sprintf = require('sprintf-js').sprintf;
let defaultLanguage = 'en_US';
/** /**
* @ngdoc method * @ngdoc method
@@ -24,7 +25,12 @@ export default
$window.navigator.userLanguage || $window.navigator.userLanguage ||
''; '';
var langUrl = langInfo.replace('-', '_'); var langUrl = langInfo.replace('-', '_');
//gettextCatalog.debug = true;
if (langUrl === defaultLanguage) {
return;
}
// gettextCatalog.debug = true;
gettextCatalog.setCurrentLanguage(langInfo); gettextCatalog.setCurrentLanguage(langInfo);
gettextCatalog.loadRemote('/static/languages/' + langUrl + '.json'); gettextCatalog.loadRemote('/static/languages/' + langUrl + '.json');
}; };

View File

@@ -1,11 +1,19 @@
let source = [
'client/features/**/*.js',
'client/features/**/*.html',
'client/lib/**/*.js',
'client/lib/**/*.html',
'client/src/**/*.js',
'client/src/**/*.html'
];
module.exports = { module.exports = {
all: { all: {
options: { options: {
markerNames: ['_', 'N_'] markerNames: ['_', 'N_', 't']
}, },
files: { files: {
'po/ansible-tower-ui.pot': ['client/src/**/*.js', 'po/ansible-tower-ui.pot': source
'client/src/**/*.html']
} }
}, }
}; };