UI i18n Audit: Translates strings throughout the UI

Translations for dashboard lists -> tooltips

Changing "Portal Mode" to "My View," in part due to translations.

Adding "Job Template" to strings to be translated from OPTIONS on API

Marking translations for JT that has a project that needs to be re-synced.

Marking translations for survey maker

Marking translations for lookup modal directive

Marking translations for empty, "Go To Notifications To Add Template"

Adds strings service for scheduler, and marking strings for translation

Translations for teams linkout from orgs, as well as cred types

Translations for instance groups

Marks translations for the Network UI

Translates strings on the workflow editor

Translations for workflow results

Translations for host event modal and some missing translations on

the stdout page.
This commit is contained in:
Jared Tabor
2018-05-31 19:06:51 -07:00
parent 7912f56f02
commit 1a8b5426f8
46 changed files with 393 additions and 214 deletions

View File

@@ -299,10 +299,11 @@ class BaseSerializer(serializers.ModelSerializer):
'system_job': _('Management Job'), 'system_job': _('Management Job'),
'workflow_job': _('Workflow Job'), 'workflow_job': _('Workflow Job'),
'workflow_job_template': _('Workflow Template'), 'workflow_job_template': _('Workflow Template'),
'job_template': _('Job Template')
} }
choices = [] choices = []
for t in self.get_types(): for t in self.get_types():
name = type_name_map.get(t, force_text(get_model_for_type(t)._meta.verbose_name).title()) name = _(type_name_map.get(t, force_text(get_model_for_type(t)._meta.verbose_name).title()))
choices.append((t, name)) choices.append((t, name))
return choices return choices

View File

