ui implementation of crud-based ui hiding

This commit is contained in:
John Mitchell 2016-09-02 11:31:18 -04:00
parent 6b0df43f3b
commit 6e653c29e0
44 changed files with 669 additions and 163 deletions

View File

@ -1,13 +1,13 @@
<div class="RoleList-tagContainer"
ng-repeat="entry in access_list">
<div class="RoleList-deleteContainer"
ng-if="entry.explicit"
ng-if="entry.explicit && entry.user_capabilities.unattach"
ng-click="deletePermission(permission, entry)">
<i ng-if="entry.explicit"
<i ng-if="entry.explicit && entry.user_capabilities.unattach"
class="fa fa-times RoleList-tagDelete"></i>
</div>
<div class="RoleList-tag"
ng-class="{'RoleList-tag--deletable': entry.explicit,
ng-class="{'RoleList-tag--deletable': entry.explicit && entry.user_capabilities.unattach,
'RoleList-tag--team': entry.team_id}"
aw-tool-tip='{{entry.team_name | sanitize}}' aw-tip-placement='bottom'>
<span class="RoleList-name">{{ entry.name }}</span>

View File

@ -840,6 +840,12 @@ var tower = angular.module('Tower', [
// If browser refresh, set the user_is_superuser value
$rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
$rootScope.user_is_system_auditor = Authorization.getUserInfo('is_system_auditor');
Rest.setUrl($rootScope.current_user.related.admin_of_organizations);
Rest.get()
.success(function(data) {
$rootScope.current_user_admin_orgs = data.results.map(i => i.name);
});
// state the user refreshes we want to open the socket, except if the user is on the login page, which should happen after the user logs in (see the AuthService module for that call to OpenSocket)
if (!_.contains($location.$$url, '/login')) {
ConfigService.getConfig().then(function() {

View File

@ -17,6 +17,18 @@ export function CredentialsList($scope, $rootScope, $location, $log,
SelectionInit, GetChoices, Wait, $state, $filter) {
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('credentials'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
Wait('start');
var list = CredentialList,
@ -139,6 +151,15 @@ export function CredentialsAdd($scope, $rootScope, $compile, $location, $log,
LookUpInit, OrganizationList, GetBasePath, GetChoices, Empty, KindChange,
OwnerChange, FormSave, $state, CreateSelect2) {
Rest.setUrl(GetBasePath('credentials'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add a credential.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view
@ -337,6 +358,7 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log,
}
ClearScope();
var defaultUrl = GetBasePath('credentials'),
generator = GenerateForm,
form = CredentialForm,
@ -344,6 +366,17 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log,
master = {},
id = $stateParams.credential_id,
relatedSets = {};
$scope.canEdit = false;
Rest.setUrl(GetBasePath('credentials') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();
$scope.id = id;

View File

@ -16,9 +16,20 @@ export function ProjectsList ($scope, $rootScope, $location, $log, $stateParams,
PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath,
SelectionInit, ProjectUpdate, Refresh, Wait, GetChoices, Empty,
Find, GetProjectIcon, GetProjectToolTip, $filter, $state) {
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('projects'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
Wait('start');
var list = ProjectList,
@ -379,6 +390,15 @@ export function ProjectsAdd(Refresh, $scope, $rootScope, $compile, $location, $l
OrganizationList, CredentialList, GetChoices, DebugForm, Wait, $state,
CreateSelect2) {
Rest.setUrl(GetBasePath('projects'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add a project.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view
@ -568,6 +588,16 @@ export function ProjectsEdit($scope, $rootScope, $compile, $location, $log,
id = $stateParams.id,
relatedSets = {};
$scope.canEdit = false;
Rest.setUrl(GetBasePath('projects') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
// remove "type" field from search options
CredentialList = _.cloneDeep(CredentialList);
CredentialList.fields.kind.noSearch = true;

View File

@ -15,9 +15,20 @@ export function TeamsList($scope, $rootScope, $location, $log, $stateParams,
Rest, Alert, TeamList, GenerateList, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath,
SelectionInit, Wait, $state, Refresh, $filter) {
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('teams'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
var list = TeamList,
defaultUrl = GetBasePath('teams'),
generator = GenerateList,
@ -137,6 +148,15 @@ export function TeamsAdd($scope, $rootScope, $compile, $location, $log,
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//$scope.
Rest.setUrl(GetBasePath('teams'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add a team.', 'alert-info');
}
});
// Inject dynamic view
var defaultUrl = GetBasePath('teams'),
form = TeamForm,
@ -206,6 +226,16 @@ export function TeamsEdit($scope, $rootScope, $location,
relatedSets = {},
set;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('teams') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
$scope.team_id = id;

View File

@ -35,9 +35,20 @@ export function UsersList($scope, $rootScope, $location, $log, $stateParams,
Rest, Alert, UserList, GenerateList, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit,
Wait, $state, Refresh, $filter) {
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('users'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
var list = UserList,
defaultUrl = GetBasePath('users'),
generator = GenerateList,
@ -148,6 +159,15 @@ export function UsersAdd($scope, $rootScope, $compile, $location, $log,
ReturnToCaller, ClearScope, GetBasePath, LookUpInit, OrganizationList,
ResetForm, Wait, CreateSelect2, $state) {
Rest.setUrl(GetBasePath('users'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add a user.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view
@ -272,6 +292,16 @@ export function UsersEdit($scope, $rootScope, $location,
relatedSets = {},
set;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('users') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();

View File

@ -32,13 +32,15 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
autocomplete: false
autocomplete: false,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
},
organization: {
addRequired: false,
@ -52,7 +54,8 @@ export default
awPopOver: "<p>If no organization is given, the credential can only be used by the user that creates the credential. Organization admins and system administrators can assign an organization so that roles for the credential can be assigned to users and teams in that organization.</p>",
dataTitle: 'Organization ',
dataPlacement: 'bottom',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
kind: {
label: 'Type',
@ -83,7 +86,8 @@ export default
dataTitle: 'Type',
dataPlacement: 'right',
dataContainer: "body",
hasSubForm: true
hasSubForm: true,
ngDisabled: '!canEdit'
},
access_key: {
label: 'Access Key',
@ -96,12 +100,13 @@ export default
autocomplete: false,
apiField: 'username',
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
secret_key: {
label: 'Secret Key',
type: 'sensitive',
ngShow: "kind.value == 'aws'",
ngDisabled: "secret_key_ask",
ngDisabled: "secret_key_ask || !canEdit",
awRequiredWhen: {
reqExpression: "aws_required",
init: false
@ -123,7 +128,8 @@ export default
dataTitle: 'STS Token',
dataPlacement: 'right',
dataContainer: "body",
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"host": {
labelBind: 'hostLabel',
@ -139,7 +145,8 @@ export default
reqExpression: 'host_required',
init: false
},
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"subscription": {
label: "Subscription ID",
@ -156,7 +163,8 @@ export default
dataTitle: 'Subscription ID',
dataPlacement: 'right',
dataContainer: "body",
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"username": {
labelBind: 'usernameLabel',
@ -168,7 +176,8 @@ export default
init: false
},
autocomplete: false,
subForm: "credentialSubForm"
subForm: "credentialSubForm",
ngDisabled: '!canEdit'
},
"email_address": {
labelBind: 'usernameLabel',
@ -183,7 +192,8 @@ export default
dataTitle: 'Email',
dataPlacement: 'right',
dataContainer: "body",
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"api_key": {
label: 'API Key',
@ -196,7 +206,8 @@ export default
autocomplete: false,
hasShowInputButton: true,
clear: false,
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"password": {
labelBind: 'passwordLabel',
@ -209,13 +220,14 @@ export default
reqExpression: "password_required",
init: false
},
subForm: "credentialSubForm"
subForm: "credentialSubForm",
ngDisabled: '!canEdit'
},
"ssh_password": {
label: 'Password',
type: 'sensitive',
ngShow: "kind.value == 'ssh'",
ngDisabled: "ssh_password_ask",
ngDisabled: "ssh_password_ask || !canEdit",
addRequired: false,
editRequired: false,
subCheckbox: {
@ -247,7 +259,8 @@ export default
dataTitle: 'Private Key',
dataPlacement: 'right',
dataContainer: "body",
subForm: "credentialSubForm"
subForm: "credentialSubForm",
ngDisabled: '!canEdit'
},
"ssh_key_unlock": {
label: 'Private Key Passphrase',
@ -255,7 +268,7 @@ export default
ngShow: "kind.value == 'ssh' || kind.value == 'scm'",
addRequired: false,
editRequired: false,
ngDisabled: "keyEntered === false || ssh_key_unlock_ask",
ngDisabled: "keyEntered === false || ssh_key_unlock_ask || !canEdit",
subCheckbox: {
variable: 'ssh_key_unlock_ask',
ngShow: "kind.value == 'ssh'",
@ -278,7 +291,8 @@ export default
"<code>sudo | su | pbrun | pfexec | runas</code> <br>(defaults to <code>sudo</code>)</p>",
dataPlacement: 'right',
dataContainer: "body",
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"become_username": {
labelBind: 'becomeUsernameLabel',
@ -287,13 +301,14 @@ export default
addRequired: false,
editRequired: false,
autocomplete: false,
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"become_password": {
labelBind: 'becomePasswordLabel',
type: 'sensitive',
ngShow: "(kind.value == 'ssh' && (become_method && become_method.value)) ",
ngDisabled: "become_password_ask",
ngDisabled: "become_password_ask || !canEdit",
addRequired: false,
editRequired: false,
subCheckbox: {
@ -309,7 +324,8 @@ export default
type: 'text',
label: 'Client ID',
subForm: 'credentialSubForm',
ngShow: "kind.value === 'azure_rm'"
ngShow: "kind.value === 'azure_rm'",
ngDisabled: '!canEdit'
},
secret:{
type: 'sensitive',
@ -317,20 +333,23 @@ export default
autocomplete: false,
label: 'Client Secret',
subForm: 'credentialSubForm',
ngShow: "kind.value === 'azure_rm'"
ngShow: "kind.value === 'azure_rm'",
ngDisabled: '!canEdit'
},
tenant: {
type: 'text',
label: 'Tenant ID',
subForm: 'credentialSubForm',
ngShow: "kind.value === 'azure_rm'"
ngShow: "kind.value === 'azure_rm'",
ngDisabled: '!canEdit'
},
authorize: {
label: 'Authorize',
type: 'checkbox',
ngChange: "toggleCallback('host_config_key')",
subForm: 'credentialSubForm',
ngShow: "kind.value === 'net'"
ngShow: "kind.value === 'net'",
ngDisabled: '!canEdit'
},
authorize_password: {
label: 'Authorize Password',
@ -339,6 +358,7 @@ export default
autocomplete: false,
subForm: 'credentialSubForm',
ngShow: "authorize && authorize !== 'false'",
ngDisabled: '!canEdit'
},
"project": {
labelBind: 'projectLabel',
@ -355,7 +375,8 @@ export default
reqExpression: 'project_required',
init: false
},
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"domain": {
labelBind: 'domainLabel',
@ -371,13 +392,14 @@ export default
dataContainer: "body",
addRequired: false,
editRequired: false,
subForm: 'credentialSubForm'
subForm: 'credentialSubForm',
ngDisabled: '!canEdit'
},
"vault_password": {
label: "Vault Password",
type: 'sensitive',
ngShow: "kind.value == 'ssh'",
ngDisabled: "vault_password_ask",
ngDisabled: "vault_password_ask || !canEdit",
addRequired: false,
editRequired: false,
subCheckbox: {
@ -394,11 +416,17 @@ export default
buttons: {
cancel: {
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
label: 'Save',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
ngDisabled: true,
ngShow: 'canEdit' //Disable when $pristine or $invalid, optional
}
},
@ -421,7 +449,8 @@ export default
label: 'Add',
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -26,14 +26,16 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
capitalize: false,
ngDisabled: '!canEdit'
},
inventory_description: {
realName: 'description',
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
},
organization: {
label: 'Organization',
@ -44,7 +46,8 @@ export default
awRequiredWhen: {
reqExpression: "organizationrequired",
init: "true"
}
},
ngDisabled: '!canEdit'
},
variables: {
label: 'Variables',
@ -63,17 +66,24 @@ export default
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataTitle: 'Inventory Variables',
dataPlacement: 'right',
dataContainer: 'body'
dataContainer: 'body',
ngDisabled: '!canEdit' // TODO: get working
}
},
buttons: {
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngHide: 'canEdit'
},
save: {
ngClick: 'formSave()',
ngDisabled: true
ngDisabled: true,
ngShow: 'canEdit'
}
},
@ -94,7 +104,8 @@ export default
label: 'Add',
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -27,14 +27,16 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
column: 1
column: 1,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
column: 1
column: 1,
ngDisabled: '!canEdit'
},
job_type: {
label: 'Job Type',
@ -56,7 +58,8 @@ export default
variable: 'ask_job_type_on_launch',
ngShow: "!job_type.value || job_type.value !== 'scan'",
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
inventory: {
label: 'Inventory',
@ -78,7 +81,8 @@ export default
variable: 'ask_inventory_on_launch',
ngShow: "!job_type.value || job_type.value !== 'scan'",
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
project: {
label: 'Project',
@ -100,12 +104,13 @@ export default
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!canEdit'
},
playbook: {
label: 'Playbook',
type:'select',
ngOptions: 'book for book in playbook_options track by book',
ngDisabled: "job_type.value === 'scan' && project_name === 'Default'",
ngDisabled: "(job_type.value === 'scan' && project_name === 'Default') || !canEdit",
id: 'playbook-select',
awRequiredWhen: {
reqExpression: "playbookrequired",
@ -138,7 +143,8 @@ export default
subCheckbox: {
variable: 'ask_credential_on_launch',
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
cloud_credential: {
label: 'Cloud Credential',
@ -153,7 +159,8 @@ export default
"running playbook, allowing provisioning into the cloud without manually passing parameters to the included modules.</p>",
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
network_credential: {
label: 'Network Credential',
@ -167,7 +174,8 @@ export default
awPopOver: "<p>Network credentials are used by Ansible networking modules to connect to and manage networking devices.</p>",
dataTitle: 'Network Credential',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
forks: {
label: 'Forks',
@ -186,7 +194,8 @@ export default
' target=\"_blank\">ansible configuration file</a>.</p>',
dataTitle: 'Forks',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit' // TODO: get working
},
limit: {
label: 'Limit',
@ -203,7 +212,8 @@ export default
subCheckbox: {
variable: 'ask_limit_on_launch',
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
verbosity: {
label: 'Verbosity',
@ -216,7 +226,8 @@ export default
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
job_tags: {
label: 'Job Tags',
@ -235,7 +246,8 @@ export default
subCheckbox: {
variable: 'ask_tags_on_launch',
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
skip_tags: {
label: 'Skip Tags',
@ -254,7 +266,8 @@ export default
subCheckbox: {
variable: 'ask_skip_tags_on_launch',
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit'
},
checkbox_group: {
label: 'Options',
@ -270,7 +283,8 @@ export default
dataPlacement: 'right',
dataTitle: 'Become Privilege Escalation',
dataContainer: "body",
labelClass: 'stack-inline'
labelClass: 'stack-inline',
ngDisabled: '!canEdit'
}, {
name: 'allow_callbacks',
label: 'Allow Provisioning Callbacks',
@ -284,7 +298,8 @@ export default
dataPlacement: 'right',
dataTitle: 'Allow Provisioning Callbacks',
dataContainer: "body",
labelClass: 'stack-inline'
labelClass: 'stack-inline',
ngDisabled: '!canEdit'
}]
},
callback_url: {
@ -299,7 +314,8 @@ export default
awPopOverWatch: "callback_help",
dataPlacement: 'top',
dataTitle: 'Provisioning Callback URL',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
host_config_key: {
label: 'Host Config Key',
@ -312,7 +328,8 @@ export default
awPopOverWatch: "callback_help",
dataPlacement: 'right',
dataTitle: "Host Config Key",
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit'
},
labels: {
label: 'Labels',
@ -325,7 +342,8 @@ export default
dataTitle: 'Labels',
dataPlacement: 'right',
awPopOver: "<p>Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs in the Tower display.</p>",
dataContainer: 'body'
dataContainer: 'body',
ngDisabled: '!canEdit'
},
variables: {
label: 'Extra Variables',
@ -348,14 +366,15 @@ export default
subCheckbox: {
variable: 'ask_variables_on_launch',
text: 'Prompt on launch'
}
},
ngDisabled: '!canEdit' // TODO: get working
}
},
buttons: { //for now always generates <button> tags
add_survey: {
ngClick: 'addSurvey()',
ngShow: 'job_type.value !== "scan" && !survey_exists',
ngShow: 'job_type.value !== "scan" && !survey_exists && canEdit',
awFeature: 'surveys',
awToolTip: 'Surveys allow users to be prompted at job launch with a series of questions related to the job. This allows for variables to be defined that affect the playbook run at time of launch.',
dataPlacement: 'top'
@ -363,14 +382,25 @@ export default
edit_survey: {
ngClick: 'editSurvey()',
awFeature: 'surveys',
ngShow: 'job_type.value !== "scan" && survey_exists'
ngShow: 'job_type.value !== "scan" && survey_exists && canEdit'
},
view_survey: {
ngClick: 'editSurvey()',
awFeature: 'surveys',
ngShow: 'job_type.value !== "scan" && survey_exists && !canEdit'
},
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: "job_templates_form.$invalid || can_edit!==true"//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
ngDisabled: "job_templates_form.$invalid || can_edit!==true",//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
ngShow: 'canEdit'
}
},
@ -394,7 +424,8 @@ export default
label: 'Add',
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -25,23 +25,31 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
capitalize: false,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
}
},
buttons: { //for now always generates <button> tags
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
ngDisabled: true,
ngShow: 'canEdit'
}
},
@ -62,7 +70,8 @@ export default
label: 'Add',
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -30,13 +30,15 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
capitalize: false,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
},
organization: {
label: 'Organization',
@ -50,7 +52,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
},
dataTitle: 'Organization',
dataContainer: 'body',
dataPlacement: 'right'
dataPlacement: 'right',
ngDisabled: '!canEdit'
},
scm_type: {
label: 'SCM Type',
@ -61,6 +64,7 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
addRequired: true,
editRequired: true,
hasSubForm: true,
ngDisabled: '!canEdit'
},
missing_path_alert: {
type: 'alertblock',
@ -82,7 +86,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
dataTitle: 'Project Base Path',
dataContainer: 'body',
dataPlacement: 'right'
dataPlacement: 'right',
ngDisabled: '!canEdit'
},
local_path: {
label: 'Playbook Directory',
@ -99,7 +104,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
dataTitle: 'Project Path',
dataContainer: 'body',
dataPlacement: 'right'
dataPlacement: 'right',
ngDisabled: '!canEdit'
},
scm_url: {
label: 'SCM URL',
@ -115,7 +121,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
awPopOver: "set in controllers/projects",
dataTitle: 'SCM URL',
dataContainer: 'body',
dataPlacement: 'right'
dataPlacement: 'right',
ngDisabled: '!canEdit'
},
scm_branch: {
labelBind: "scmBranchLabel",
@ -123,7 +130,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
ngShow: "scm_type && scm_type.value !== 'manual'",
addRequired: false,
editRequired: false,
subForm: 'sourceSubForm'
subForm: 'sourceSubForm',
ngDisabled: '!canEdit'
},
credential: {
label: 'SCM Credential',
@ -134,7 +142,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false,
subForm: 'sourceSubForm'
subForm: 'sourceSubForm',
ngDisabled: '!canEdit'
},
checkbox_group: {
label: 'SCM Update Options',
@ -151,7 +160,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
dataTitle: 'SCM Clean',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options stack-inline'
labelClass: 'checkbox-options stack-inline',
ngDisabled: '!canEdit'
}, {
name: 'scm_delete_on_update',
label: 'Delete on Update',
@ -163,7 +173,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
dataTitle: 'SCM Delete',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options stack-inline'
labelClass: 'checkbox-options stack-inline',
ngDisabled: '!canEdit'
}, {
name: 'scm_update_on_launch',
label: 'Update on Launch',
@ -174,7 +185,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
dataTitle: 'SCM Update',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options stack-inline'
labelClass: 'checkbox-options stack-inline',
ngDisabled: '!canEdit'
}]
},
scm_update_cache_timeout: {
@ -193,17 +205,24 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
'and a new project update will be performed.</p>',
dataTitle: 'Cache Timeout',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!canEdit' // TODO: get working
}
},
buttons: {
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()',
ngDisabled: true
ngDisabled: true,
ngShow: 'canEdit'
}
},
@ -224,7 +243,8 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
label: 'Add',
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -25,13 +25,15 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
capitalize: false,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
},
organization: {
label: 'Organization',
@ -44,17 +46,24 @@ export default
awRequiredWhen: {
reqExpression: "orgrequired",
init: true
}
},
ngDisabled: '!canEdit'
}
},
buttons: {
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()',
ngDisabled: true
ngDisabled: true,
ngShow: 'canEdit'
}
},
@ -75,7 +84,8 @@ export default
label: 'Add',
awToolTip: 'Add user to team',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canEdit'
}
},

View File

@ -26,21 +26,24 @@ export default
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
capitalize: true,
ngDisabled: '!canEdit'
},
last_name: {
label: 'Last Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
capitalize: true,
ngDisabled: '!canEdit'
},
email: {
label: 'Email',
type: 'email',
addRequired: true,
editRequired: true,
autocomplete: false
autocomplete: false,
ngDisabled: '!canEdit'
},
username: {
label: 'Username',
@ -49,7 +52,8 @@ export default
reqExpression: "not_ldap_user && external_account === null",
init: true
},
autocomplete: false
autocomplete: false,
ngDisabled: '!canEdit'
},
organization: {
label: 'Organization',
@ -63,7 +67,8 @@ export default
awRequiredWhen: {
reqExpression: "orgrequired",
init: true
}
},
ngDisabled: '!canEdit'
},
password: {
label: 'Password',
@ -74,7 +79,8 @@ export default
editRequired: false,
ngChange: "clearPWConfirm('password_confirm')",
autocomplete: false,
chkPass: true
chkPass: true,
ngDisabled: '!canEdit'
},
password_confirm: {
label: 'Confirm Password',
@ -85,7 +91,8 @@ export default
editRequired: false,
awPassMatch: true,
associated: 'password',
autocomplete: false
autocomplete: false,
ngDisabled: '!canEdit'
},
user_type: {
label: 'User Type',
@ -94,16 +101,23 @@ export default
disableChooseOption: true,
ngModel: 'user_type',
ngShow: 'current_user["is_superuser"]',
ngDisabled: '!canEdit'
},
},
buttons: {
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()',
ngDisabled: true
ngDisabled: true,
ngShow: 'canEdit'
}
},
@ -186,7 +200,8 @@ export default
label: 'Remove',
ngClick: 'deletePermissionFromUser(user_id, username, permission.name, permission.summary_fields.resource_name, permission.related.users)',
iconClass: 'fa fa-times',
awToolTip: 'Dissasociate permission from user'
awToolTip: 'Dissasociate permission from user',
ngShow: 'canEdit'
}
},
hideOnSuperuser: true

View File

@ -46,7 +46,7 @@ export default
function createField(onChange, onReady, fld) {
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
scope[fld + 'codeMirror'] = AngularCodeMirror();
scope[fld + 'codeMirror'] = AngularCodeMirror(readOnly);
scope[fld + 'codeMirror'].addModes(global.$AnsibleConfig.variable_edit_modes);
scope[fld + 'codeMirror'].showTextArea({
scope: scope,

View File

@ -3,7 +3,7 @@
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name helpers.function:ProjectPath
@ -47,11 +47,13 @@ export default
Rest.get()
.success(function (data) {
var opts = [], i;
for (i = 0; i < data.project_local_paths.length; i++) {
opts.push({
label: data.project_local_paths[i],
value: data.project_local_paths[i]
});
if (data.project_local_paths) {
for (i = 0; i < data.project_local_paths.length; i++) {
opts.push({
label: data.project_local_paths[i],
value: data.project_local_paths[i]
});
}
}
if (scope.local_path) {
// List only includes paths not assigned to projects, so add the

View File

@ -16,6 +16,15 @@ function InventoriesAdd($scope, $rootScope, $compile, $location, $log,
PaginateInit, LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON,
$state) {
Rest.setUrl(GetBasePath('inventory'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add an inventory.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view

View File

@ -17,7 +17,6 @@ function InventoriesEdit($scope, $rootScope, $compile, $location,
ParseVariableString, RelatedSearchInit, RelatedPaginateInit,
Prompt, InitiatePlaybookRun, CreateDialog, deleteJobTemplate, $state,
$filter) {
ClearScope();
// Inject dynamic view
@ -29,6 +28,16 @@ function InventoriesEdit($scope, $rootScope, $compile, $location,
fld, json_data, data,
relatedSets = {};
$scope.canEdit = false;
Rest.setUrl(GetBasePath('inventory') + inventory_id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
form.formLabelSize = null;
form.formFieldSize = null;
$scope.inventory_id = inventory_id;

View File

@ -16,6 +16,18 @@ function InventoriesList($scope, $rootScope, $location, $log,
ClearScope, ProcessErrors, GetBasePath, Wait,
Find, Empty, $state) {
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('inventory'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
var list = InventoryList,
defaultUrl = GetBasePath('inventory') + ($stateParams.status === 'sync-failed' ? '?not__inventory_sources_with_failures=0' : ''),
view = generateList,

View File

@ -8,13 +8,22 @@ export default
[ '$rootScope', 'pagination', '$compile','SchedulerInit', 'Rest', 'Wait',
'inventoryScriptsFormObject', 'ProcessErrors', 'GetBasePath', 'Empty',
'GenerateForm', 'SearchInit' , 'PaginateInit',
'LookUpInit', 'OrganizationList', '$scope', '$state',
'LookUpInit', 'OrganizationList', '$scope', '$state', 'Alert',
function(
$rootScope, pagination, $compile, SchedulerInit, Rest, Wait,
inventoryScriptsFormObject, ProcessErrors, GetBasePath, Empty,
GenerateForm, SearchInit, PaginateInit,
LookUpInit, OrganizationList, $scope, $state
LookUpInit, OrganizationList, $scope, $state, Alert
) {
Rest.setUrl(GetBasePath('inventory_scripts'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add an inventory script.', 'alert-info');
}
});
var scope = $scope,
generator = GenerateForm,
form = inventoryScriptsFormObject,

View File

@ -23,6 +23,17 @@ export default
master = {},
url = GetBasePath('inventory_scripts');
$scope.canEdit = false;
Rest.setUrl(GetBasePath('inventory_scripts') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
$scope.inventory_script = inventory_script;
generator.inject(form, {
mode: 'edit' ,

View File

@ -24,13 +24,15 @@ export default function() {
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
capitalize: false,
ngDisabled: '!canEdit'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
editRequired: false,
ngDisabled: '!canEdit'
},
organization: {
label: 'Organization',
@ -41,7 +43,8 @@ export default function() {
},
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()'
ngClick: 'lookUpOrganization()',
ngDisabled: '!canEdit'
},
script: {
label: 'Custom Script',
@ -64,10 +67,16 @@ export default function() {
buttons: { //for now always generates <button> tags
cancel: {
ngClick: 'formCancel()',
ngShow: 'canEdit'
},
close: {
ngClick: 'formCancel()',
ngShow: '!canEdit'
},
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: 'custom_inventory_form.$pristine || custom_inventory_form.$invalid || !canEdit' //Disable when $pristine or $invalid, optional
ngDisabled: 'custom_inventory_form.$pristine || custom_inventory_form.$invalid || !canEdit', //Disable when $pristine or $invalid, optional
ngShow: 'canEdit'
}
}
};

View File

@ -42,7 +42,8 @@ export default function(){
ngClick: 'addCustomInv()',
awToolTip: 'Create a new custom inventory',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canAdd'
}
},
@ -56,7 +57,16 @@ export default function(){
label: 'Edit',
"class": 'btn-sm',
awToolTip: 'Edit inventory script',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'inventory_script.summary_fields.user_capabilities.edit'
},
view: {
ngClick: "editCustomInv(inventory_script.id)",
label: 'View',
"class": 'btn-sm',
awToolTip: 'View inventory script',
dataPlacement: 'top',
ngShow: '!inventory_script.summary_fields.user_capabilities.edit'
},
"delete": {
ngClick: "deleteCustomInv(inventory_script.id, inventory_script.name)",
@ -64,7 +74,8 @@ export default function(){
label: 'Delete',
"class": 'btn-sm',
awToolTip: 'Delete inventory script',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'inventory_script.summary_fields.user_capabilities.delete'
}
}
};

View File

@ -18,6 +18,18 @@ export default
list = inventoryScriptsListObject,
view = GenerateList;
scope.canAdd = false;
scope.canEdit = false;
Rest.setUrl(GetBasePath('inventory_scripts'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
scope.canAdd = true;
scope.canEdit = true;
}
});
view.inject( list, {
mode: 'edit',
scope: scope

View File

@ -21,6 +21,15 @@
$state, CreateSelect2, $q
) {
Rest.setUrl(GetBasePath('job_templates'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add a job template.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view
var defaultUrl = GetBasePath('job_templates'),

View File

@ -46,6 +46,16 @@ export default
checkSCMStatus, getPlaybooks, callback,
choicesCount = 0;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('job_templates') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
// remove "type" field from search options
CredentialList = _.cloneDeep(CredentialList);
CredentialList.fields.kind.noSearch = true;

View File

@ -19,9 +19,20 @@ export default
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, InitiatePlaybookRun,
Wait, $compile, $state, $filter
) {
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('job_templates'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
var list = JobTemplateList,
defaultUrl = GetBasePath('job_templates'),
view = GenerateList,

View File

@ -70,6 +70,12 @@
flex: 0 0 637px;
max-width: 637px;
}
.SurveyMaker-previewPanel--viewOnly {
flex: 0 0 1155px;
max-width: 1155px;
}
.SurveyMaker-separatorPanel {
display: flex;
flex: 0 0 51px;

View File

@ -101,21 +101,21 @@ export default
ngClick: 'relaunchJob($event, all_job.id)',
awToolTip: 'Relaunch using the same parameters',
dataPlacement: 'top',
ngHide: "all_job.type == 'system_job' "
ngShow: "!(all_job.type == 'system_job') && all_job.summary_fields.user_capabilities.start"
},
cancel: {
mode: 'all',
ngClick: 'deleteJob(all_job.id)',
awToolTip: 'Cancel the job',
dataPlacement: 'top',
ngShow: "all_job.status === 'running'|| all_job.status === 'waiting' || all_job.status === 'pending'"
ngShow: "(all_job.status === 'running'|| all_job.status === 'waiting' || all_job.status === 'pending') && all_job.summary_fields.user_capabilities.start"
},
"delete": {
mode: 'all',
ngClick: 'deleteJob(all_job.id)',
awToolTip: 'Delete the job',
dataPlacement: 'top',
ngShow: "all_job.status !== 'running' && all_job.status !== 'waiting' && all_job.status !== 'pending'"
ngShow: "(all_job.status !== 'running' && all_job.status !== 'waiting' && all_job.status !== 'pending') && all_job.summary_fields.user_capabilities.delete"
}
}
});

View File

@ -100,13 +100,14 @@ export default
ngClick: 'relaunchJob($event, completed_job.id)',
awToolTip: 'Relaunch using the same parameters',
dataPlacement: 'top',
ngHide: "completed_job.type == 'system_job' "
ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start"
},
"delete": {
mode: 'all',
ngClick: 'deleteJob(completed_job.id)',
awToolTip: 'Delete the job',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'completed_job.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -58,7 +58,8 @@ export default
ngClick: 'addCredential()',
awToolTip: 'Create a new credential',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canAdd'
}
},
@ -72,7 +73,17 @@ export default
label: 'Edit',
"class": 'btn-sm',
awToolTip: 'Edit credential',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'credential.summary_fields.user_capabilities.edit'
},
view: {
ngClick: "editCredential(credential.id)",
label: 'View',
"class": 'btn-sm',
awToolTip: 'View credential',
dataPlacement: 'top',
ngShow: '!credential.summary_fields.user_capabilities.edit'
},
"delete": {
@ -81,7 +92,8 @@ export default
label: 'Delete',
"class": 'btn-sm',
awToolTip: 'Delete credential',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'credential.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -91,7 +91,8 @@ export default
ngClick: 'addInventory()',
awToolTip: 'Create a new inventory',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canAdd'
}
},
@ -103,13 +104,22 @@ export default
label: 'Edit',
ngClick: 'editInventory(inventory.id)',
awToolTip: 'Edit inventory',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'inventory.summary_fields.user_capabilities.edit'
},
view: {
label: 'View',
ngClick: 'editInventory(inventory.id)',
awToolTip: 'View inventory',
dataPlacement: 'top',
ngShow: '!inventory.summary_fields.user_capabilities.edit'
},
"delete": {
label: 'Delete',
ngClick: "deleteInventory(inventory.id, inventory.name)",
awToolTip: 'Delete inventory',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'inventory.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -169,8 +169,8 @@ export default
ngClick: 'updateGroup(group)',
awToolTip: "{{ group.launch_tooltip }}",
dataTipWatch: "group.launch_tooltip",
ngShow: "group.status !== 'running' && group.status " +
"!== 'pending' && group.status !== 'updating'",
ngShow: "(group.status !== 'running' && group.status " +
"!== 'pending' && group.status !== 'updating') && group.summary_fields.user_capabilities.start",
ngClass: "group.launch_class",
dataPlacement: "top",
},
@ -180,8 +180,8 @@ export default
ngClick: "cancelUpdate(group.id)",
awToolTip: "Cancel sync process",
'class': 'red-txt',
ngShow: "group.status == 'running' || group.status == 'pending' " +
"|| group.status == 'updating'",
ngShow: "(group.status == 'running' || group.status == 'pending' " +
"|| group.status == 'updating') && group.summary_fields.user_capabilities.start",
dataPlacement: "top",
iconClass: "fa fa-minus-circle"
},
@ -189,7 +189,7 @@ export default
mode: 'all',
ngClick: "copyMoveGroup(group.id)",
awToolTip: 'Copy or move group',
ngShow: "group.id > 0",
ngShow: "group.id > 0 && group.summary_fields.user_capabilities.copy",
dataPlacement: "top"
},
schedule: {
@ -198,21 +198,23 @@ export default
awToolTip: "{{ group.group_schedule_tooltip }}",
ngClass: "group.scm_type_class",
dataPlacement: 'top',
ngHide: "group.summary_fields.inventory_source.source === ''"
ngShow: "!(group.summary_fields.inventory_source.source === '') && group.summary_fields.user_capabilities.schedule"
},
edit: {
//label: 'Edit',
mode: 'all',
ngClick: "editGroup(group.id)",
awToolTip: 'Edit group',
dataPlacement: "top"
dataPlacement: "top",
ngShow: "group.summary_fields.user_capabilities.edit"
},
"delete": {
//label: 'Delete',
mode: 'all',
ngClick: "deleteGroup(group)",
awToolTip: 'Delete group',
dataPlacement: "top"
dataPlacement: "top",
ngShow: "group.summary_fields.user_capabilities.delete"
}
}
});

View File

@ -68,7 +68,8 @@ export default
mode: 'all',
ngClick: 'submitJob(job_template.id)',
awToolTip: 'Start a job using this template',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'job_template.summary_fields.user_capabilities.start'
},
schedule: {
label: 'Schedule',
@ -76,6 +77,7 @@ export default
ngClick: 'scheduleJob(job_template.id)',
awToolTip: 'Schedule future job template runs',
dataPlacement: 'top',
ngShow: 'job_template.summary_fields.user_capabilities.schedule'
},
copy: {
label: 'Copy',
@ -83,7 +85,7 @@ export default
"class": 'btn-danger btn-xs',
awToolTip: 'Copy template',
dataPlacement: 'top',
ngHide: 'job_template.summary_fields.can_copy===false'
ngShow: 'job_template.summary_fields.user_capabilities.copy'
},
edit: {
label: 'Edit',
@ -91,6 +93,15 @@ export default
awToolTip: 'Edit template',
"class": 'btn-default btn-xs',
dataPlacement: 'top',
ngShow: 'job_template.summary_fields.user_capabilities.edit'
},
view: {
label: 'View',
ngClick: "editJobTemplate(job_template.id)",
awToolTip: 'View template',
"class": 'btn-default btn-xs',
dataPlacement: 'top',
ngShow: '!job_template.summary_fields.user_capabilities.edit'
},
"delete": {
label: 'Delete',
@ -98,6 +109,7 @@ export default
"class": 'btn-danger btn-xs',
awToolTip: 'Delete template',
dataPlacement: 'top',
ngShow: 'job_template.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -65,7 +65,8 @@ export default
ngClick: 'addProject()',
awToolTip: 'Create a new project',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: "canAdd"
},
refresh: {
mode: 'all',
@ -86,30 +87,40 @@ export default
awToolTip: "{{ project.scm_update_tooltip }}",
dataTipWatch: "project.scm_update_tooltip",
ngClass: "project.scm_type_class",
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: "project.summary_fields.user_capabilities.start"
},
schedule: {
mode: 'all',
ngClick: "editSchedules(project.id)",
awToolTip: "{{ project.scm_schedule_tooltip }}",
ngClass: "project.scm_type_class",
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: "project.summary_fields.user_capabilities.schedule"
},
edit: {
ngClick: "editProject(project.id)",
awToolTip: 'Edit the project',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: "project.summary_fields.user_capabilities.edit"
},
view: {
ngClick: "editProject(project.id)",
awToolTip: 'View the project',
dataPlacement: 'top',
ngShow: "!project.summary_fields.user_capabilities.edit",
icon: 'fa-eye',
},
"delete": {
ngClick: "deleteProject(project.id, project.name)",
awToolTip: 'Delete the project',
ngShow: "project.status !== 'updating' && project.status !== 'running' && project.status !== 'pending'",
ngShow: "(project.status !== 'updating' && project.status !== 'running' && project.status !== 'pending') && project.summary_fields.user_capabilities.delete",
dataPlacement: 'top'
},
cancel: {
ngClick: "cancelUpdate(project.id, project.name)",
awToolTip: 'Cancel the SCM update',
ngShow: "project.status == 'updating' || project.status == 'running' || project.status == 'pending'",
ngShow: "(project.status == 'updating' || project.status == 'running' || project.status == 'pending') && project.summary_fields.user_capabilities.start",
dataPlacement: 'top'
}
}

View File

@ -79,14 +79,16 @@ export default
ngClick: "editSchedule(schedule.id)",
icon: 'icon-edit',
awToolTip: 'Edit schedule',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'schedule.summary_fields.user_capabilities.edit'
},
"delete": {
label: 'Delete',
ngClick: "deleteSchedule(schedule.id)",
icon: 'icon-trash',
awToolTip: 'Delete schedule',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'schedule.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -47,7 +47,8 @@ export default
ngClick: 'addTeam()',
awToolTip: 'Create a new team',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canAdd'
}
},
@ -61,16 +62,25 @@ export default
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'Edit team',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'team.summary_fields.user_capabilities.edit'
},
view: {
label: 'View',
ngClick: "editTeam(team.id)",
"class": 'btn-xs btn-default',
awToolTip: 'View team',
dataPlacement: 'top',
ngShow: '!team.summary_fields.user_capabilities.edit'
},
"delete": {
label: 'Delete',
ngClick: "deleteTeam(team.id, team.name)",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete team',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'team.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -44,7 +44,8 @@ export default
basePaths: ['organizations', 'users'], // base path must be in list, or action not available
awToolTip: 'Create a new user',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD'
buttonContent: '&#43; ADD',
ngShow: 'canAdd'
}
},
@ -58,7 +59,17 @@ export default
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'Edit user',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'user.summary_fields.user_capabilities.edit'
},
view: {
label: 'View',
ngClick: "editUser(user.id)",
"class": 'btn-xs btn-default',
awToolTip: 'View user',
dataPlacement: 'top',
ngShow: '!user.summary_fields.user_capabilities.edit'
},
"delete": {
@ -67,7 +78,8 @@ export default
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete user',
dataPlacement: 'top'
dataPlacement: 'top',
ngShow: 'user.summary_fields.user_capabilities.delete'
}
}
});

View File

@ -65,7 +65,8 @@ export default function(){
ngClick: 'addNotificationTemplate()',
awToolTip: 'Create a new notification template',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD NOTIFICATION TEMPLATE'
buttonContent: '&#43; ADD NOTIFICATION TEMPLATE',
ngShow: 'current_user.is_superuser || (current_user_admin_orgs && current_user_admin_orgs.length > 0)'
}
}

View File

@ -12,6 +12,15 @@ export default ['$scope', '$rootScope', '$compile', '$location',
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ReturnToCaller, Wait, $state) {
Rest.setUrl(GetBasePath('organizations'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add an organization.', 'alert-info');
}
});
ClearScope();
// Inject dynamic view

View File

@ -25,6 +25,16 @@ export default ['$scope', '$rootScope', '$compile', '$location',
id = $stateParams.organization_id,
relatedSets = {};
$scope.canEdit = false;
Rest.setUrl(GetBasePath('organizations') + id);
Rest.options()
.success(function(data) {
if (data.actions.PUT) {
$scope.canEdit = true;
}
});
$scope.$parent.activeMode = 'edit';
$scope.$parent.activeCard = parseInt(id);

View File

@ -17,6 +17,18 @@ export default ['$stateParams', '$scope', '$rootScope', '$location',
ClearScope();
$scope.canAdd = false;
$scope.canEdit = false;
Rest.setUrl(GetBasePath('organizations'));
Rest.options()
.success(function(data) {
if (data.actions.POST) {
$scope.canAdd = true;
$scope.canEdit = true;
}
});
var defaultUrl = GetBasePath('organizations'),
list = OrganizationList,
pageSize = 24,
@ -25,6 +37,7 @@ export default ['$stateParams', '$scope', '$rootScope', '$location',
var parseCardData = function(cards) {
return cards.map(function(card) {
var val = {}, url = '/#/organizations/' + card.id + '/';
val.user_capabilities = card.summary_fields.user_capabilities;
val.name = card.name;
val.id = card.id;
val.description = card.description || undefined;

View File

@ -13,6 +13,7 @@
<div class="List-actions">
<button class="btn List-buttonSubmit"
aw-tool-tip="Create a new organization"
ng-show="canAdd"
ng-click="addOrganization()">
+ ADD
</button>
@ -31,13 +32,23 @@
<div class="OrgCards-actionItems">
<button class="OrgCards-actionItem
List-actionButton"
ng-show="card.user_capabilities.edit"
ng-class="{'List-editButton--selected': (activeCard === card.id || card.isActiveCard) && activeMode === 'edit' }"
ng-click="editOrganization(card.id)">
<i class="OrgCards-actionItemIcon fa fa-pencil">
</i>
</button>
<button class="OrgCards-actionItem
List-actionButton"
ng-show="!card.user_capabilities.edit"
ng-class="{'List-editButton--selected': (activeCard === card.id || card.isActiveCard) && activeMode === 'edit' }"
ng-click="editOrganization(card.id)">
<i class="OrgCards-actionItemIcon fa fa-search-plus">
</i>
</button>
<button class="OrgCards-actionItem List-actionButton
List-actionButton--delete"
ng-show="card.user_capabilities.delete"
ng-click="deleteOrganization(card.id, card.name)">
<i class="OrgCards-actionItemIcon
fa fa-trash-o">

View File

@ -32,13 +32,13 @@
</div>
</div>
<div class="SurveyMaker-content">
<div class="SurveyMaker-questionPanel">
<div class="SurveyMaker-questionPanel" ng-show="canEdit">
<div id="survey_maker_question_form"></div>
</div>
<div class="SurveyMaker-separatorPanel">
<div class="SurveyMaker-separatorPanel" ng-show="canEdit">
<div class="SurveyMaker-contentSeparator"></div>
</div>
<div class="SurveyMaker-previewPanel">
<div class="SurveyMaker-previewPanel" ng-class="{'SurveyMaker-previewPanel--viewOnly': !canEdit}">
<div style="display: flex; flex-direction: column; width: 100%;">
<div class="SurveyMaker-panelHeader">PREVIEW</div>
<div class="SurveyMaker-panelBody">
@ -56,13 +56,13 @@
<i>{{question.question_description}}</i>
</div>
<div class="SurveyMaker-previewInputRow">
<span dnd-handle class="SurveyMaker-reorderButton" data-placement="top" aw-tool-tip="Drag to reorder question" data-original-title="" title="">
<span dnd-handle class="SurveyMaker-reorderButton" data-placement="top" aw-tool-tip="Drag to reorder question" data-original-title="" title="" ng-show="canEdit">
<i class="fa fa-ellipsis-v"></i>
<span>&nbsp;</span>
<i class="fa fa-ellipsis-v"></i>
</span>
<survey-question class="SurveyMaker-previewInput" preview="true" question="question" ng-required="question.required" ng-disabled=true></survey-question>
<div class="SurveyMaker-previewActions">
<div class="SurveyMaker-previewActions" ng-show="canEdit">
<button class="List-actionButton" data-placement="top" ng-class="{'SurveyMaker-previewActions--selected' : editQuestionIndex == $index}" ng-click="editQuestion($index)" aw-tool-tip="Edit question" data-original-title="" title="">
<i class="fa fa-pencil"></i>
</button>
@ -80,9 +80,10 @@
</div>
<div class="SurveyMaker-panelFooter">
<div class="Form-buttons">
<button id="survey-delete-button" class="btn btn-sm SurveyMaker-deleteButton" ng-show="survey_exists" ng-click="showDeleteOverlay('survey')">DELETE SURVEY</button>
<button id="survey-close-button" class="btn btn-sm Form-buttonDefault" ng-click="closeSurvey('survey-modal-dialog')">CANCEL</button>
<button id="survey-save-button" class="btn btn-sm Form-saveButton" ng-click="saveSurvey()" ng-disabled="survey_questions.length < 1 || !can_edit || editQuestionIndex !== null">SAVE</button>
<button id="survey-delete-button" class="btn btn-sm SurveyMaker-deleteButton" ng-show="survey_exists && canEdit" ng-click="showDeleteOverlay('survey')">DELETE SURVEY</button>
<button id="survey-close-button" class="btn btn-sm Form-buttonDefault" ng-click="closeSurvey('survey-modal-dialog')" ng-show="canEdit">CANCEL</button>
<button id="survey-close-button" class="btn btn-sm Form-buttonDefault" ng-click="closeSurvey('survey-modal-dialog')" ng-show="!canEdit">CLOSE</button>
<button id="survey-save-button" class="btn btn-sm Form-saveButton" ng-click="saveSurvey()" ng-disabled="survey_questions.length < 1 || !can_edit || editQuestionIndex !== null" ng-show="canEdit">SAVE</button>
</div>
</div>
</div>

View File

@ -865,6 +865,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += ">";
html += "<input type=\"checkbox\" ng-model=\"" + field.subCheckbox.variable + "\" ";
html += (field.subCheckbox.ngChange) ? "ng-change=\"" + field.subCheckbox.ngChange + "\" " : "";
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += "id=\"" + this.form.name + "_" + fld + "_ask_chbox\" ";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
@ -987,6 +988,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
if (field.subCheckbox.ngDisabled) {
html += "ng-disabled='" + field.subCheckbox.ngDisabled + "'";
}
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
html += "</label>";
@ -1084,6 +1086,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
if (field.subCheckbox.ngDisabled) {
html += "ng-disabled='" + field.subCheckbox.ngDisabled + "'";
}
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
html += "</label>";
@ -1151,6 +1154,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
if (field.subCheckbox.ngDisabled) {
html += "ng-disabled='" + field.subCheckbox.ngDisabled + "'";
}
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
html += "</label>";
@ -1199,6 +1203,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += (field.min || field.min === 0) ? this.attr(field, 'min') : "";
html += (field.max) ? this.attr(field, 'max') : "";
html += (field.ngChange) ? this.attr(field, 'ngChange') : "";
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += (field.slider) ? "id=\"" + fld + "-number\"" : (field.id) ? this.attr(field, 'id') : "";
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
html += (options.mode === 'add' && field.addRequired) ? "required " : "";
@ -1219,6 +1224,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += "<input type=\"checkbox\" ng-model=\"" +
field.subCheckbox.variable + "\" ";
html += (field.subCheckbox.ngChange) ? "ng-change=\"" + field.subCheckbox.ngChange + "\" " : "";
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += "id=\"" + this.form.name + "_" + fld + "_ask_chbox\" ";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
@ -1422,6 +1428,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += "<input type=\"checkbox\" ng-model=\"" +
field.subCheckbox.variable + "\" ";
html += (field.subCheckbox.ngChange) ? "ng-change=\"" + field.subCheckbox.ngChange + "\" " : "";
html += (field.ngDisabled) ? "ng-disabled=\"" + field.ngDisabled + "\" " : "";
html += "id=\"" + this.form.name + "_" + fld + "_ask_chbox\" ";
html += ">";
html += field.subCheckbox.text ? field.subCheckbox.text : "";
@ -1693,6 +1700,10 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
button.label = 'Cancel';
button['class'] = 'Form-cancelButton';
}
if (btn === 'close') {
button.label = 'Close';
button['class'] = 'Form-cancelButton';
}
if (btn === 'launch') {
button.label = 'Launch';
button['class'] = 'Form-launchButton';
@ -1705,6 +1716,10 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
button.label = 'Edit Survey';
button['class'] = 'Form-surveyButton';
}
if (btn === 'view_survey') {
button.label = 'View Survey';
button['class'] = 'Form-surveyButton';
}
// Build button HTML
html += "<button type=\"button\" ";