@@ -16,23 +16,23 @@
<div class="HostEvent-details"> <div class="HostEvent-details">
<div class="HostEvent-field"> <div class="HostEvent-field">
<span class="HostEvent-field--label">CREATED</span> <span class="HostEvent-field--label">{{strings.get('host_event_modal.CREATED')}}</span>
<span class="HostEvent-field--content">{{(event.created | longDate) || "No result found"}}</span> <span class="HostEvent-field--content">{{(event.created | longDate) || "No result found"}}</span>
</div> </div>
<div class="HostEvent-field"> <div class="HostEvent-field">
<span class="HostEvent-field--label">ID</span> <span class="HostEvent-field--label">{{strings.get('host_event_modal.ID')}}</span>
<span class="HostEvent-field--content">{{event.id || "No result found"}}</span> <span class="HostEvent-field--content">{{event.id || "No result found"}}</span>
</div> </div>
<div class="HostEvent-field"> <div class="HostEvent-field">
<span class="HostEvent-field--label">PLAY</span> <span class="HostEvent-field--label">{{strings.get('host_event_modal.PLAY')}}</span>
<span class="HostEvent-field--content">{{event.play || "No result found"}}</span> <span class="HostEvent-field--content">{{event.play || "No result found"}}</span>
</div> </div>
<div class="HostEvent-field"> <div class="HostEvent-field">
<span class="HostEvent-field--label">TASK</span> <span class="HostEvent-field--label">{{strings.get('host_event_modal.TASK')}}</span>
<span class="HostEvent-field--content">{{event.task || "No result found"}}</span> <span class="HostEvent-field--content">{{event.task || "No result found"}}</span>
</div> </div>
<div class="HostEvent-field"> <div class="HostEvent-field">
<span class="HostEvent-field--label">MODULE</span> <span class="HostEvent-field--label">{{strings.get('host_event_modal.MODULE')}}</span>
<span class="HostEvent-field--content HostEvent-field--monospaceContent">{{module_name}}</span> <span class="HostEvent-field--content HostEvent-field--monospaceContent">{{module_name}}</span>
</div> </div>
</div> </div>
@@ -48,12 +48,12 @@
<button ng-if="stdout" ui-sref="output.host-event.stdout" <button ng-if="stdout" ui-sref="output.host-event.stdout"
type="button" class="btn btn-sm btn-default HostEvent-tab" type="button" class="btn btn-sm btn-default HostEvent-tab"
ng-class="{'HostEvent-tab--selected' : isActiveState('output.host-event.stdout')}"> ng-class="{'HostEvent-tab--selected' : isActiveState('output.host-event.stdout')}">
Standard Out {{strings.get('host_event_modal.STANDARD_OUT')}}
</button> </button>
<button ng-if="stderr" ui-sref="output.host-event.stderr" <button ng-if="stderr" ui-sref="output.host-event.stderr"
type="button" class="btn btn-sm btn-default HostEvent-tab" type="button" class="btn btn-sm btn-default HostEvent-tab"
ng-class="{'HostEvent-tab--selected' : isActiveState('output.host-event.stderr')}"> ng-class="{'HostEvent-tab--selected' : isActiveState('output.host-event.stderr')}">
Standard Error {{strings.get('host_event_modal.STANDARD_ERROR')}}
</button> </button>
</div> </div>
@@ -64,7 +64,7 @@
<!-- controls --> <!-- controls -->
<div class="HostEvent-controls"> <div class="HostEvent-controls">
<button ng-click="closeHostEvent()" class="btn btn-sm btn-default HostEvent-close">Close</button> <button ng-click="closeHostEvent()" class="btn btn-sm btn-default HostEvent-close">{{strings.get('CLOSE')}}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -2,14 +2,15 @@ function HostEventsController (
$scope, $scope,
$state, $state,
HostEventService, HostEventService,
hostEvent hostEvent,
OutputStrings
) { ) {
$scope.processEventStatus = HostEventService.processEventStatus; $scope.processEventStatus = HostEventService.processEventStatus;
$scope.processResults = processResults; $scope.processResults = processResults;
$scope.isActiveState = isActiveState; $scope.isActiveState = isActiveState;
$scope.getActiveHostIndex = getActiveHostIndex; $scope.getActiveHostIndex = getActiveHostIndex;
$scope.closeHostEvent = closeHostEvent; $scope.closeHostEvent = closeHostEvent;
$scope.strings = OutputStrings;
function init () { function init () {
hostEvent.event_name = hostEvent.event; hostEvent.event_name = hostEvent.event;
$scope.event = _.cloneDeep(hostEvent); $scope.event = _.cloneDeep(hostEvent);
@@ -165,6 +166,7 @@ HostEventsController.$inject = [
'$state', '$state',
'HostEventService', 'HostEventService',
'hostEvent', 'hostEvent',
'OutputStrings'
]; ];
module.exports = HostEventsController; module.exports = HostEventsController;

View File

@@ -87,11 +87,25 @@ function OutputStrings (BaseString) {
ns.stats = { ns.stats = {
ELAPSED: t.s('Elapsed'), ELAPSED: t.s('Elapsed'),
PLAYS: t.s('Plays'),
TASKS: t.s('Tasks'),
HOSTS: t.s('Hosts')
}; };
ns.stdout = { ns.stdout = {
BACK_TO_TOP: t.s('Back to Top'), BACK_TO_TOP: t.s('Back to Top'),
}; };
ns.host_event_modal = {
CREATED: t.s('CREATED'),
ID: t.s('ID'),
PLAY: t.s('PLAY'),
TASK: t.s('TASK'),
MODULE: t.s('MODULE'),
NO_RESULT_FOUND: t.s('No result found'),
STANDARD_OUT: t.s('Standard Out'),
STANDARD_ERROR: t.s('Standard Error')
};
} }
OutputStrings.$inject = ['BaseStringService']; OutputStrings.$inject = ['BaseStringService'];

View File

@@ -8,7 +8,7 @@
<span ng-show="!vm.tasks" class="at-Panel-headingTitleBadge">...</span> <span ng-show="!vm.tasks" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.tasks" class="at-Panel-headingTitleBadge">{{ vm.tasks }}</span> <span ng-show="vm.tasks" class="at-Panel-headingTitleBadge">{{ vm.tasks }}</span>
<span class="at-Panel-label">hosts</span> <span class="at-Panel-label">{{:: vm.strings.get('stats.HOSTS')}}</span>
<span ng-show="!vm.hosts" class="at-Panel-headingTitleBadge">...</span> <span ng-show="!vm.hosts" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.hosts" class="at-Panel-headingTitleBadge">{{ vm.hosts }}</span> <span ng-show="vm.hosts" class="at-Panel-headingTitleBadge">{{ vm.hosts }}</span>

View File

@@ -23,6 +23,7 @@ function TemplatesStrings (BaseString) {
ns.prompt = { ns.prompt = {
INVENTORY: t.s('Inventory'), INVENTORY: t.s('Inventory'),
CREDENTIAL: t.s('Credential'), CREDENTIAL: t.s('Credential'),
PROMPT: t.s('PROMPT'),
OTHER_PROMPTS: t.s('Other Prompts'), OTHER_PROMPTS: t.s('Other Prompts'),
SURVEY: t.s('Survey'), SURVEY: t.s('Survey'),
PREVIEW: t.s('Preview'), PREVIEW: t.s('Preview'),
@@ -96,6 +97,31 @@ function TemplatesStrings (BaseString) {
INVALID_JOB_TEMPLATE: t.s('This Job Template is missing a default inventory or project. This must be addressed in the Job Template form before this node can be saved.'), INVALID_JOB_TEMPLATE: t.s('This Job Template is missing a default inventory or project. This must be addressed in the Job Template form before this node can be saved.'),
CREDENTIAL_WITH_PASS: t.s('This Job Template has a credential that requires a password. Credentials requiring passwords on launch are not permitted on workflow nodes.') CREDENTIAL_WITH_PASS: t.s('This Job Template has a credential that requires a password. Credentials requiring passwords on launch are not permitted on workflow nodes.')
}; };
ns.workflow_maker = {
DELETE_NODE_PROMPT_TEXT: t.s('Are you sure you want to delete this workflow node?'),
KEY: t.s('KEY'),
ON_SUCCESS: t.s('On Success'),
ON_FAILURE: t.s('On Failure'),
ALWAYS: t.s('Always'),
PROJECT_SYNC: t.s('Project Sync'),
INVENTORY_SYNC: t.s('Inventory Sync'),
WARNING: t.s('Warning'),
TOTAL_TEMPLATES: t.s('TOTAL TEMPLATES'),
ADD_A_TEMPLATE: t.s('ADD A TEMPLATE'),
EDIT_TEMPLATE: t.s('EDIT TEMPLATE'),
JOBS: t.s('JOBS'),
PLEASE_CLICK_THE_START_BUTTON: t.s('Please click the start button to build your workflow.'),
PLEASE_HOVER_OVER_A_TEMPLATE: t.s('Please hover over a template for additional options.'),
RUN: t.s('RUN'),
CHECK: t.s('CHECK'),
SELECT: t.s('SELECT'),
EDGE_CONFLICT: t.s('EDGE CONFLICT'),
DELETED: t.s('DELETED'),
START: t.s('START'),
DETAILS: t.s('DETAILS')
}
} }
TemplatesStrings.$inject = ['BaseStringService']; TemplatesStrings.$inject = ['BaseStringService'];

View File

@@ -68,7 +68,7 @@ function ComponentsStrings (BaseString) {
DASHBOARD: t.s('Dashboard'), DASHBOARD: t.s('Dashboard'),
JOBS: t.s('Jobs'), JOBS: t.s('Jobs'),
SCHEDULES: t.s('Schedules'), SCHEDULES: t.s('Schedules'),
PORTAL_MODE: t.s('Portal Mode'), MY_VIEW: t.s('My View'),
PROJECTS: t.s('Projects'), PROJECTS: t.s('Projects'),
CREDENTIALS: t.s('Credentials'), CREDENTIALS: t.s('Credentials'),
CREDENTIAL_TYPES: t.s('Credential Types'), CREDENTIAL_TYPES: t.s('Credential Types'),

View File

@@ -42,7 +42,7 @@
</at-side-nav-item> </at-side-nav-item>
<at-side-nav-item icon-class="fa-calendar" route="jobs.schedules" name="SCHEDULES"> <at-side-nav-item icon-class="fa-calendar" route="jobs.schedules" name="SCHEDULES">
</at-side-nav-item> </at-side-nav-item>
<at-side-nav-item icon-class="fa-columns" route="portalMode.myJobs" name="PORTAL_MODE"> <at-side-nav-item icon-class="fa-columns" route="portalMode.myJobs" name="MY_VIEW">
</at-side-nav-item> </at-side-nav-item>
<div class="at-Layout-sideNavSpacer"> <div class="at-Layout-sideNavSpacer">
<span class="at-Layout-sideNavHeader"> <span class="at-Layout-sideNavHeader">

View File

@@ -71,6 +71,7 @@ function BaseStringService (namespace) {
this.DELETE = t.s('DELETE'); this.DELETE = t.s('DELETE');
this.COPY = t.s('COPY'); this.COPY = t.s('COPY');
this.YES = t.s('YES'); this.YES = t.s('YES');
this.CLOSE = t.s('CLOSE');
this.deleteResource = { this.deleteResource = {
HEADER: t.s('Delete'), HEADER: t.s('Delete'),

View File

@@ -6,10 +6,10 @@
export default ['Rest', 'Wait', export default ['Rest', 'Wait',
'CredentialTypesForm', 'ProcessErrors', 'GetBasePath', 'CredentialTypesForm', 'ProcessErrors', 'GetBasePath',
'GenerateForm', '$scope', '$state', 'Alert', 'GetChoices', 'ParseTypeChange', 'ToJSON', 'CreateSelect2', 'GenerateForm', '$scope', '$state', 'Alert', 'GetChoices', 'ParseTypeChange', 'ToJSON', 'CreateSelect2', 'i18n',
function(Rest, Wait, function(Rest, Wait,
CredentialTypesForm, ProcessErrors, GetBasePath, CredentialTypesForm, ProcessErrors, GetBasePath,
GenerateForm, $scope, $state, Alert, GetChoices, ParseTypeChange, ToJSON, CreateSelect2 GenerateForm, $scope, $state, Alert, GetChoices, ParseTypeChange, ToJSON, CreateSelect2, i18n
) { ) {
var form = CredentialTypesForm, var form = CredentialTypesForm,
url = GetBasePath('credential_types'); url = GetBasePath('credential_types');
@@ -38,7 +38,7 @@ export default ['Rest', 'Wait',
}); });
const docs_url = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/credential_types.html#getting-started-with-credential-types'; const docs_url = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/credential_types.html#getting-started-with-credential-types';
const docs_help_text = `<br><br><a href=${docs_url}>Getting Started with Credential Types</a>`; const docs_help_text = `<br><br><a href=${docs_url}>${i18n._('Getting Started with Credential Types')}</a>`;
const api_inputs_help_text = _.get(options, 'actions.POST.inputs.help_text', "Specification for credential type inputs."); const api_inputs_help_text = _.get(options, 'actions.POST.inputs.help_text', "Specification for credential type inputs.");
const api_injectors_help_text = _.get(options, 'actions.POST.injectors.help_text', "Specification for credential type injector."); const api_injectors_help_text = _.get(options, 'actions.POST.injectors.help_text', "Specification for credential type injector.");

View File

@@ -3,7 +3,8 @@ export default
[ '$filter', [ '$filter',
'templateUrl', 'templateUrl',
'$location', '$location',
function JobsList($filter, templateUrl, $location) { 'i18n',
function JobsList($filter, templateUrl, $location, i18n) {
return { return {
restrict: 'E', restrict: 'E',
link: link, link: link,
@@ -29,7 +30,7 @@ export default
// detailsUrl, status, name, time // detailsUrl, status, name, time
scope.jobs = _.map(list, function(job){ scope.jobs = _.map(list, function(job){
let detailsUrl; let detailsUrl, tooltip;
if (job.type === 'workflow_job') { if (job.type === 'workflow_job') {
detailsUrl = `/#/workflows/${job.id}`; detailsUrl = `/#/workflows/${job.id}`;
@@ -37,12 +38,20 @@ export default
detailsUrl = `/#/jobs/playbook/${job.id}`; detailsUrl = `/#/jobs/playbook/${job.id}`;
} }
if(_.has(job, 'status') && job.status === 'successful'){
tooltip = i18n._('Job successful. Click for details.');
}
else if(_.has(job, 'status') && job.status === 'failed'){
tooltip = i18n._('Job failed. Click for details.');
}
return { return {
detailsUrl, detailsUrl,
status: job.status, status: job.status,
name: job.name, name: job.name,
id: job.id, id: job.id,
time: $filter('longDate')(job.finished) time: $filter('longDate')(job.finished),
tooltip: tooltip
}; }); }; });
} }

View File

@@ -16,10 +16,10 @@
<tr class="List-tableRow" <tr class="List-tableRow"
ng-repeat = "job in jobs"> ng-repeat = "job in jobs">
<td class="DashboardList-nameCell"> <td class="DashboardList-nameCell">
<a href="{{ job.detailsUrl }}" ng-if="isSuccessful(job.status)" aw-tool-tip="Job successful. Click for details." aw-tip-placement="right"> <a href="{{ job.detailsUrl }}" ng-if="isSuccessful(job.status)" aw-tool-tip="{{job.tooltip}}" aw-tip-placement="right" data-tip-watch="job.tooltip">
<i class="fa DashboardList-status DashboardList-status--success icon-job-successful"></i> <i class="fa DashboardList-status DashboardList-status--success icon-job-successful"></i>
</a> </a>
<a href="{{ job.detailsUrl }}" ng-if="!isSuccessful(job.status)" aw-tool-tip="Job failed. Click for details." aw-tip-placement="right"> <a href="{{ job.detailsUrl }}" ng-if="!isSuccessful(job.status)" aw-tool-tip="{{job.tooltip}}" aw-tip-placement="right" data-tip-watch="job.tooltip">
<i class="fa DashboardList-status DashboardList-status--failed icon-job-failed"></i> <i class="fa DashboardList-status DashboardList-status--failed icon-job-failed"></i>
</a> </a>
<a href="{{ job.detailsUrl }}" class="DashboardList-nameContainer"> <a href="{{ job.detailsUrl }}" class="DashboardList-nameContainer">

View File

@@ -34,7 +34,8 @@ function InstanceGroupsStrings (BaseString) {
ns.capacityBar = { ns.capacityBar = {
IS_OFFLINE: t.s('Unavailable to run jobs.'), IS_OFFLINE: t.s('Unavailable to run jobs.'),
IS_OFFLINE_LABEL: t.s('Unavailable') IS_OFFLINE_LABEL: t.s('Unavailable'),
USED_CAPACITY: t.s('Used Capacity')
}; };
ns.capacityAdjuster = { ns.capacityAdjuster = {
@@ -43,7 +44,8 @@ function InstanceGroupsStrings (BaseString) {
}; };
ns.jobs = { ns.jobs = {
PANEL_TITLE: t.s('Jobs') PANEL_TITLE: t.s('Jobs'),
RUNNING_JOBS: t.s('Running Jobs')
}; };
ns.error = { ns.error = {

View File

@@ -31,9 +31,8 @@ export default {
} }
}, },
resolve: { resolve: {
ListDefinition: ['CredentialList', 'i18n', function(CredentialList, i18n) { ListDefinition: ['CredentialList', function(CredentialList) {
let list = _.cloneDeep(CredentialList); let list = _.cloneDeep(CredentialList);
list.lookupConfirmText = i18n._('SELECT');
return list; return list;
}], }],
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',

View File

@@ -11,7 +11,7 @@
dy=".3em" dy=".3em"
text-anchor="left">{{contextMenuButton.name}} text-anchor="left">{{contextMenuButton.name}}
</text> </text>
<text ng-show="contextMenuButton.name ==='Remove'" ng-attr-class="{{contextMenuButton.is_pressed ? 'NetworkUI__contextMenuRemoveButtonText-pressed' : contextMenuButton.mouse_over ? 'NetworkUI__contextMenuRemoveButtonText-hover' : 'NetworkUI__contextMenuRemoveButtonText'}}" <text ng-show="contextMenuButton.type ==='remove'" ng-attr-class="{{contextMenuButton.is_pressed ? 'NetworkUI__contextMenuRemoveButtonText-pressed' : contextMenuButton.mouse_over ? 'NetworkUI__contextMenuRemoveButtonText-hover' : 'NetworkUI__contextMenuRemoveButtonText'}}"
x=15 x=15
ng-attr-y="{{(contextMenuButton.height * $parent.$index) + 18}}" ng-attr-y="{{(contextMenuButton.height * $parent.$index) + 18}}"
dy=".3em" dy=".3em"

View File

@@ -303,7 +303,7 @@ ContextMenu.prototype.is_selected = function (x, y) {
}; };
function ContextMenuButton(name, x, y, width, height, callback, tracer) { function ContextMenuButton(name, x, y, width, height, callback, tracer, type) {
this.name = name; this.name = name;
this.x = x; this.x = x;
this.y = y; this.y = y;
@@ -313,6 +313,7 @@ function ContextMenuButton(name, x, y, width, height, callback, tracer) {
this.is_pressed = false; this.is_pressed = false;
this.mouse_over = false; this.mouse_over = false;
this.enabled = true; this.enabled = true;
this.type = type;
this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer);
} }
exports.ContextMenuButton = ContextMenuButton; exports.ContextMenuButton = ContextMenuButton;

View File

@@ -5,8 +5,8 @@
*************************************************/ *************************************************/
export default export default
['$scope', 'HostsService', ['$scope', 'HostsService', 'awxNetStrings',
function($scope, HostsService){ function($scope, HostsService, strings){
function codemirror () { function codemirror () {
return { return {
@@ -17,6 +17,8 @@
$scope.formCancel = function(){ $scope.formCancel = function(){
$scope.$parent.$broadcast('awxNet-closeDetailsPanel'); $scope.$parent.$broadcast('awxNet-closeDetailsPanel');
}; };
$scope.strings = strings;
$scope.hostPopover = `<p>${$scope.strings.get('details.HOST_POPOVER')}</p><blockquote>myserver.domain.com<br/>127.0.0.1<br />10.1.0.140:25<br />server.example.com:25</blockquote>`;
$scope.formSave = function(){ $scope.formSave = function(){
var host = { var host = {

View File

@@ -11,9 +11,9 @@
<div ng-show="item.host_id"> <div ng-show="item.host_id">
<form class="Form Networking-form ng-pristine ng-valid ng-valid-required" name="host_form" id="host_form" autocomplete="off" novalidate=""> <form class="Form Networking-form ng-pristine ng-valid ng-valid-required" name="host_form" id="host_form" autocomplete="off" novalidate="">
<div class="form-group Form-formGroup Form-formGroup--fullWidth"> <div class="form-group Form-formGroup Form-formGroup--fullWidth">
<label class="Form-inputLabelContainer" for="name"> <label class="Form-inputLabelContainer">
<span class="Form-requiredAsterisk">*</span> <span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel" translate="">Host Name</span><a id="awp-name" href="" aw-pop-over="<p>Provide a host name, ip address, or ip address:port. Examples include:</p><blockquote>myserver.domain.com<br/>127.0.0.1<br />10.1.0.140:25<br />server.example.com:25</blockquote>" data-placement="right" data-container="body" over-title="Host Name" class="help-link" data-original-title="" title="" tabindex="-1"><i class="fa fa-question-circle"></i></a> <span class="Form-inputLabel"> {{strings.get('details.HOST_NAME')}}</span><a id="awp-name" href="" aw-pop-over="{{hostPopover}}" data-placement="right" data-tip-watch="hostPopover" data-container="body" over-title="{{strings.get('details.HOST_NAME')}}" class="help-link" data-original-title="" title="" tabindex="-1"><i class="fa fa-question-circle"></i></a>
</label> </label>
<div> <div>
<input readonly type="text" ng-model="item.name" name="name" id="host_name" class="form-control Form-textInput Networking-input ng-pristine ng-untouched ng-valid ng-not-empty ng-valid-required" required="" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)"> <input readonly type="text" ng-model="item.name" name="name" id="host_name" class="form-control Form-textInput Networking-input ng-pristine ng-untouched ng-valid ng-not-empty ng-valid-required" required="" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)">
@@ -22,8 +22,8 @@
</div> </div>
</div> </div>
<div class="form-group Form-formGroup Form-formGroup--fullWidth"> <div class="form-group Form-formGroup Form-formGroup--fullWidth">
<label class="Form-inputLabelContainer" for="description"> <label class="Form-inputLabelContainer">
<span class="Form-inputLabel" translate="">Description</span> <span class="Form-inputLabel">{{strings.get('details.DESCRIPTION')}}</span>
</label> </label>
<div> <div>
<input readonly type="text" ng-model="item.description" name="description" id="host_description" class="form-control Form-textInput Networking-input" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)"> <input readonly type="text" ng-model="item.description" name="description" id="host_description" class="form-control Form-textInput Networking-input" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)">
@@ -40,9 +40,9 @@
</div> </div>
</form> </form>
<div class="buttons Form-buttons" id="host_controls"> <div class="buttons Form-buttons" id="host_controls">
<button type="button" class="btn btn-sm Form-cancelButton" id="host_cancel_btn" ng-click="formCancel()"> Cancel</button> <button type="button" class="btn btn-sm Form-cancelButton" id="host_cancel_btn" ng-click="formCancel()"> {{strings.get('details.CANCEL')}}</button>
</div> </div>
<div class="Networking-saveConfirmation" ng-show="saveConfirmed"> <div class="Networking-saveConfirmation" ng-show="saveConfirmed">
Save Complete <i class="fa fa-check-circle"></i> {{strings.get('details.SAVE_COMPLETE')}} <i class="fa fa-check-circle"></i>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,4 @@
import NetworkingController from './network.nav.controller'; import NetworkingController from './network.nav.controller';
import NetworkingStrings from './network.nav.strings';
const MODULE_NAME = 'at.features.networking'; const MODULE_NAME = 'at.features.networking';
@@ -45,12 +44,11 @@ function NetworkingRun ($stateExtender, strings) {
NetworkingRun.$inject = [ NetworkingRun.$inject = [
'$stateExtender', '$stateExtender',
'NetworkingStrings' 'awxNetStrings'
]; ];
angular angular
.module(MODULE_NAME, []) .module(MODULE_NAME, [])
.service('NetworkingStrings', NetworkingStrings)
.run(NetworkingRun); .run(NetworkingRun);
export default MODULE_NAME; export default MODULE_NAME;

View File

@@ -164,6 +164,7 @@
font-weight: bold; font-weight: bold;
display: flex; display: flex;
align-items: center; align-items: center;
text-transform: uppercase;
} }
.Networking-keyContainer{ .Networking-keyContainer{
@@ -205,7 +206,8 @@
.Networking-keySymbolLabel{ .Networking-keySymbolLabel{
font-size: 12px; font-size: 12px;
padding-left: 15px; padding-left: 15px;
color: @default-stdout-txt color: @default-stdout-txt;
text-transform: uppercase;
} }
.Networking-toolboxPanelToolbarIcon--selected{ .Networking-toolboxPanelToolbarIcon--selected{

View File

@@ -33,26 +33,42 @@ function NetworkingController (models, $state, $scope, strings) {
$scope.$on('awxNet-instatiateSelect', (e, devices) => { $scope.$on('awxNet-instatiateSelect', (e, devices) => {
for(var i = 0; i < devices.length; i++){ for(var i = 0; i < devices.length; i++){
let device = devices[i]; let device = devices[i];
let grouping;
switch (device.type){
case 'host':
grouping = strings.get('search.HOST');
break;
case 'switch':
grouping = strings.get('search.SWITCH');
break;
case 'router':
grouping = strings.get('search.ROUTER');
break;
default:
grouping = strings.get('search.UNKNOWN');
}
$scope.devices.push({ $scope.devices.push({
value: device.id, value: device.id,
text: device.name, text: device.name,
label: device.name, label: device.name,
id: device.id, id: device.id,
type: device.type type: device.type,
group_type: grouping
}); });
} }
$("#networking-search").select2({ $("#networking-search").select2({
width:'400px', width:'400px',
containerCssClass: 'Form-dropDown', containerCssClass: 'Form-dropDown',
placeholder: 'SEARCH', placeholder: strings.get('search.SEARCH'),
dropdownParent: $('.Networking-toolbar'), dropdownParent: $('.Networking-toolbar'),
}); });
$("#networking-actionsDropdown").select2({ $("#networking-actionsDropdown").select2({
width:'400px', width:'400px',
containerCssClass: 'Form-dropDown', containerCssClass: 'Form-dropDown',
minimumResultsForSearch: -1, minimumResultsForSearch: -1,
placeholder: 'ACTIONS', placeholder: strings.get('actions.ACTIONS'),
dropdownParent: $('.Networking-toolbar'), dropdownParent: $('.Networking-toolbar'),
}); });
}); });
@@ -118,7 +134,7 @@ NetworkingController.$inject = [
'resolvedModels', 'resolvedModels',
'$state', '$state',
'$scope', '$scope',
'NetworkingStrings', 'awxNetStrings',
'CreateSelect2' 'CreateSelect2'
]; ];

View File

@@ -1,19 +0,0 @@
function NetworkingStrings (BaseString) {
BaseString.call(this, 'networking');
const { t } = this;
const ns = this.networking;
ns.state = {
BREADCRUMB_LABEL: t.s('INVENTORIES'),
};
ns.actions = {
EXPAND_PANEL: t.s('Expand Panel'),
COLLAPSE_PANEL: t.s('Collapse Panel')
};
}
NetworkingStrings.$inject = ['BaseStringService'];
export default NetworkingStrings;

View File

@@ -16,8 +16,8 @@
<select id="networking-actionsDropdown" <select id="networking-actionsDropdown"
style="width:400px"> style="width:400px">
<option></option> <option></option>
<option value="Export" title="Export">Export SVG</option> <option value="Export" title="Export">{{ vm.strings.get('actions.EXPORT') }} SVG</option>
<option value="ExportYaml" title="ExportYaml">Export YAML</option> <option value="ExportYaml" title="ExportYaml">{{ vm.strings.get('actions.EXPORT') }} YAML</option>
</select> </select>
</div> </div>
</div> </div>
@@ -33,26 +33,26 @@
</button> </button>
<div class="Networking-keyDropDownPanel" ng-if="vm.keyPanelExpanded"> <div class="Networking-keyDropDownPanel" ng-if="vm.keyPanelExpanded">
<div class="Networking-dropdownPanelTitle"> <div class="Networking-dropdownPanelTitle">
KEY {{ vm.strings.get('key.KEY') }}
</div> </div>
<div class="Networking-keyPanelOption"> <div class="Networking-keyPanelOption">
<div class="Networking-keySymbol">d</div> <div class="Networking-keySymbol">d</div>
<div class="Networking-keySymbolLabel">DEBUG MODE</div> <div class="Networking-keySymbolLabel">{{ vm.strings.get('key.DEBUG_MODE') }}</div>
</div> </div>
<div class="Networking-keyPanelOption"> <div class="Networking-keyPanelOption">
<div class="Networking-keySymbol">i</div> <div class="Networking-keySymbol">i</div>
<div class="Networking-keySymbolLabel">HIDE INTERFACES</div> <div class="Networking-keySymbolLabel">{{ vm.strings.get('key.HIDE_INTERFACES') }}</div>
</div> </div>
<div class="Networking-keyPanelOption"> <div class="Networking-keyPanelOption">
<div class="Networking-keySymbol">0</div> <div class="Networking-keySymbol">0</div>
<div class="Networking-keySymbolLabel">RESET ZOOM</div> <div class="Networking-keySymbolLabel">{{ vm.strings.get('key.RESET_ZOOM') }}</div>
</div> </div>
</div> </div>
</div> </div>
<div class="Networking-searchBarContainer"> <div class="Networking-searchBarContainer">
<select id="networking-search" <select id="networking-search"
ng-model="device" ng-model="device"
ng-options="device.label group by device.type | capitalize for device in devices | orderBy:'label' " ng-options="device.label group by device.group_type for device in devices | orderBy:'label' "
style="width:400px"> style="width:400px">
<option></option> <option></option>
</select> </select>

View File

@@ -3,6 +3,7 @@
import atFeaturesNetworking from './network-nav/main'; import atFeaturesNetworking from './network-nav/main';
import networkDetailsDirective from './network-details/main'; import networkDetailsDirective from './network-details/main';
import networkZoomWidget from './zoom-widget/main'; import networkZoomWidget from './zoom-widget/main';
import awxNetStrings from './network.ui.strings';
//console.log = function () { }; //console.log = function () { };
var NetworkUIController = require('./network.ui.controller.js'); var NetworkUIController = require('./network.ui.controller.js');
@@ -40,4 +41,5 @@ export default
.directive('awxNetQuadrants', quadrants.quadrants) .directive('awxNetQuadrants', quadrants.quadrants)
.directive('awxNetInventoryToolbox', inventoryToolbox.inventoryToolbox) .directive('awxNetInventoryToolbox', inventoryToolbox.inventoryToolbox)
.directive('awxNetTestResults', test_results.test_results) .directive('awxNetTestResults', test_results.test_results)
.directive('awxNetworkUi', awxNetworkUI.awxNetworkUI); .directive('awxNetworkUi', awxNetworkUI.awxNetworkUI)
.service('awxNetStrings', awxNetStrings);

View File

@@ -28,7 +28,8 @@ var NetworkUIController = function($scope,
$log, $log,
ProcessErrors, ProcessErrors,
ConfigService, ConfigService,
rbacUiControlService) { rbacUiControlService,
awxNetStrings) {
window.scope = $scope; window.scope = $scope;
@@ -153,6 +154,7 @@ var NetworkUIController = function($scope,
to_x: 0, to_x: 0,
to_y: 0}; to_y: 0};
$scope.canEdit = $scope.$parent.$resolve.resolvedModels.canEdit; $scope.canEdit = $scope.$parent.$resolve.resolvedModels.canEdit;
$scope.strings = awxNetStrings;
$scope.send_trace_message = function (message) { $scope.send_trace_message = function (message) {
if (!$scope.recording) { if (!$scope.recording) {
return; return;
@@ -265,7 +267,7 @@ var NetworkUIController = function($scope,
}; };
//Inventory Toolbox Setup //Inventory Toolbox Setup
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, toolboxTopMargin, 200, toolboxHeight); $scope.inventory_toolbox = new models.ToolBox(0, $scope.strings.get('toolbox.INVENTORY'), 'device', 0, toolboxTopMargin, 200, toolboxHeight);
if (!$scope.disconnected) { if (!$scope.disconnected) {
$scope.for_each_page('/api/v2/inventories/' + $scope.inventory_id + '/hosts/', $scope.for_each_page('/api/v2/inventories/' + $scope.inventory_id + '/hosts/',
function(all_results) { function(all_results) {
@@ -920,8 +922,8 @@ var NetworkUIController = function($scope,
const contextMenuButtonHeight = 26; const contextMenuButtonHeight = 26;
let contextMenuHeight = 64; let contextMenuHeight = 64;
$scope.context_menu_buttons = [ $scope.context_menu_buttons = [
new models.ContextMenuButton("Details", 236, 231, 160, contextMenuButtonHeight, $scope.onDetailsContextButton, $scope), new models.ContextMenuButton($scope.strings.get('context_menu.DETAILS'), 236, 231, 160, contextMenuButtonHeight, $scope.onDetailsContextButton, $scope, 'details'),
new models.ContextMenuButton("Remove", 256, 231, 160, contextMenuButtonHeight, $scope.onDeleteContextMenu, $scope) new models.ContextMenuButton($scope.strings.get('context_menu.REMOVE'), 256, 231, 160, contextMenuButtonHeight, $scope.onDeleteContextMenu, $scope, 'remove')
]; ];
if(!$scope.canEdit){ if(!$scope.canEdit){
$scope.context_menu_buttons.pop(); $scope.context_menu_buttons.pop();

View File

@@ -0,0 +1,56 @@
function awxNetStrings (BaseString) {
BaseString.call(this, 'awxNet');
const { t } = this;
const ns = this.awxNet;
ns.state = {
BREADCRUMB_LABEL: t.s('INVENTORIES')
};
ns.toolbox = {
INVENTORY: t.s('Inventory')
};
ns.actions = {
ACTIONS: t.s('Actions'),
EXPORT: t.s('Export'),
EXPAND_PANEL: t.s('Expand Panel'),
COLLAPSE_PANEL: t.s('Collapse Panel')
};
ns.key = {
KEY: t.s('Key'),
DEBUG_MODE: t.s('Debug Mode'),
HIDE_CURSOR: t.s('Hide Cursor'),
HIDE_BUTTONS: t.s('Hide Buttons'),
HIDE_INTERFACES: t.s('Hide Interfaces'),
RESET_ZOOM: t.s('Reset Zoom')
};
ns.search = {
SEARCH: t.s('Search'),
HOST: t.s('Host'),
SWITCH: t.s('Switch'),
ROUTER: t.s('Router'),
UNKNOWN: t.s('Unknown')
};
ns.context_menu = {
DETAILS: t.s('Details'),
REMOVE: t.s('Remove')
};
ns.details = {
HOST_NAME: t.s('Host Name'),
DESCRIPTION: t.s('Description'),
HOST_POPOVER: t.s('Provide a host name, ip address, or ip address:port. Examples include:'),
SAVE_COMPLETE: t.s('Save Complete'),
CANCEL: t.s('Cancel')
};
}
awxNetStrings.$inject = ['BaseStringService'];
export default awxNetStrings;

View File

@@ -1,4 +1,4 @@
<div class="List-action--notificationAdd"> <div class="List-action--notificationAdd">
<div>GO TO <a ui-sref="notifications.add">NOTIFICATIONS</a> TO</div> <div translate>GO TO <a ui-sref="notifications.add" translate>NOTIFICATIONS</a translate> TO</div>
<div>ADD A NEW TEMPLATE</div> <div translate>ADD A NEW TEMPLATE</div>
</div> </div>

View File

@@ -108,7 +108,7 @@ let lists = [{
delete list.fieldActions.delete; delete list.fieldActions.delete;
list.listTitle = N_('Teams') + ` | {{ name }}`; list.listTitle = N_('Teams') + ` | {{ name }}`;
list.basePath = `${GetBasePath('organizations')}${$stateParams.organization_id}/teams`; list.basePath = `${GetBasePath('organizations')}${$stateParams.organization_id}/teams`;
list.emptyListText = "This list is populated by teams added from the&nbsp;<a ui-sref='teams.add'>Teams</a>&nbsp;section"; list.emptyListText = `${N_('This list is populated by teams added from the')}&nbsp;<a ui-sref='teams.add'>${N_('Teams')}</a>&nbsp;${N_('section')}`;
return list; return list;
}], }],
OrgTeamsDataset: ['OrgTeamList', 'QuerySet', '$stateParams', 'GetBasePath', OrgTeamsDataset: ['OrgTeamList', 'QuerySet', '$stateParams', 'GetBasePath',

View File

@@ -57,17 +57,17 @@
<i>{{question.question_description}}</i> <i>{{question.question_description}}</i>
</div> </div>
<div class="SurveyMaker-previewInputRow"> <div class="SurveyMaker-previewInputRow">
<span dnd-handle class="SurveyMaker-reorderButton" data-placement="top" aw-tool-tip="Drag to reorder question" data-container="#survey-modal-dialog" data-original-title="" title="" ng-show="(job_template_obj.summary_fields.user_capabilities.edit || workflow_job_template_obj.summary_fields.user_capabilities.edit || canAdd)"> <span dnd-handle class="SurveyMaker-reorderButton" data-placement="top" aw-tool-tip="dragQuestionTooltip" data-tip-watch="dragQuestionTooltip" data-container="#survey-modal-dialog" data-original-title="" title="" ng-show="(job_template_obj.summary_fields.user_capabilities.edit || workflow_job_template_obj.summary_fields.user_capabilities.edit || canAdd)">
<i class="fa fa-ellipsis-v"></i> <i class="fa fa-ellipsis-v"></i>
<span>&nbsp;</span> <span>&nbsp;</span>
<i class="fa fa-ellipsis-v"></i> <i class="fa fa-ellipsis-v"></i>
</span> </span>
<survey-question class="SurveyMaker-previewInput" preview="true" question="question" ng-required="question.required" ng-disabled=true></survey-question> <survey-question class="SurveyMaker-previewInput" preview="true" question="question" ng-required="question.required" ng-disabled=true></survey-question>
<div class="SurveyMaker-previewActions" ng-show="(job_template_obj.summary_fields.user_capabilities.edit || workflow_job_template_obj.summary_fields.user_capabilities.edit || canAdd)"> <div class="SurveyMaker-previewActions" ng-show="(job_template_obj.summary_fields.user_capabilities.edit || workflow_job_template_obj.summary_fields.user_capabilities.edit || canAdd)">
<button class="List-actionButton" data-placement="top" ng-class="{'SurveyMaker-previewActions--selected' : editQuestionIndex == $index}" ng-click="editQuestion($index)" aw-tool-tip="Edit question" data-container="#survey-modal-dialog" data-original-title="" title=""> <button class="List-actionButton" data-placement="top" ng-class="{'SurveyMaker-previewActions--selected' : editQuestionIndex == $index}" ng-click="editQuestion($index)" aw-tool-tip="{{editQuestionTooltip}}" data-tip-watch="editQuestionTooltip" data-container="#survey-modal-dialog" data-original-title="" title="">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</button> </button>
<button class="List-actionButton List-actionButton--delete" data-placement="top" ng-click="showDeleteQuestion($index)" aw-tool-tip="Delete question" data-container="#survey-modal-dialog" data-original-title="" title=""> <button class="List-actionButton List-actionButton--delete" data-placement="top" ng-click="showDeleteQuestion($index)" aw-tool-tip="deleteQuestionTooltip" data-tip-watch="deleteQuestionTooltip" data-container="#survey-modal-dialog" data-original-title="" title="">
<i class="fa fa-trash-o"></i> <i class="fa fa-trash-o"></i>
</button> </button>
</div> </div>

View File

@@ -14,6 +14,7 @@ import SchedulePost from './factories/schedule-post.factory';
import ToggleSchedule from './factories/toggle-schedule.factory'; import ToggleSchedule from './factories/toggle-schedule.factory';
import SchedulesList from './schedules.list'; import SchedulesList from './schedules.list';
import ScheduledJobsList from './scheduled-jobs.list'; import ScheduledJobsList from './scheduled-jobs.list';
import SchedulerStrings from './scheduler.strings';
export default export default
angular.module('scheduler', []) angular.module('scheduler', [])
@@ -26,4 +27,5 @@ export default
.factory('ToggleSchedule', ToggleSchedule) .factory('ToggleSchedule', ToggleSchedule)
.factory('SchedulesList', SchedulesList) .factory('SchedulesList', SchedulesList)
.factory('ScheduledJobsList', ScheduledJobsList) .factory('ScheduledJobsList', ScheduledJobsList)
.directive('schedulerDatePicker', schedulerDatePicker); .directive('schedulerDatePicker', schedulerDatePicker)
.service('SchedulerStrings', SchedulerStrings);

View File

@@ -0,0 +1,61 @@
function SchedulerStrings (BaseString) {
BaseString.call(this, 'scheduler');
const { t } = this;
const ns = this.scheduler;
ns.state = {
CREATE_SCHEDULE: t.s('CREATE SCHEDULE'),
EDIT_SCHEDULE: t.s('EDIT SCHEDULE')
};
ns.form = {
NAME: t.s('Name'),
NAME_REQUIRED_MESSAGE: t.s('A schedule name is required.'),
START_DATE: t.s('Start Date'),
START_TIME: t.s('Start Time'),
START_TIME_ERROR_MESSAGE: t.s('The time must be in HH24:MM:SS format.'),
LOCAL_TIME_ZONE: t.s('Local Time Zone'),
REPEAT_FREQUENCY: t.s('Repeat frequency'),
FREQUENCY_DETAILS: t.s('Frequency Details'),
EVERY: t.s('Every'),
REPEAT_FREQUENCY_ERROR_MESSAGE: t.s('Please provide a value between 1 and 999.'),
ON_DAY: t.s('on day'),
MONTH_DAY_ERROR_MESSAGE: t.s('The day must be between 1 and 31.'),
ON_THE: t.s('on the'),
ON: t.s('on'),
ON_DAYS: t.s('on days'),
SUN: t.s('Sun'),
MON: t.s('Mon'),
TUE: t.s('Tue'),
WED: t.s('Wed'),
THU: t.s('Thu'),
FRI: t.s('Fri'),
SAT: t.s('Sat'),
WEEK_DAY_ERROR_MESSAGE: t.s('Please select one or more days.'),
END: t.s('End'),
OCCURENCES: t.s('Occurrences'),
END_DATE: t.s('End Date'),
PROVIDE_VALID_DATE: t.s('Please provide a valid date.'),
END_TIME: t.s('End Time'),
SCHEDULER_OPTIONS_ARE_INVALID: t.s('The scheduler options are invalid, incomplete, or a date is in the past.'),
SCHEDULE_DESCRIPTION: t.s('Schedule Description'),
LIMITED_TO_FIRST_TEN: t.s('Limited to first 10'),
DATE_FORMAT: t.s('Date format'),
EXTRA_VARIABLES: t.s('Extra Variables'),
PROMPT: t.s('Prompt'),
CLOSE: t.s('Close'),
CANCEL: t.s('Cancel'),
SAVE: t.s('Save'),
WARNING: t.s('Warning'),
CREDENTIAL_REQUIRES_PASSWORD_WARNING: t.s('This Job Template has a default credential that requires a password before launch. Adding or editing schedules is prohibited while this credential is selected. To add or edit a schedule, credentials that require a password must be removed from the Job Template.')
};
ns.prompt = {
CONFIRM: t.s('CONFIRM')
};
}
SchedulerStrings.$inject = ['BaseStringService'];
export default SchedulerStrings;

View File

@@ -8,12 +8,12 @@ export default ['$filter', '$state', '$stateParams', '$http', 'Wait',
'$scope', '$rootScope', 'CreateSelect2', 'ParseTypeChange', 'GetBasePath', '$scope', '$rootScope', 'CreateSelect2', 'ParseTypeChange', 'GetBasePath',
'Rest', 'ParentObject', 'JobTemplateModel', '$q', 'Empty', 'SchedulePost', 'Rest', 'ParentObject', 'JobTemplateModel', '$q', 'Empty', 'SchedulePost',
'ProcessErrors', 'SchedulerInit', '$location', 'PromptService', 'RRuleToAPI', 'moment', 'ProcessErrors', 'SchedulerInit', '$location', 'PromptService', 'RRuleToAPI', 'moment',
'WorkflowJobTemplateModel', 'TemplatesStrings', 'rbacUiControlService', 'Alert', 'i18n', 'WorkflowJobTemplateModel', 'SchedulerStrings', 'rbacUiControlService', 'Alert',
function($filter, $state, $stateParams, $http, Wait, function($filter, $state, $stateParams, $http, Wait,
$scope, $rootScope, CreateSelect2, ParseTypeChange, GetBasePath, $scope, $rootScope, CreateSelect2, ParseTypeChange, GetBasePath,
Rest, ParentObject, JobTemplate, $q, Empty, SchedulePost, Rest, ParentObject, JobTemplate, $q, Empty, SchedulePost,
ProcessErrors, SchedulerInit, $location, PromptService, RRuleToAPI, moment, ProcessErrors, SchedulerInit, $location, PromptService, RRuleToAPI, moment,
WorkflowJobTemplate, TemplatesStrings, rbacUiControlService, Alert, i18n WorkflowJobTemplate, SchedulerStrings, rbacUiControlService, Alert
) { ) {
var base = $scope.base || $location.path().replace(/^\//, '').split('/')[0], var base = $scope.base || $location.path().replace(/^\//, '').split('/')[0],
@@ -46,7 +46,7 @@ export default ['$filter', '$state', '$stateParams', '$http', 'Wait',
}; };
$scope.preventCredsWithPasswords = true; $scope.preventCredsWithPasswords = true;
$scope.strings = TemplatesStrings; $scope.strings = SchedulerStrings;
/* /*
* This is a workaround for the angular-scheduler library inserting `ll` into fields after an * This is a workaround for the angular-scheduler library inserting `ll` into fields after an
@@ -116,7 +116,7 @@ export default ['$filter', '$state', '$stateParams', '$http', 'Wait',
launchConf.passwords_needed_to_start.length > 0 && launchConf.passwords_needed_to_start.length > 0 &&
!launchConf.ask_credential_on_launch !launchConf.ask_credential_on_launch
) { ) {
Alert(i18n._('Warning'), i18n._('This Job Template has a default credential that requires a password before launch. Adding or editing schedules is prohibited while this credential is selected. To add or edit a schedule, credentials that require a password must be removed from the Job Template.'), 'alert-info'); Alert(SchedulerStrings.get('form.WARNING'), SchedulerStrings.get('form.CREDENTIAL_REQUIRES_PASSWORD_WARNING'), 'alert-info');
$state.go('^', { reload: true }); $state.go('^', { reload: true });
} }

View File

@@ -1,11 +1,11 @@
export default ['$filter', '$state', '$stateParams', 'Wait', '$scope', 'moment', export default ['$filter', '$state', '$stateParams', 'Wait', '$scope', 'moment',
'$rootScope', '$http', 'CreateSelect2', 'ParseTypeChange', 'ParentObject', 'ProcessErrors', 'Rest', '$rootScope', '$http', 'CreateSelect2', 'ParseTypeChange', 'ParentObject', 'ProcessErrors', 'Rest',
'GetBasePath', 'SchedulerInit', 'SchedulePost', 'JobTemplateModel', '$q', 'Empty', 'PromptService', 'RRuleToAPI', 'GetBasePath', 'SchedulerInit', 'SchedulePost', 'JobTemplateModel', '$q', 'Empty', 'PromptService', 'RRuleToAPI',
'WorkflowJobTemplateModel', 'TemplatesStrings', 'scheduleResolve', 'timezonesResolve', 'Alert', 'i18n', 'WorkflowJobTemplateModel', 'SchedulerStrings', 'scheduleResolve', 'timezonesResolve', 'Alert',
function($filter, $state, $stateParams, Wait, $scope, moment, function($filter, $state, $stateParams, Wait, $scope, moment,
$rootScope, $http, CreateSelect2, ParseTypeChange, ParentObject, ProcessErrors, Rest, $rootScope, $http, CreateSelect2, ParseTypeChange, ParentObject, ProcessErrors, Rest,
GetBasePath, SchedulerInit, SchedulePost, JobTemplate, $q, Empty, PromptService, RRuleToAPI, GetBasePath, SchedulerInit, SchedulePost, JobTemplate, $q, Empty, PromptService, RRuleToAPI,
WorkflowJobTemplate, TemplatesStrings, scheduleResolve, timezonesResolve, Alert, i18n WorkflowJobTemplate, SchedulerStrings, scheduleResolve, timezonesResolve, Alert
) { ) {
let schedule, scheduler, scheduleCredentials = []; let schedule, scheduler, scheduleCredentials = [];
@@ -21,7 +21,7 @@ function($filter, $state, $stateParams, Wait, $scope, moment,
$scope.hideForm = true; $scope.hideForm = true;
$scope.parseType = 'yaml'; $scope.parseType = 'yaml';
$scope.strings = TemplatesStrings; $scope.strings = SchedulerStrings;
/* /*
* Keep processSchedulerEndDt method on the $scope * Keep processSchedulerEndDt method on the $scope
@@ -255,7 +255,7 @@ function($filter, $state, $stateParams, Wait, $scope, moment,
launchConf.passwords_needed_to_start.length > 0 && launchConf.passwords_needed_to_start.length > 0 &&
!launchConf.ask_credential_on_launch !launchConf.ask_credential_on_launch
) { ) {
Alert(i18n._('Warning'), i18n._('This Job Template has a default credential that requires a password before launch. Adding or editing schedules is prohibited while this credential is selected. To add or edit a schedule, credentials that require a password must be removed from the Job Template.'), 'alert-info'); Alert(SchedulerStrings.get('form.WARNING'), SchedulerStrings.get('form.CREDENTIAL_REQUIRES_PASSWORD_WARNING'), 'alert-info');
$scope.credentialRequiresPassword = true; $scope.credentialRequiresPassword = true;
} }

View File

@@ -1,7 +1,7 @@
<div id="htmlTemplate" class=" SchedulerFormPanel Panel" ng-hide="hideForm"> <div id="htmlTemplate" class=" SchedulerFormPanel Panel" ng-hide="hideForm">
<div class="Form-header"> <div class="Form-header">
<div class="Form-title" ng-show="!isEdit">{{ schedulerName || "ADD SCHEDULE"}}</div> <div class="Form-title" ng-show="!isEdit">{{ schedulerName || strings.get('state.CREATE_SCHEDULE') }}</div>
<div class="Form-title" ng-show="isEdit">{{ schedulerName || "EDIT SCHEDULE"}}</div> <div class="Form-title" ng-show="isEdit">{{ schedulerName || strings.get('state.EDIT_SCHEDULE') }}</div>
<div class="Form-header--fields"></div> <div class="Form-header--fields"></div>
<div class="Form-exitHolder"> <div class="Form-exitHolder">
<button class="Form-exit" ng-click="formCancel()"> <button class="Form-exit" ng-click="formCancel()">
@@ -18,7 +18,7 @@
<div class="form-group SchedulerForm-formGroup"> <div class="form-group SchedulerForm-formGroup">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Name {{ strings.get('form.NAME') }}
</label> </label>
<input <input
type="text" type="text"
@@ -32,13 +32,13 @@
placeholder="Schedule name"> placeholder="Schedule name">
<div class="error" <div class="error"
ng-show="scheduler_form.$dirty && scheduler_form.schedulerName.$error.required"> ng-show="scheduler_form.$dirty && scheduler_form.schedulerName.$error.required">
A schedule name is required. {{ strings.get('form.NAME_REQUIRED_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group SchedulerForm-formGroup"> <div class="form-group SchedulerForm-formGroup">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Start Date {{ strings.get('form.START_DATE') }}
</label> </label>
<div class="input-group Form-inputGroup SchedulerForm-inputGroup--date"> <div class="input-group Form-inputGroup SchedulerForm-inputGroup--date">
<scheduler-date-picker date="schedulerStartDt" <scheduler-date-picker date="schedulerStartDt"
@@ -53,7 +53,7 @@
<div class="form-group SchedulerForm-formGroup"> <div class="form-group SchedulerForm-formGroup">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Start Time {{ strings.get('form.START_TIME') }}
<span class="fmt-help" <span class="fmt-help"
ng-show="schedulerShowTimeZone"> ng-show="schedulerShowTimeZone">
(HH24:MM:SS) (HH24:MM:SS)
@@ -111,14 +111,14 @@
</div> </div>
<div class="error" <div class="error"
ng-show="scheduler_startTime_error"> ng-show="scheduler_startTime_error">
The time must be in HH24:MM:SS format. {{ strings.get('form.START_TIME_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group SchedulerForm-formGroup" <div class="form-group SchedulerForm-formGroup"
ng-show="schedulerShowTimeZone"> ng-show="schedulerShowTimeZone">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Local Time Zone {{ strings.get('form.START_TIME') }}
</label> </label>
<select <select
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -134,7 +134,7 @@
<div class="form-group SchedulerForm-formGroup"> <div class="form-group SchedulerForm-formGroup">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Repeat frequency {{ strings.get('form.REPEAT_FREQUENCY') }}
</label> </label>
<select name="schedulerFrequency" <select name="schedulerFrequency"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -151,7 +151,7 @@
</div> </div>
<div class="RepeatFrequencyOptions-label" <div class="RepeatFrequencyOptions-label"
ng-show="schedulerFrequency.value && schedulerFrequency.value !== 'none'"> ng-show="schedulerFrequency.value && schedulerFrequency.value !== 'none'">
Frequency Details</div> {{ strings.get('form.FREQUENCY_DETAILS') }}</div>
<div class="RepeatFrequencyOptions Form" <div class="RepeatFrequencyOptions Form"
ng-show="schedulerFrequency.value && schedulerFrequency.value !== 'none'"> ng-show="schedulerFrequency.value && schedulerFrequency.value !== 'none'">
<div class="form-group <div class="form-group
@@ -161,7 +161,7 @@
<label class="Form-inputLabel <label class="Form-inputLabel
RepeatFrequencyOptions-everyLabel"> RepeatFrequencyOptions-everyLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Every {{ strings.get('form.EVERY') }}
</label> </label>
<input name="schedulerInterval" <input name="schedulerInterval"
id="schedulerInterval" id="schedulerInterval"
@@ -183,7 +183,7 @@
class="error class="error
RepeatFrequencyOptions-error" RepeatFrequencyOptions-error"
ng-show="$parent.scheduler_interval_error"> ng-show="$parent.scheduler_interval_error">
Please provide a value between 1 and 999. {{ strings.get('form.REPEAT_FREQUENCY_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group RepeatFrequencyOptions-formGroup" <div class="form-group RepeatFrequencyOptions-formGroup"
@@ -198,7 +198,7 @@
ng-change="monthlyRepeatChange()" ng-change="monthlyRepeatChange()"
name="monthlyRepeatOption" name="monthlyRepeatOption"
id="monthlyRepeatOption"> id="monthlyRepeatOption">
on day {{ strings.get('form.ON_DAY') }}
</label> </label>
</div> </div>
<input <input
@@ -213,7 +213,7 @@
ng-change="resetError('scheduler_monthDay_error')" > ng-change="resetError('scheduler_monthDay_error')" >
<div class="error" <div class="error"
ng-show="$parent.scheduler_monthDay_error"> ng-show="$parent.scheduler_monthDay_error">
The day must be between 1 and 31. {{ strings.get('form.MONTH_DAY_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group <div class="form-group
@@ -230,7 +230,7 @@
ng-change="monthlyRepeatChange()" ng-change="monthlyRepeatChange()"
name="monthlyRepeatOption" name="monthlyRepeatOption"
id="monthlyRepeatOption"> id="monthlyRepeatOption">
on the {{ strings.get('form.ON_THE') }}
</label> </label>
</div> </div>
<div class="RepeatFrequencyOptions-inputGroup <div class="RepeatFrequencyOptions-inputGroup
@@ -269,7 +269,7 @@
ng-change="yearlyRepeatChange()" ng-change="yearlyRepeatChange()"
name="yearlyRepeatOption" name="yearlyRepeatOption"
id="yearlyRepeatOption"> id="yearlyRepeatOption">
on {{ strings.get('form.ON') }}
</label> </label>
</div> </div>
<div class="RepeatFrequencyOptions-inputGroup <div class="RepeatFrequencyOptions-inputGroup
@@ -297,7 +297,7 @@
</div> </div>
<div class="error" <div class="error"
ng-show="$parent.scheduler_yearlyMonthDay_error"> ng-show="$parent.scheduler_yearlyMonthDay_error">
The day must be between 1 and 31. {{ strings.get('form.MONTH_DAY_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group <div class="form-group
@@ -314,7 +314,7 @@
ng-change="yearlyRepeatChange()" ng-change="yearlyRepeatChange()"
name="yearlyRepeatOption" name="yearlyRepeatOption"
id="yearlyRepeatOption"> id="yearlyRepeatOption">
on the {{ strings.get('form.ON_THE') }}
</label> </label>
</div> </div>
<div <div
@@ -361,7 +361,7 @@
ng-if="schedulerFrequency && schedulerFrequency.value == 'weekly'"> ng-if="schedulerFrequency && schedulerFrequency.value == 'weekly'">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
On Days {{ strings.get('form.ON_DAYS') }}
</label> </label>
<div class="input-group <div class="input-group
RepeatFrequencyOptions-weekButtonContainer"> RepeatFrequencyOptions-weekButtonContainer">
@@ -376,7 +376,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="SU" data-value="SU"
ng-click="$parent.setWeekday($event,'su')"> ng-click="$parent.setWeekday($event,'su')">
Sun {{ strings.get('form.SUN') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -385,7 +385,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="MO" data-value="MO"
ng-click="$parent.setWeekday($event,'mo')"> ng-click="$parent.setWeekday($event,'mo')">
Mon {{ strings.get('form.MON') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -394,7 +394,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="TU" data-value="TU"
ng-click="$parent.setWeekday($event,'tu')"> ng-click="$parent.setWeekday($event,'tu')">
Tue {{ strings.get('form.TUE') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -403,7 +403,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="WE" data-value="WE"
ng-click="$parent.setWeekday($event,'we')"> ng-click="$parent.setWeekday($event,'we')">
Wed {{ strings.get('form.WED') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -412,7 +412,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="TH" data-value="TH"
ng-click="$parent.setWeekday($event,'th')"> ng-click="$parent.setWeekday($event,'th')">
Thu {{ strings.get('form.THU') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -421,7 +421,7 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="FR" data-value="FR"
ng-click="$parent.setWeekday($event,'fr')"> ng-click="$parent.setWeekday($event,'fr')">
Fri {{ strings.get('form.FRI') }}
</button> </button>
<button type="button" <button type="button"
ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-disabled="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
@@ -430,13 +430,13 @@
RepeatFrequencyOptions-weekButton" RepeatFrequencyOptions-weekButton"
data-value="SA" data-value="SA"
ng-click="$parent.setWeekday($event,'sa')"> ng-click="$parent.setWeekday($event,'sa')">
Sat {{ strings.get('form.SAT') }}
</button> </button>
</div> </div>
</div> </div>
<div class="error" <div class="error"
ng-show="$parent.scheduler_weekDays_error"> ng-show="$parent.scheduler_weekDays_error">
Please select one or more days. {{ strings.get('form.WEEK_DAY_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group <div class="form-group
@@ -444,7 +444,7 @@
ng-if="schedulerShowInterval"> ng-if="schedulerShowInterval">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
End {{ strings.get('form.END') }}
</label> </label>
<div> <div>
<select id="schedulerEnd" <select id="schedulerEnd"
@@ -464,7 +464,7 @@
ng-if="schedulerEnd && schedulerEnd.value == 'after'"> ng-if="schedulerEnd && schedulerEnd.value == 'after'">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
Occurrence(s) {{ strings.get('form.OCCURENCES') }}
</label> </label>
<input <input
ng-name="schedulerOccurrenceCount" ng-name="schedulerOccurrenceCount"
@@ -481,14 +481,14 @@
<div class="error <div class="error
RepeatFrequencyOptions-error" RepeatFrequencyOptions-error"
ng-show="$parent.scheduler_occurrenceCount_error"> ng-show="$parent.scheduler_occurrenceCount_error">
Please provide a value between 1 and 999. {{ strings.get('form.REPEAT_FREQUENCY_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
<div class="form-group RepeatFrequencyOptions-formGroup" <div class="form-group RepeatFrequencyOptions-formGroup"
ng-if="schedulerEnd && schedulerEnd.value == 'on'"> ng-if="schedulerEnd && schedulerEnd.value == 'on'">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
End Date {{ strings.get('form.END_DATE') }}
</label> </label>
<div class="input-group Form-inputGroup SchedulerForm-inputGroup--date"> <div class="input-group Form-inputGroup SchedulerForm-inputGroup--date">
<scheduler-date-picker date="$parent.schedulerEndDt" <scheduler-date-picker date="$parent.schedulerEndDt"
@@ -497,14 +497,14 @@
</div> </div>
<div class="error" <div class="error"
ng-show="$parent.scheduler_endDt_error"> ng-show="$parent.scheduler_endDt_error">
Please provide a valid date. {{ strings.get('form.PROVIDE_VALID_DATE') }}
</div> </div>
</div> </div>
<div class="form-group SchedulerForm-formGroup" <div class="form-group SchedulerForm-formGroup"
ng-if="schedulerEnd && schedulerEnd.value == 'on'"> ng-if="schedulerEnd && schedulerEnd.value == 'on'">
<label class="Form-inputLabel"> <label class="Form-inputLabel">
<span class="red-text">*</span> <span class="red-text">*</span>
End Time {{ strings.get('form.END_TIME') }}
<span class="fmt-help" <span class="fmt-help"
ng-show="schedulerShowTimeZone"> ng-show="schedulerShowTimeZone">
(HH24:MM:SS) (HH24:MM:SS)
@@ -562,7 +562,7 @@
</div> </div>
<div class="error" <div class="error"
ng-show="scheduler_startTime_error"> ng-show="scheduler_startTime_error">
The time must be in HH24:MM:SS format. {{ strings.get('form.START_TIME_ERROR_MESSAGE') }}
</div> </div>
</div> </div>
</div> </div>
@@ -574,13 +574,13 @@
SchedulerFormDetail-container--error" SchedulerFormDetail-container--error"
ng-show="(preview_list.isEmpty && scheduler_form.$dirty) || (!schedulerIsValid && scheduler_form.$dirty)"> ng-show="(preview_list.isEmpty && scheduler_form.$dirty) || (!schedulerIsValid && scheduler_form.$dirty)">
<p class="SchedulerFormDetail-errorText"> <p class="SchedulerFormDetail-errorText">
The scheduler options are invalid, incomplete, or a date is in the past. {{ strings.get('form.SCHEDULER_OPTIONS_ARE_INVALID') }}
</p> </p>
</div> </div>
<div class="SchedulerFormDetail-container" <div class="SchedulerFormDetail-container"
ng-show="schedulerIsValid && !preview_list.isEmpty"> ng-show="schedulerIsValid && !preview_list.isEmpty">
<label class="SchedulerFormDetail-label"> <label class="SchedulerFormDetail-label">
Schedule Description {{ strings.get('form.SCHEDULE_DESCRIPTION') }}
</label> </label>
<div class="SchedulerFormDetail-nlp" ng-hide="rrule_nlp_description == 'Natural language description not available' "> <div class="SchedulerFormDetail-nlp" ng-hide="rrule_nlp_description == 'Natural language description not available' ">
{{ rrule_nlp_description }} {{ rrule_nlp_description }}
@@ -588,17 +588,17 @@
<div class="SchedulerFormDetail-occurrenceHeader"> <div class="SchedulerFormDetail-occurrenceHeader">
<label class="SchedulerFormDetail-label <label class="SchedulerFormDetail-label
SchedulerFormDetail-labelOccurrence"> SchedulerFormDetail-labelOccurrence">
Occurrences {{ strings.get('form.OCCURENCES') }}
<span <span
class="SchedulerFormDetail-labelDetail"> class="SchedulerFormDetail-labelDetail">
(Limited to first 10) ({{ strings.get('form.LIMITED_TO_FIRST_TEN') }})
</span> </span>
</label> </label>
<div id="date-choice" <div id="date-choice"
class="SchedulerFormDetail-dateFormats"> class="SchedulerFormDetail-dateFormats">
<label <label
class="SchedulerFormDetail-dateFormatsLabel"> class="SchedulerFormDetail-dateFormatsLabel">
Date format {{ strings.get('form.DATE_FORMAT') }}
</label> </label>
<label class="radio-inline <label class="radio-inline
SchedulerFormDetail-radioLabel"> SchedulerFormDetail-radioLabel">
@@ -607,7 +607,7 @@
ng-model="dateChoice" ng-model="dateChoice"
id="date-choice-local" id="date-choice-local"
value="local" > value="local" >
Local Time Zone {{ strings.get('form.LOCAL_TIME_ZONE') }}
</label> </label>
<label class="radio-inline <label class="radio-inline
SchedulerFormDetail-radioLabel"> SchedulerFormDetail-radioLabel">
@@ -639,7 +639,7 @@
<div class="form-group Form-formGroup Form-textAreaLabel Form-formGroup--fullWidth" ng-hide="noVars"> <div class="form-group Form-formGroup Form-textAreaLabel Form-formGroup--fullWidth" ng-hide="noVars">
<label for="Scheduler-extraVars"> <label for="Scheduler-extraVars">
<span class="Form-inputLabel"> <span class="Form-inputLabel">
Extra Variables {{ strings.get('form.EXTRA_VARIABLES') }}
</span> </span>
<!-- tooltip --> <!-- tooltip -->
<a aw-pop-over="<p>Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.</p>JSON:<br /> <a aw-pop-over="<p>Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.</p>JSON:<br />
@@ -666,24 +666,25 @@
class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin"
id="schedule_prompt_btn" id="schedule_prompt_btn"
ng-show="showPromptButton" ng-show="showPromptButton"
ng-click="prompt()">Prompt</button> ng-click="prompt()">{{ strings.get('form.PROMPT') }}</button>
<button type="button" <button type="button"
class="btn btn-sm Form-cancelButton" class="btn btn-sm Form-cancelButton"
id="schedule_cancel_btn" id="schedule_cancel_btn"
ng-show="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword" ng-show="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd) || credentialRequiresPassword"
ng-click="formCancel()">Close</button> ng-click="formCancel()">{{ strings.get('form.CLOSE') }}</button>
<button type="button" <button type="button"
class="btn btn-sm Form-cancelButton" class="btn btn-sm Form-cancelButton"
id="schedule_cancel_btn" id="schedule_cancel_btn"
ng-show="(schedule_obj.summary_fields.user_capabilities.edit || canAdd) && !credentialRequiresPassword" ng-show="(schedule_obj.summary_fields.user_capabilities.edit || canAdd) && !credentialRequiresPassword"
ng-click="formCancel()">Cancel</button> ng-click="formCancel()">{{ strings.get('form.CANCEL') }}</button>
<div class="SchedulerForm-promptSave" ng-show="(schedule_obj.summary_fields.user_capabilities.edit || canAdd) && !credentialRequiresPassword"> <div class="SchedulerForm-promptSave" ng-show="(schedule_obj.summary_fields.user_capabilities.edit || canAdd) && !credentialRequiresPassword">
<div ng-if="promptModalMissingReqFields" class="SchedulerForm-promptSaveTooltip" aw-tool-tip="Additional information required in the Prompt area before saving" data-placement="top"></div> <div ng-if="promptModalMissingReqFields" class="SchedulerForm-promptSaveTooltip" aw-tool-tip="Additional information required in the Prompt area before saving" data-placement="top"></div>
<button type="button" <button type="button"
class="btn btn-sm Form-saveButton" class="btn btn-sm Form-saveButton"
id="schedule_save_btn" id="schedule_save_btn"
ng-click="saveSchedule()" ng-click="saveSchedule()"
ng-disabled="!schedulerIsValid || promptModalMissingReqFields || (preview_list.isEmpty && scheduler_form.$dirty) || credentialRequiresPassword"> Save</button> ng-disabled="!schedulerIsValid || promptModalMissingReqFields || (preview_list.isEmpty && scheduler_form.$dirty) || credentialRequiresPassword"> {{ strings.get('form.SAVE') }}</button>
</div> </div>
</div> </div>
<prompt prompt-data="promptData" prevent-creds-with-passwords="preventCredsWithPasswords" action-text="{{:: strings.get('prompt.CONFIRM')}}" read-only-prompts="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd)"></prompt> <prompt prompt-data="promptData" prevent-creds-with-passwords="preventCredsWithPasswords" action-text="{{:: strings.get('prompt.CONFIRM')}}" read-only-prompts="!(schedule_obj.summary_fields.user_capabilities.edit || canAdd)"></prompt>

View File

@@ -1,4 +1,4 @@
export default ['templateUrl', function(templateUrl) { export default ['templateUrl', 'i18n', function(templateUrl, i18n) {
return { return {
restrict: 'E', restrict: 'E',
replace: true, replace: true,
@@ -55,8 +55,8 @@ export default ['templateUrl', function(templateUrl) {
$scope.$watch(list.name, function(){ $scope.$watch(list.name, function(){
selectRowIfPresent(); selectRowIfPresent();
}); });
let resource = list.iterator.replace(/_/g, ' ');
$scope.modalTitle = list.iterator.replace(/_/g, ' '); $scope.modalTitle = i18n._('Select') + ' ' + i18n._(resource);
listeners = eventService.addListeners([ listeners = eventService.addListeners([
[window, 'click', clickToHide] [window, 'click', clickToHide]

View File

@@ -2,7 +2,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header Form-header"> <div class="modal-header Form-header">
<div class="Form-title Form-title--uppercase">Select {{modalTitle}}</div> <div class="Form-title Form-title--uppercase">{{modalTitle}}</div>
<!-- optional: transclude header fields --> <!-- optional: transclude header fields -->
<div class="Form-header--fields"></div> <div class="Form-header--fields"></div>
<div class="Form-exitHolder"> <div class="Form-exitHolder">
@@ -16,8 +16,8 @@
<!-- see: lookup-modal.directive.js --> <!-- see: lookup-modal.directive.js -->
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button ng-click="cancelForm()" class="Lookup-cancel btn btn-default">Cancel</button> <button ng-click="cancelForm()" class="Lookup-cancel btn btn-default" translate>Cancel</button>
<button ng-click="saveForm()" class="Lookup-save btn btn-primary" ng-disabled="!currentSelection || !currentSelection.id" ng-bind="list.lookupConfirmText ? list.lookupConfirmText : 'Select'"></button> <button ng-click="saveForm()" class="Lookup-save btn btn-primary" ng-disabled="!currentSelection || !currentSelection.id" translate>Select</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,8 +4,8 @@
* All Rights Reserved * All Rights Reserved
*************************************************/ *************************************************/
export default ['$scope', '$filter', export default ['$scope', '$filter', 'i18n',
function ($scope, $filter) { function ($scope, $filter, i18n) {
function isFailureState(status) { function isFailureState(status) {
return status === 'failed' || status === 'error' || status === 'canceled'; return status === 'failed' || status === 'error' || status === 'canceled';
@@ -40,7 +40,7 @@ export default ['$scope', '$filter',
jobId: job.id, jobId: job.id,
sortDate: job.finished || "running" + job.id, sortDate: job.finished || "running" + job.id,
finished: finished, finished: finished,
status_tip: "JOB ID: " + job.id + "<br>STATUS: " + job.status.toUpperCase() + "<br>FINISHED: " + finished, status_tip: `${i18n._('JOB ID')}: ${job.id} <br>${i18n._('STATUS')}: ${job.status.toUpperCase()} <br>${i18n._('FINISHED')}: ${finished}`,
detailsUrl: detailsBaseUrl + job.id detailsUrl: detailsBaseUrl + job.id
}; };

View File

@@ -200,18 +200,17 @@
var msg; var msg;
switch (data.status) { switch (data.status) {
case 'failed': case 'failed':
msg = "<div>The Project selected has a status of \"failed\". You must run a successful update before you can select a playbook. You will not be able to save this Job Template without a valid playbook."; msg = `<div>${i18n._('The Project selected has a status of')} \"${i18n._('failed')}\". ${i18n._('You must run a successful update before you can select a playbook. You will not be able to save this Job Template without a valid playbook.')}</div>`;
break; break;
case 'never updated': case 'never updated':
msg = "<div>The Project selected has a status of \"never updated\". You must run a successful update before you can select a playbook. You will not be able to save this Job Template without a valid playbook."; msg = `<div>${i18n._('The Project selected has a status of')} \"${i18n._('never updated')}\". ${i18n._('You must run a successful update before you can select a playbook. You will not be able to save this Job Template without a valid playbook.')}</div>`;
break; break;
case 'missing': case 'missing':
msg = '<div>The selected project has a status of \"missing\". Please check the server and make sure ' + msg = `<div>${i18n._('The selected project has a status of')} \"${i18n._('missing')}\". ${i18n._('Please check the server and make sure the directory exists and file permissions are set correctly.')}</div>`;
' the directory exists and file permissions are set correctly.</div>';
break; break;
} }
if (msg) { if (msg) {
Alert('Warning', msg, 'alert-info alert-info--noTextTransform', null, null, null, null, true); Alert(i18n._('Warning'), msg, 'alert-info alert-info--noTextTransform', null, null, null, null, true);
} }
}) })
.catch(({data, status}) => { .catch(({data, status}) => {

View File

@@ -273,7 +273,7 @@ export default ['i18n', function(i18n){
'<div>'+ '<div>'+
'<div class="input-group">'+ '<div class="input-group">'+
'<span class="input-group-btn">'+ '<span class="input-group-btn">'+
'<button type="button" class="btn btn-default show_input_button" id="default_password_show_input_button" aw-tool-tip="Toggle the display of plaintext." aw-tip-placement="top" ng-click="toggleInput(&quot;#default_password&quot;)" data-container="#survey-modal-dialog" data-original-title="" title="">SHOW</button>'+ '<button type="button" class="btn btn-default show_input_button" id="default_password_show_input_button" aw-tool-tip="Toggle the display of plaintext." aw-tip-placement="top" ng-click="toggleInput(&quot;#default_password&quot;)" data-container="#survey-modal-dialog" data-original-title="" title="" translate>SHOW</button>'+
'</span>'+ '</span>'+
'<input id="default_password" type="password" ng-model="default_password" name="default_password" class="form-control Form-textInput" autocomplete="false">'+ '<input id="default_password" type="password" ng-model="default_password" name="default_password" class="form-control Form-textInput" autocomplete="false">'+
'</div>'+ '</div>'+

View File

@@ -1,6 +1,6 @@
export default export default
function Init(DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert, function Init(DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert,
GetBasePath, Rest, ProcessErrors, EditQuestion, CreateSelect2) { GetBasePath, Rest, ProcessErrors, EditQuestion, CreateSelect2, i18n) {
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
id = params.id, id = params.id,
@@ -10,14 +10,18 @@ export default
scope.sce = sce; scope.sce = sce;
scope.survey_questions = []; scope.survey_questions = [];
scope.answer_types=[ scope.answer_types=[
{name: 'Text' , type: 'text'}, {name: i18n._('Text'), type: 'text'},
{name: 'Textarea', type: 'textarea'}, {name: i18n._('Textarea'), type: 'textarea'},
{name: 'Password', type: 'password'}, {name: i18n._('Password'), type: 'password'},
{name: 'Multiple Choice (single select)', type: 'multiplechoice'}, {name: i18n._('Multiple Choice (single select)'), type: 'multiplechoice'},
{name: 'Multiple Choice (multiple select)', type: 'multiselect'}, {name: i18n._('Multiple Choice (multiple select)'), type: 'multiselect'},
{name: 'Integer', type: 'integer'}, {name: i18n._('Integer'), type: 'integer'},
{name: 'Float', type: 'float'} {name: i18n._('Float'), type: 'float'}
]; ];
scope.disableSurveyTooltip = i18n._('Disble Survey');
scope.editQuestionTooltip = i18n._('Edit Question');
scope.deleteQuestionTooltip = i18n._('Delete Question');
scope.dragQuestionTooltip = i18n._('Drag to reorder question');
/* SURVEY RELATED FUNCTIONS */ /* SURVEY RELATED FUNCTIONS */
@@ -476,10 +480,10 @@ export default
inputId = id, inputId = id,
buttonInnerHTML = $(buttonId).html(); buttonInnerHTML = $(buttonId).html();
if (buttonInnerHTML.indexOf("SHOW") > -1) { if (buttonInnerHTML.indexOf("SHOW") > -1) {
$(buttonId).html("HIDE"); $(buttonId).html(i18n._("HIDE"));
$(inputId).attr("type", "text"); $(inputId).attr("type", "text");
} else { } else {
$(buttonId).html("SHOW"); $(buttonId).html(i18n._("SHOW"));
$(inputId).attr("type", "password"); $(inputId).attr("type", "password");
} }
}; };
@@ -511,7 +515,7 @@ export default
// Watcher that updates the survey enabled/disabled tooltip based on scope.survey_enabled // Watcher that updates the survey enabled/disabled tooltip based on scope.survey_enabled
scope.$watch('survey_enabled', function(newVal) { scope.$watch('survey_enabled', function(newVal) {
scope.surveyEnabledTooltip = (newVal) ? "Disable survey" : "Enable survey"; scope.surveyEnabledTooltip = (newVal) ? i18n._("Disable survey") : i18n._("Enable survey");
}); });
}; };
@@ -529,5 +533,6 @@ Init.$inject =
'Rest', 'Rest',
'ProcessErrors', 'ProcessErrors',
'editQuestion', 'editQuestion',
'CreateSelect2' 'CreateSelect2',
'i18n'
]; ];

View File

@@ -4,8 +4,8 @@
* All Rights Reserved * All Rights Reserved
*************************************************/ *************************************************/
export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'GetBasePath', 'ProcessErrors', export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'GetBasePath', 'ProcessErrors', 'TemplatesStrings',
function($state, moment, $timeout, $window, $filter, Rest, GetBasePath, ProcessErrors) { function($state, moment, $timeout, $window, $filter, Rest, GetBasePath, ProcessErrors, TemplatesStrings) {
return { return {
scope: { scope: {
@@ -280,7 +280,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("y", 30) .attr("y", 30)
.attr("dy", ".35em") .attr("dy", ".35em")
.attr("class", "WorkflowChart-startText") .attr("class", "WorkflowChart-startText")
.text(function () { return "START"; }) .text(function () { return TemplatesStrings.get('workflow_maker.START'); })
.call(add_node); .call(add_node);
} }
else { else {
@@ -333,7 +333,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.style("font-size","0.7em") .style("font-size","0.7em")
.attr("class", "WorkflowChart-conflictText") .attr("class", "WorkflowChart-conflictText")
.html(function () { .html(function () {
return "<span class=\"WorkflowChart-conflictIcon\">\uf06a</span><span> EDGE CONFLICT</span>"; return `<span class=\"WorkflowChart-conflictIcon\">\uf06a</span><span> ${TemplatesStrings.get('workflow_maker.EDGE_CONFLICT')}</span>`;
}) })
.style("display", function(d) { return (d.edgeConflict && !d.placeholder) ? null : "none"; }); .style("display", function(d) { return (d.edgeConflict && !d.placeholder) ? null : "none"; });
@@ -344,7 +344,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("class", "WorkflowChart-defaultText WorkflowChart-deletedText") .attr("class", "WorkflowChart-defaultText WorkflowChart-deletedText")
.html(function () { .html(function () {
return "<span>DELETED</span>"; return `<span>${TemplatesStrings.get('workflow_maker.DELETED')}</span>`;
}) })
.style("display", function(d) { return d.unifiedJobTemplate || d.placeholder ? "none" : null; }); .style("display", function(d) { return d.unifiedJobTemplate || d.placeholder ? "none" : null; });
@@ -423,7 +423,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("class", "WorkflowChart-detailsLink") .attr("class", "WorkflowChart-detailsLink")
.style("display", function(d){ return d.job && d.job.status && d.job.id ? null : "none"; }) .style("display", function(d){ return d.job && d.job.status && d.job.id ? null : "none"; })
.text(function () { .text(function () {
return "DETAILS"; return TemplatesStrings.get('workflow_maker.DETAILS');
}) })
.call(details); .call(details);
thisNode.append("circle") thisNode.append("circle")

View File

@@ -23,10 +23,10 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}; };
$scope.job_type_options = [{ $scope.job_type_options = [{
label: "Run", label: $scope.strings.get('workflow_maker.RUN'),
value: "run" value: "run"
}, { }, {
label: "Check", label: $scope.strings.get('workflow_maker.CHECK'),
value: "check" value: "check"
}]; }];
@@ -36,15 +36,15 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.edgeTypeOptions = [ $scope.edgeTypeOptions = [
{ {
label: 'Always', label: $scope.strings.get('workflow_maker.ALWAYS'),
value: 'always' value: 'always'
}, },
{ {
label: 'On Success', label: $scope.strings.get('workflow_maker.ON_SUCCESS'),
value: 'success' value: 'success'
}, },
{ {
label: 'On Failure', label: $scope.strings.get('workflow_maker.ON_FAILURE'),
value: 'failure' value: 'failure'
} }
]; ];
@@ -318,17 +318,17 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
optionsToInclude.forEach((optionToInclude) => { optionsToInclude.forEach((optionToInclude) => {
if (optionToInclude === "always") { if (optionToInclude === "always") {
$scope.edgeTypeOptions.push({ $scope.edgeTypeOptions.push({
label: 'Always', label: $scope.strings.get('workflow_maker.ALWAYS'),
value: 'always' value: 'always'
}); });
} else if (optionToInclude === "success") { } else if (optionToInclude === "success") {
$scope.edgeTypeOptions.push({ $scope.edgeTypeOptions.push({
label: 'On Success', label: $scope.strings.get('workflow_maker.ON_SUCCESS'),
value: 'success' value: 'success'
}); });
} else if (optionToInclude === "failure") { } else if (optionToInclude === "failure") {
$scope.edgeTypeOptions.push({ $scope.edgeTypeOptions.push({
label: 'On Failure', label: $scope.strings.get('workflow_maker.ON_FAILURE'),
value: 'failure' value: 'failure'
}); });
} }
@@ -486,20 +486,20 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}); });
// Set the default to success // Set the default to success
let edgeType = {label: "On Success", value: "success"}; let edgeType = {label: $scope.strings.get('workflow_maker.ON_SUCCESS'), value: "success"};
if (parent && ((betweenTwoNodes && parent.source.isStartNode) || (!betweenTwoNodes && parent.isStartNode))) { if (parent && ((betweenTwoNodes && parent.source.isStartNode) || (!betweenTwoNodes && parent.isStartNode))) {
// We don't want to give the user the option to select // We don't want to give the user the option to select
// a type as this node will always be executed // a type as this node will always be executed
updateEdgeDropdownOptions(["always"]); updateEdgeDropdownOptions(["always"]);
edgeType = {label: "Always", value: "always"}; edgeType = {label: $scope.strings.get('workflow_maker.ALWAYS'), value: "always"};
} else { } else {
if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) { if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
updateEdgeDropdownOptions(["success", "failure"]); updateEdgeDropdownOptions(["success", "failure"]);
edgeType = {label: "On Success", value: "success"}; edgeType = {label: $scope.strings.get('workflow_maker.ON_SUCCESS'), value: "success"};
} else if (_.includes(siblingConnectionTypes, "always")) { } else if (_.includes(siblingConnectionTypes, "always")) {
updateEdgeDropdownOptions(["always"]); updateEdgeDropdownOptions(["always"]);
edgeType = {label: "Always", value: "always"}; edgeType = {label: $scope.strings.get('workflow_maker.ALWAYS'), value: "always"};
} else { } else {
updateEdgeDropdownOptions(); updateEdgeDropdownOptions();
} }

View File

@@ -4,7 +4,7 @@
<div class="Modal-content modal-content"> <div class="Modal-content modal-content">
<div class="Modal-header"> <div class="Modal-header">
<div class="Modal-title"> <div class="Modal-title">
<span>DELETE</span> <span>{{strings.get('DELETE')}}</span>
<span class="Modal-titleResourceName" ng-bind="nodeToBeDeleted.unifiedJobTemplate.name"></span> <span class="Modal-titleResourceName" ng-bind="nodeToBeDeleted.unifiedJobTemplate.name"></span>
</div> </div>
<div class="Modal-exitHolder"> <div class="Modal-exitHolder">
@@ -14,11 +14,11 @@
</div> </div>
</div> </div>
<div class="Modal-body ng-binding"> <div class="Modal-body ng-binding">
<div class="Prompt-bodyQuery">Are you sure you want to delete this workflow node?</div> <div class="Prompt-bodyQuery">{{strings.get('workflow_maker.DELETE_NODE_PROMPT_TEXT')}}</div>
</div> </div>
<div class="Modal-footer"> <div class="Modal-footer">
<button ng-click="cancelDeleteNode()" class="btn Modal-defaultButton Modal-footerButton">CANCEL</a> <button ng-click="cancelDeleteNode()" class="btn Modal-defaultButton Modal-footerButton">{{strings.get('CANCEL')}}</a>
<button ng-click="confirmDeleteNode()" class="btn Modal-footerButton ng-binding Modal-errorButton">DELETE</a> <button ng-click="confirmDeleteNode()" class="btn Modal-footerButton ng-binding Modal-errorButton">{{strings.get('DELETE')}}</a>
</div> </div>
</div> </div>
</div> </div>
@@ -40,36 +40,36 @@
<i ng-class="{{ keyClassList }}" class="fa fa-key Key-menuIcon" ng-click="toggleKey()"></i> <i ng-class="{{ keyClassList }}" class="fa fa-key Key-menuIcon" ng-click="toggleKey()"></i>
<ul ng-show="showKey" class="Key-list noselect"> <ul ng-show="showKey" class="Key-list noselect">
<li class="Key-listItem"> <li class="Key-listItem">
<p class="Key-heading">KEY</p> <p class="Key-heading">{{strings.get('workflow_maker.KEY')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--success"></div> <div class="Key-icon Key-icon--success"></div>
<p class="Key-listItemContent">On Success</p> <p class="Key-listItemContent">{{strings.get('workflow_maker.ON_SUCCESS')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--fail"></div> <div class="Key-icon Key-icon--fail"></div>
<p class="Key-listItemContent">On Fail</p> <p class="Key-listItemContent">{{strings.get('workflow_maker.ON_FAILURE')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--always"></div> <div class="Key-icon Key-icon--always"></div>
<p class="Key-listItemContent">Always</p> <p class="Key-listItemContent">{{strings.get('workflow_maker.ALWAYS')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--circle Key-icon--default">P</div> <div class="Key-icon Key-icon--circle Key-icon--default">P</div>
<p class="Key-listItemContent Key-listItemContent--circle">Project Sync</p> <p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.PROJECT_SYNC')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--circle Key-icon--default">I</div> <div class="Key-icon Key-icon--circle Key-icon--default">I</div>
<p class="Key-listItemContent Key-listItemContent--circle">Inventory Sync</p> <p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.INVENTORY_SYNC')}}</p>
</li> </li>
<li class="Key-listItem"> <li class="Key-listItem">
<div class="Key-icon Key-icon--circle Key-icon--warning">!</div> <div class="Key-icon Key-icon--circle Key-icon--warning">!</div>
<p class="Key-listItemContent Key-listItemContent--circle">Warning</p> <p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.WARNING')}}</p>
</li> </li>
</ul> </ul>
</div> </div>
<div class="WorkflowLegend-maker--right"> <div class="WorkflowLegend-maker--right">
<span class="WorkflowMaker-totalJobs">TOTAL TEMPLATES</span> <span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
<span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span> <span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span>
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i> <i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect"> <div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
@@ -80,13 +80,13 @@
<workflow-chart ng-if="modalOpen" tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" workflow-zoomed="workflowZoomed(zoom)" can-add-workflow-job-template="canAddWorkflowJobTemplate" workflow-job-template-obj="workflowJobTemplateObj" mode="edit" class="WorkflowMaker-chart"></workflow-chart> <workflow-chart ng-if="modalOpen" tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" workflow-zoomed="workflowZoomed(zoom)" can-add-workflow-job-template="canAddWorkflowJobTemplate" workflow-job-template-obj="workflowJobTemplateObj" mode="edit" class="WorkflowMaker-chart"></workflow-chart>
</div> </div>
<div class="WorkflowMaker-contentRight"> <div class="WorkflowMaker-contentRight">
<div class="WorkflowMaker-formTitle">{{(workflowMakerFormConfig.nodeMode === 'edit' && nodeBeingEdited) ? ((nodeBeingEdited.unifiedJobTemplate && nodeBeingEdited.unifiedJobTemplate.name) ? nodeBeingEdited.unifiedJobTemplate.name : "EDIT TEMPLATE") : "ADD A TEMPLATE"}}</div> <div class="WorkflowMaker-formTitle">{{(workflowMakerFormConfig.nodeMode === 'edit' && nodeBeingEdited) ? ((nodeBeingEdited.unifiedJobTemplate && nodeBeingEdited.unifiedJobTemplate.name) ? nodeBeingEdited.unifiedJobTemplate.name : strings.get('workflow_maker.EDIT_TEMPLATE')) : strings.get('workflow_maker.ADD_A_TEMPLATE')}}</div>
<div class="WorkflowMaker-formHelp" ng-show="workflowMakerFormConfig.nodeMode === 'idle'" ng-bind="treeData.data.totalNodes === 0 ? 'Please click the start button to build your workflow.' : 'Please hover over a template for additional options.'"></div> <div class="WorkflowMaker-formHelp" ng-show="workflowMakerFormConfig.nodeMode === 'idle'" ng-bind="treeData.data.totalNodes === 0 ? strings.get('workflow_maker.PLEASE_CLICK_THE_START_BUTTON') : strings.get('workflow_maker.PLEASE_HOVER_OVER_A_TEMPLATE')"></div>
<div class="WorkflowMaker-form" ng-show="workflowMakerFormConfig.nodeMode === 'add' || workflowMakerFormConfig.nodeMode === 'edit'"> <div class="WorkflowMaker-form" ng-show="workflowMakerFormConfig.nodeMode === 'add' || workflowMakerFormConfig.nodeMode === 'edit'">
<div class="Form-tabHolder"> <div class="Form-tabHolder">
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'jobs'}" ng-click="toggleFormTab('jobs')">JOBS</div> <div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'jobs'}" ng-click="toggleFormTab('jobs')">{{strings.get('workflow_maker.JOBS')}}</div>
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'project_sync'}" ng-click="toggleFormTab('project_sync')">PROJECT SYNC</div> <div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'project_sync'}" ng-click="toggleFormTab('project_sync')">{{strings.get('workflow_maker.PROJECT_SYNC')}}</div>
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'inventory_sync'}" ng-click="toggleFormTab('inventory_sync')">INVENTORY SYNC</div> <div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': workflowMakerFormConfig.activeTab === 'inventory_sync'}" ng-click="toggleFormTab('inventory_sync')">{{strings.get('workflow_maker.INVENTORY_SYNC')}}</div>
</div> </div>
<div class="WorkflowMaker-formLists"> <div class="WorkflowMaker-formLists">
<div id="workflow-jobs-list" ui-view="jobTemplateList" ng-show="workflowMakerFormConfig.activeTab === 'jobs'"></div> <div id="workflow-jobs-list" ui-view="jobTemplateList" ng-show="workflowMakerFormConfig.activeTab === 'jobs'"></div>
@@ -112,7 +112,7 @@
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="selectedTemplate && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)"> <div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="selectedTemplate && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)">
<label for="verbosity" class="Form-inputLabelContainer"> <label for="verbosity" class="Form-inputLabelContainer">
<span class="Form-requiredAsterisk">*</span> <span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel">RUN</span> <span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
</label> </label>
<div> <div>
<select <select
@@ -128,18 +128,18 @@
</div> </div>
</div> </div>
<div class="buttons Form-buttons" id="workflow_maker_controls"> <div class="buttons Form-buttons" id="workflow_maker_controls">
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="showPromptButton" ng-click="openPromptModal()"> Prompt</button> <button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="showPromptButton" ng-click="openPromptModal()"> {{:: strings.get('prompt.PROMPT') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Cancel</button> <button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> {{:: strings.get('CANCEL') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_btn" ng-show="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Close</button> <button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_btn" ng-show="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> {{:: strings.get('CLOSE') }}</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate) && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)" ng-click="confirmNodeForm()" ng-disabled="!selectedTemplate || promptModalMissingReqFields || credentialRequiresPassword"> Select</button> <button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate) && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)" ng-click="confirmNodeForm()" ng-disabled="!selectedTemplate || promptModalMissingReqFields || credentialRequiresPassword"> {{:: strings.get('workflow_maker.SELECT') }}</button>
</div> </div>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<div class="WorkflowMaker-buttonHolder"> <div class="WorkflowMaker-buttonHolder">
<button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> Close</button> <button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> {{:: strings.get('CLOSE') }}</button>
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate" ng-disabled="edgeFlags.conflict || workflowMakerFormConfig.nodeMode === 'add'"> Save</button> <button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate" ng-disabled="edgeFlags.conflict || workflowMakerFormConfig.nodeMode === 'add'"> {{:: strings.get('SAVE') }}</button>
</div> </div>
<prompt prompt-data="promptData" action-text="{{:: strings.get('prompt.CONFIRM')}}" prevent-creds-with-passwords="preventCredsWithPasswords" read-only-prompts="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)"></prompt> <prompt prompt-data="promptData" action-text="{{:: strings.get('prompt.CONFIRM')}}" prevent-creds-with-passwords="preventCredsWithPasswords" read-only-prompts="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)"></prompt>
</div> </div>

View File

@@ -20,11 +20,12 @@
.StandardOut-actionButton { .StandardOut-actionButton {
font-size: 16px; font-size: 16px;
height: 20px; height: 30px;
min-width: 30px; min-width: 30px;
color: @list-action-icon; color: @list-action-icon;
background-color: inherit; background-color: inherit;
border: none; border: none;
border-radius: 5px;
} }
.StandardOut-actionButton:hover { .StandardOut-actionButton:hover {

View File

@@ -49,9 +49,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
STARTED: i18n._('Started'), STARTED: i18n._('Started'),
FINISHED: i18n._('Finished'), FINISHED: i18n._('Finished'),
LABELS: i18n._('Labels'), LABELS: i18n._('Labels'),
STATUS: '', // re-assigned elsewhere STATUS: i18n._('Status')
JOB_TYPE: '', // re-assigned elsewhere
VERBOSITY: '', // re-assigned elsewhere
}, },
details: { details: {
HEADER: i18n._('DETAILS'), HEADER: i18n._('DETAILS'),
@@ -84,10 +82,8 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
} }
}; };
$scope.strings.labels.STATUS = getLabel('status'); $scope.workflow.statusLabel = i18n._(getLabel('status'));
$scope.strings.tooltips.STATUS = `Job ${$scope.strings.labels.STATUS}`; $scope.strings.tooltips.STATUS = `${i18n._('Job')} ${$scope.workflow.statusLabel}`;
$scope.strings.labels.JOB_TYPE = getLabel('job_type');
$scope.strings.labels.VERBOSITY = getLabel('verbosity');
}; };
var updateWorkflowJobElapsedTimer = function(time) { var updateWorkflowJobElapsedTimer = function(time) {

View File

@@ -65,13 +65,13 @@
<!-- STATUS DETAIL --> <!-- STATUS DETAIL -->
<div class="WorkflowResults-resultRow"> <div class="WorkflowResults-resultRow">
<label class="WorkflowResults-resultRowLabel"> <label class="WorkflowResults-resultRowLabel">
Status {{strings.labels.STATUS}}
</label> </label>
<div class="WorkflowResults-resultRowText"> <div class="WorkflowResults-resultRowText">
<i class="WorkflowResults-statusResultIcon <i class="WorkflowResults-statusResultIcon
fa fa
icon-job-{{ workflow.status }}"> icon-job-{{ workflow.status }}">
</i> {{ strings.labels.STATUS }} </i> {{ workflow.statusLabel }}
</div> </div>
</div> </div>