mirror of
https://github.com/ansible/awx.git
synced 2026-01-16 04:10:44 -03:30
cleanup activity stream
This commit is contained in:
parent
a6c57fc060
commit
e784dba612
@ -16,9 +16,7 @@
|
||||
* @description This form is for activity detail modal that can be shown on most pages.
|
||||
*/
|
||||
|
||||
export default
|
||||
angular.module('ActivityDetailDefinition', [])
|
||||
.factory('ActivityDetailForm', ['i18n', function(i18n) {
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
|
||||
name: 'activity',
|
||||
@ -48,4 +46,4 @@ export default
|
||||
}
|
||||
}
|
||||
|
||||
};}]); //Form
|
||||
};}];
|
||||
@ -9,45 +9,47 @@
|
||||
* @name controllers.function:Activity Stream
|
||||
* @description This controller controls the activity stream.
|
||||
*/
|
||||
function activityStreamController($scope, $state, subTitle, Stream, GetTargetTitle, list, Dataset) {
|
||||
export default ['$scope', '$state', 'subTitle', 'Stream', 'GetTargetTitle',
|
||||
'StreamList', 'Dataset',
|
||||
function activityStreamController($scope, $state, subTitle, Stream,
|
||||
GetTargetTitle, list, Dataset) {
|
||||
|
||||
init();
|
||||
initOmitSmartTags();
|
||||
init();
|
||||
initOmitSmartTags();
|
||||
|
||||
function init() {
|
||||
// search init
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
function init() {
|
||||
// search init
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
|
||||
// subTitle is passed in via a resolve on the route. If there is no subtitle
|
||||
// generated in the resolve then we go get the targets generic title.
|
||||
// subTitle is passed in via a resolve on the route. If there is no subtitle
|
||||
// generated in the resolve then we go get the targets generic title.
|
||||
|
||||
// Get the streams sub-title based on the target. This scope variable is leveraged
|
||||
// when we define the activity stream list. Specifically it is included in the list
|
||||
// title.
|
||||
$scope.streamSubTitle = subTitle ? subTitle : GetTargetTitle($state.params.target);
|
||||
// Get the streams sub-title based on the target. This scope variable is leveraged
|
||||
// when we define the activity stream list. Specifically it is included in the list
|
||||
// title.
|
||||
$scope.streamSubTitle = subTitle ? subTitle : GetTargetTitle($state.params.target);
|
||||
|
||||
// Open the stream
|
||||
Stream({
|
||||
scope: $scope
|
||||
});
|
||||
}
|
||||
// Open the stream
|
||||
Stream({
|
||||
scope: $scope
|
||||
});
|
||||
}
|
||||
|
||||
// Specification of smart-tags omission from the UI is done in the route/state init.
|
||||
// A limitation is that this specficiation is static and the key for which to be omitted from
|
||||
// the smart-tags must be known at that time.
|
||||
// In the case of activity stream, we won't to dynamically ommit the resource for which we are
|
||||
// displaying the activity stream for. i.e. 'project', 'credential', etc.
|
||||
function initOmitSmartTags() {
|
||||
let defaults, route = _.find($state.$current.path, (step) => {
|
||||
return step.params.hasOwnProperty('activity_search');
|
||||
});
|
||||
if (route && $state.params.target !== undefined) {
|
||||
defaults = route.params.activity_search.config.value;
|
||||
defaults[$state.params.target] = null;
|
||||
// Specification of smart-tags omission from the UI is done in the route/state init.
|
||||
// A limitation is that this specficiation is static and the key for which to be omitted from
|
||||
// the smart-tags must be known at that time.
|
||||
// In the case of activity stream, we won't to dynamically ommit the resource for which we are
|
||||
// displaying the activity stream for. i.e. 'project', 'credential', etc.
|
||||
function initOmitSmartTags() {
|
||||
let defaults, route = _.find($state.$current.path, (step) => {
|
||||
return step.params.hasOwnProperty('activity_search');
|
||||
});
|
||||
if (route && $state.params.target !== undefined) {
|
||||
defaults = route.params.activity_search.config.value;
|
||||
defaults[$state.params.target] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ['$scope', '$state', 'subTitle', 'Stream', 'GetTargetTitle', 'StreamList', 'Dataset', activityStreamController];
|
||||
];
|
||||
|
||||
@ -60,8 +60,8 @@ export default {
|
||||
return qs.search(path, stateParams);
|
||||
}
|
||||
],
|
||||
features: ['FeaturesService', 'ProcessErrors', '$state', '$rootScope',
|
||||
function(FeaturesService, ProcessErrors, $state, $rootScope) {
|
||||
features: ['FeaturesService', '$state', '$rootScope',
|
||||
function(FeaturesService, $state, $rootScope) {
|
||||
var features = FeaturesService.get();
|
||||
if (features) {
|
||||
if (FeaturesService.featureEnabled('activity_streams')) {
|
||||
@ -81,12 +81,10 @@ export default {
|
||||
});
|
||||
}
|
||||
],
|
||||
subTitle: ['$stateParams',
|
||||
'Rest',
|
||||
'ModelToBasePathKey',
|
||||
'GetBasePath',
|
||||
subTitle: ['$stateParams', 'Rest', 'ModelToBasePathKey', 'GetBasePath',
|
||||
'ProcessErrors',
|
||||
function($stateParams, rest, ModelToBasePathKey, getBasePath, ProcessErrors) {
|
||||
function($stateParams, rest, ModelToBasePathKey, getBasePath,
|
||||
ProcessErrors) {
|
||||
// If we have a target and an ID then we want to go grab the name of the object
|
||||
// that we're examining with the activity stream. This name will be used in the
|
||||
// subtitle.
|
||||
|
||||
@ -1,78 +1,77 @@
|
||||
export default
|
||||
function BuildAnchor($log, $filter) {
|
||||
// Returns a full <a href=''>resource_name</a> HTML string if link can be derived from supplied context
|
||||
// returns name of resource if activity stream object doesn't contain enough data to build a UI url
|
||||
// arguments are: a summary_field object, a resource type, an activity stream object
|
||||
return function (obj, resource, activity) {
|
||||
var url = '/#/';
|
||||
// try/except pattern asserts that:
|
||||
// if we encounter a case where a UI url can't or shouldn't be generated, just supply the name of the resource
|
||||
try {
|
||||
// catch-all case to avoid generating urls if a resource has been deleted
|
||||
// if a resource still exists, it'll be serialized in the activity's summary_fields
|
||||
if (!activity.summary_fields[resource]){
|
||||
throw {name : 'ResourceDeleted', message: 'The referenced resource no longer exists'};
|
||||
}
|
||||
switch (resource) {
|
||||
case 'custom_inventory_script':
|
||||
url += 'inventory_scripts/' + obj.id + '/';
|
||||
break;
|
||||
case 'group':
|
||||
if (activity.operation === 'create' || activity.operation === 'delete'){
|
||||
// the API formats the changes.inventory field as str 'myInventoryName-PrimaryKey'
|
||||
var inventory_id = _.last(activity.changes.inventory.split('-'));
|
||||
url += 'inventories/' + inventory_id + '/manage?group=' + activity.changes.id;
|
||||
}
|
||||
else {
|
||||
url += 'inventories/' + activity.summary_fields.inventory[0].id + '/manage?group=' + (activity.changes.id || activity.changes.object1_pk);
|
||||
}
|
||||
break;
|
||||
case 'host':
|
||||
url += 'home/hosts/' + obj.id;
|
||||
break;
|
||||
case 'job':
|
||||
url += 'jobs/' + obj.id;
|
||||
break;
|
||||
case 'inventory':
|
||||
url += 'inventories/' + obj.id + '/';
|
||||
break;
|
||||
case 'schedule':
|
||||
// schedule urls depend on the resource they're associated with
|
||||
if (activity.summary_fields.job_template){
|
||||
url += 'job_templates/' + activity.summary_fields.job_template.id + '/schedules/' + obj.id;
|
||||
}
|
||||
else if (activity.summary_fields.project){
|
||||
url += 'projects/' + activity.summary_fields.project.id + '/schedules/' + obj.id;
|
||||
}
|
||||
else if (activity.summary_fields.system_job_template){
|
||||
url += 'management_jobs/' + activity.summary_fields.system_job_template.id + '/schedules/edit/' + obj.id;
|
||||
}
|
||||
// urls for inventory sync schedules currently depend on having an inventory id and group id
|
||||
else {
|
||||
throw {name : 'NotImplementedError', message : 'activity.summary_fields to build this url not implemented yet'};
|
||||
}
|
||||
break;
|
||||
case 'notification_template':
|
||||
url += `notification_templates/${obj.id}`;
|
||||
break;
|
||||
case 'role':
|
||||
throw {name : 'NotImplementedError', message : 'role object management is not consolidated to a single UI view'};
|
||||
case 'job_template':
|
||||
url += `templates/job_template/${obj.id}`;
|
||||
break;
|
||||
case 'workflow_job_template':
|
||||
url += `templates/workflow_job_template/${obj.id}`;
|
||||
break;
|
||||
default:
|
||||
url += resource + 's/' + obj.id + '/';
|
||||
}
|
||||
return ' <a href=\"' + url + '\"> ' + $filter('sanitize')(obj.name || obj.username) + ' </a> ';
|
||||
export default function BuildAnchor($log, $filter) {
|
||||
// Returns a full <a href=''>resource_name</a> HTML string if link can be derived from supplied context
|
||||
// returns name of resource if activity stream object doesn't contain enough data to build a UI url
|
||||
// arguments are: a summary_field object, a resource type, an activity stream object
|
||||
return function (obj, resource, activity) {
|
||||
var url = '/#/';
|
||||
// try/except pattern asserts that:
|
||||
// if we encounter a case where a UI url can't or shouldn't be generated, just supply the name of the resource
|
||||
try {
|
||||
// catch-all case to avoid generating urls if a resource has been deleted
|
||||
// if a resource still exists, it'll be serialized in the activity's summary_fields
|
||||
if (!activity.summary_fields[resource]){
|
||||
throw {name : 'ResourceDeleted', message: 'The referenced resource no longer exists'};
|
||||
}
|
||||
catch(err){
|
||||
$log.debug(err);
|
||||
return ' ' + $filter('sanitize')(obj.name || obj.username || '') + ' ';
|
||||
switch (resource) {
|
||||
case 'custom_inventory_script':
|
||||
url += 'inventory_scripts/' + obj.id + '/';
|
||||
break;
|
||||
case 'group':
|
||||
if (activity.operation === 'create' || activity.operation === 'delete'){
|
||||
// the API formats the changes.inventory field as str 'myInventoryName-PrimaryKey'
|
||||
var inventory_id = _.last(activity.changes.inventory.split('-'));
|
||||
url += 'inventories/' + inventory_id + '/manage?group=' + activity.changes.id;
|
||||
}
|
||||
else {
|
||||
url += 'inventories/' + activity.summary_fields.inventory[0].id + '/manage?group=' + (activity.changes.id || activity.changes.object1_pk);
|
||||
}
|
||||
break;
|
||||
case 'host':
|
||||
url += 'home/hosts/' + obj.id;
|
||||
break;
|
||||
case 'job':
|
||||
url += 'jobs/' + obj.id;
|
||||
break;
|
||||
case 'inventory':
|
||||
url += 'inventories/' + obj.id + '/';
|
||||
break;
|
||||
case 'schedule':
|
||||
// schedule urls depend on the resource they're associated with
|
||||
if (activity.summary_fields.job_template){
|
||||
url += 'job_templates/' + activity.summary_fields.job_template.id + '/schedules/' + obj.id;
|
||||
}
|
||||
else if (activity.summary_fields.project){
|
||||
url += 'projects/' + activity.summary_fields.project.id + '/schedules/' + obj.id;
|
||||
}
|
||||
else if (activity.summary_fields.system_job_template){
|
||||
url += 'management_jobs/' + activity.summary_fields.system_job_template.id + '/schedules/edit/' + obj.id;
|
||||
}
|
||||
// urls for inventory sync schedules currently depend on having an inventory id and group id
|
||||
else {
|
||||
throw {name : 'NotImplementedError', message : 'activity.summary_fields to build this url not implemented yet'};
|
||||
}
|
||||
break;
|
||||
case 'notification_template':
|
||||
url += `notification_templates/${obj.id}`;
|
||||
break;
|
||||
case 'role':
|
||||
throw {name : 'NotImplementedError', message : 'role object management is not consolidated to a single UI view'};
|
||||
case 'job_template':
|
||||
url += `templates/job_template/${obj.id}`;
|
||||
break;
|
||||
case 'workflow_job_template':
|
||||
url += `templates/workflow_job_template/${obj.id}`;
|
||||
break;
|
||||
default:
|
||||
url += resource + 's/' + obj.id + '/';
|
||||
}
|
||||
};
|
||||
}
|
||||
return ' <a href=\"' + url + '\"> ' + $filter('sanitize')(obj.name || obj.username) + ' </a> ';
|
||||
}
|
||||
catch(err){
|
||||
$log.debug(err);
|
||||
return ' ' + $filter('sanitize')(obj.name || obj.username || '') + ' ';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
BuildAnchor.$inject = ['$log', '$filter'];
|
||||
|
||||
@ -1,126 +1,125 @@
|
||||
export default
|
||||
function BuildDescription(BuildAnchor, $log, i18n) {
|
||||
return function (activity) {
|
||||
export default function BuildDescription(BuildAnchor, $log, i18n) {
|
||||
return function (activity) {
|
||||
|
||||
var pastTense = function(operation){
|
||||
return (/e$/.test(activity.operation)) ? operation + 'd ' : operation + 'ed ';
|
||||
};
|
||||
// convenience method to see if dis+association operation involves 2 groups
|
||||
// the group cases are slightly different because groups can be dis+associated into each other
|
||||
var isGroupRelationship = function(activity){
|
||||
return activity.object1 === 'group' && activity.object2 === 'group' && activity.summary_fields.group.length > 1;
|
||||
};
|
||||
|
||||
// Activity stream objects will outlive the resources they reference
|
||||
// in that case, summary_fields will not be available - show generic error text instead
|
||||
try {
|
||||
activity.description = pastTense(activity.operation);
|
||||
switch(activity.object_association){
|
||||
// explicit role dis+associations
|
||||
case 'role':
|
||||
// object1 field is resource targeted by the dis+association
|
||||
// object2 field is the resource the role is inherited from
|
||||
// summary_field.role[0] contains ref info about the role
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> role_name from <object1>"
|
||||
case 'disassociate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome: "associated <object2> role_name to <object1>"
|
||||
case 'associate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// inherited role dis+associations (logic identical to case 'role')
|
||||
case 'parents':
|
||||
// object1 field is resource targeted by the dis+association
|
||||
// object2 field is the resource the role is inherited from
|
||||
// summary_field.role[0] contains ref info about the role
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> role_name from <object1>"
|
||||
case 'disassociate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome: "associated <object2> role_name to <object1>"
|
||||
case 'associate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// CRUD operations / resource on resource dis+associations
|
||||
default:
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> from <object1>"
|
||||
case 'disassociate' :
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else {
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome "associated <object2> to <object1>"
|
||||
case 'associate':
|
||||
// groups are the only resource that can be associated/disassociated into each other
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
|
||||
}
|
||||
else {
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity);
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
|
||||
break;
|
||||
// expected outcome: "operation <object1>"
|
||||
case 'update':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
break;
|
||||
case 'create':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(err){
|
||||
$log.debug(err);
|
||||
activity.description = i18n._('Event summary not available');
|
||||
}
|
||||
var pastTense = function(operation){
|
||||
return (/e$/.test(activity.operation)) ? operation + 'd ' : operation + 'ed ';
|
||||
};
|
||||
// convenience method to see if dis+association operation involves 2 groups
|
||||
// the group cases are slightly different because groups can be dis+associated into each other
|
||||
var isGroupRelationship = function(activity){
|
||||
return activity.object1 === 'group' && activity.object2 === 'group' && activity.summary_fields.group.length > 1;
|
||||
};
|
||||
}
|
||||
|
||||
BuildDescription.$inject = ['BuildAnchor', '$log', 'i18n'];
|
||||
// Activity stream objects will outlive the resources they reference
|
||||
// in that case, summary_fields will not be available - show generic error text instead
|
||||
try {
|
||||
activity.description = pastTense(activity.operation);
|
||||
switch(activity.object_association){
|
||||
// explicit role dis+associations
|
||||
case 'role':
|
||||
// object1 field is resource targeted by the dis+association
|
||||
// object2 field is the resource the role is inherited from
|
||||
// summary_field.role[0] contains ref info about the role
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> role_name from <object1>"
|
||||
case 'disassociate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome: "associated <object2> role_name to <object1>"
|
||||
case 'associate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// inherited role dis+associations (logic identical to case 'role')
|
||||
case 'parents':
|
||||
// object1 field is resource targeted by the dis+association
|
||||
// object2 field is the resource the role is inherited from
|
||||
// summary_field.role[0] contains ref info about the role
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> role_name from <object1>"
|
||||
case 'disassociate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' from ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome: "associated <object2> role_name to <object1>"
|
||||
case 'associate':
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
|
||||
}
|
||||
else{
|
||||
activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
|
||||
' to ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// CRUD operations / resource on resource dis+associations
|
||||
default:
|
||||
switch(activity.operation){
|
||||
// expected outcome: "disassociated <object2> from <object1>"
|
||||
case 'disassociate' :
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
|
||||
}
|
||||
else {
|
||||
activity.description += activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) +
|
||||
'from ' + activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
}
|
||||
break;
|
||||
// expected outcome "associated <object2> to <object1>"
|
||||
case 'associate':
|
||||
// groups are the only resource that can be associated/disassociated into each other
|
||||
if (isGroupRelationship(activity)){
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
|
||||
}
|
||||
else {
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity) +
|
||||
'to ' + activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity);
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
|
||||
break;
|
||||
// expected outcome: "operation <object1>"
|
||||
case 'update':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
|
||||
break;
|
||||
case 'create':
|
||||
activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(err){
|
||||
$log.debug(err);
|
||||
activity.description = i18n._('Event summary not available');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
BuildDescription.$inject = ['BuildAnchor', '$log', 'i18n'];
|
||||
|
||||
@ -1,39 +1,40 @@
|
||||
export default
|
||||
function ShowDetail($filter, $rootScope, Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty, Find) {
|
||||
return function (params, scope) {
|
||||
export default function ShowDetail($filter, $rootScope, Rest, Alert,
|
||||
GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm,
|
||||
Empty, Find) {
|
||||
return function (params, scope) {
|
||||
|
||||
var activity_id = params.activity_id,
|
||||
activity = Find({ list: params.scope.activities, key: 'id', val: activity_id }),
|
||||
element;
|
||||
var activity_id = params.activity_id,
|
||||
activity = Find({ list: params.scope.activities, key: 'id', val: activity_id }),
|
||||
element;
|
||||
|
||||
if (activity) {
|
||||
if (activity) {
|
||||
|
||||
// Grab our element out of the dom
|
||||
element = angular.element(document.getElementById('stream-detail-modal'));
|
||||
// Grab our element out of the dom
|
||||
element = angular.element(document.getElementById('stream-detail-modal'));
|
||||
|
||||
// Grab the modal's scope so that we can set a few variables
|
||||
scope = element.scope();
|
||||
// Grab the modal's scope so that we can set a few variables
|
||||
scope = element.scope();
|
||||
|
||||
scope.changes = activity.changes;
|
||||
scope.user = ((activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system') +
|
||||
' on ' + $filter('longDate')(activity.timestamp);
|
||||
scope.operation = activity.description;
|
||||
scope.header = "Event " + activity.id;
|
||||
scope.changes = activity.changes;
|
||||
scope.user = ((activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system') +
|
||||
' on ' + $filter('longDate')(activity.timestamp);
|
||||
scope.operation = activity.description;
|
||||
scope.header = "Event " + activity.id;
|
||||
|
||||
// Open the modal
|
||||
$('#stream-detail-modal').modal({
|
||||
show: true,
|
||||
backdrop: 'static',
|
||||
keyboard: true
|
||||
});
|
||||
// Open the modal
|
||||
$('#stream-detail-modal').modal({
|
||||
show: true,
|
||||
backdrop: 'static',
|
||||
keyboard: true
|
||||
});
|
||||
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
}
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ShowDetail.$inject = ['$filter', '$rootScope', 'Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate',
|
||||
'ActivityDetailForm', 'Empty', 'Find'];
|
||||
|
||||
@ -1,53 +1,52 @@
|
||||
export default
|
||||
function Stream($rootScope, $location, $state, Rest, GetBasePath, ProcessErrors,
|
||||
Wait, StreamList, GenerateList, FormatDate,
|
||||
BuildDescription, ShowDetail) {
|
||||
return function (params) {
|
||||
export default function Stream($rootScope, $location, $state, Rest, GetBasePath,
|
||||
ProcessErrors, Wait, StreamList, GenerateList, FormatDate, BuildDescription,
|
||||
ShowDetail) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var scope = params.scope;
|
||||
|
||||
$rootScope.flashMessage = null;
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
// descriptive title describing what AS is showing
|
||||
scope.streamTitle = (params && params.title) ? params.title : null;
|
||||
|
||||
scope.refreshStream = function () {
|
||||
$state.go('.', null, {reload: true});
|
||||
};
|
||||
|
||||
scope.showDetail = function (id) {
|
||||
ShowDetail({
|
||||
scope: scope,
|
||||
activity_id: id
|
||||
});
|
||||
};
|
||||
|
||||
if(scope.activities && scope.activities.length > 0) {
|
||||
buildUserAndDescription();
|
||||
}
|
||||
|
||||
scope.$watch('activities', function(){
|
||||
// Watch for future update to scope.activities (like page change, column sort, search, etc)
|
||||
buildUserAndDescription();
|
||||
});
|
||||
|
||||
function buildUserAndDescription(){
|
||||
scope.activities.forEach(function(activity, i) {
|
||||
// build activity.user
|
||||
if (scope.activities[i].summary_fields.actor) {
|
||||
scope.activities[i].user = "<a href=\"/#/users/" + scope.activities[i].summary_fields.actor.id + "\">" +
|
||||
scope.activities[i].summary_fields.actor.username + "</a>";
|
||||
} else {
|
||||
scope.activities[i].user = 'system';
|
||||
}
|
||||
// build description column / action text
|
||||
BuildDescription(scope.activities[i]);
|
||||
|
||||
});
|
||||
}
|
||||
// descriptive title describing what AS is showing
|
||||
scope.streamTitle = (params && params.title) ? params.title : null;
|
||||
|
||||
scope.refreshStream = function () {
|
||||
$state.go('.', null, {reload: true});
|
||||
};
|
||||
}
|
||||
|
||||
scope.showDetail = function (id) {
|
||||
ShowDetail({
|
||||
scope: scope,
|
||||
activity_id: id
|
||||
});
|
||||
};
|
||||
|
||||
if(scope.activities && scope.activities.length > 0) {
|
||||
buildUserAndDescription();
|
||||
}
|
||||
|
||||
scope.$watch('activities', function(){
|
||||
// Watch for future update to scope.activities (like page change, column sort, search, etc)
|
||||
buildUserAndDescription();
|
||||
});
|
||||
|
||||
function buildUserAndDescription(){
|
||||
scope.activities.forEach(function(activity, i) {
|
||||
// build activity.user
|
||||
if (scope.activities[i].summary_fields.actor) {
|
||||
scope.activities[i].user = "<a href=\"/#/users/" + scope.activities[i].summary_fields.actor.id + "\">" +
|
||||
scope.activities[i].summary_fields.actor.username + "</a>";
|
||||
} else {
|
||||
scope.activities[i].user = 'system';
|
||||
}
|
||||
// build description column / action text
|
||||
BuildDescription(scope.activities[i]);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Stream.$inject = ['$rootScope', '$location', '$state', 'Rest', 'GetBasePath',
|
||||
'ProcessErrors', 'Wait', 'StreamList', 'generateList', 'FormatDate', 'BuildDescription',
|
||||
|
||||
@ -1,51 +1,50 @@
|
||||
export default
|
||||
function GetTargetTitle(i18n) {
|
||||
return function (target) {
|
||||
export default function GetTargetTitle(i18n) {
|
||||
return function (target) {
|
||||
|
||||
var rtnTitle = i18n._('ALL ACTIVITY');
|
||||
var rtnTitle = i18n._('ALL ACTIVITY');
|
||||
|
||||
switch(target) {
|
||||
case 'project':
|
||||
rtnTitle = i18n._('PROJECTS');
|
||||
break;
|
||||
case 'inventory':
|
||||
rtnTitle = i18n._('INVENTORIES');
|
||||
break;
|
||||
case 'credential':
|
||||
rtnTitle = i18n._('CREDENTIALS');
|
||||
break;
|
||||
case 'user':
|
||||
rtnTitle = i18n._('USERS');
|
||||
break;
|
||||
case 'team':
|
||||
rtnTitle = i18n._('TEAMS');
|
||||
break;
|
||||
case 'notification_template':
|
||||
rtnTitle = i18n._('NOTIFICATION TEMPLATES');
|
||||
break;
|
||||
case 'organization':
|
||||
rtnTitle = i18n._('ORGANIZATIONS');
|
||||
break;
|
||||
case 'job':
|
||||
rtnTitle = i18n._('JOBS');
|
||||
break;
|
||||
case 'custom_inventory_script':
|
||||
rtnTitle = i18n._('INVENTORY SCRIPTS');
|
||||
break;
|
||||
case 'schedule':
|
||||
rtnTitle = i18n._('SCHEDULES');
|
||||
break;
|
||||
case 'host':
|
||||
rtnTitle = i18n._('HOSTS');
|
||||
break;
|
||||
case 'template':
|
||||
rtnTitle = i18n._('TEMPLATES');
|
||||
break;
|
||||
}
|
||||
switch(target) {
|
||||
case 'project':
|
||||
rtnTitle = i18n._('PROJECTS');
|
||||
break;
|
||||
case 'inventory':
|
||||
rtnTitle = i18n._('INVENTORIES');
|
||||
break;
|
||||
case 'credential':
|
||||
rtnTitle = i18n._('CREDENTIALS');
|
||||
break;
|
||||
case 'user':
|
||||
rtnTitle = i18n._('USERS');
|
||||
break;
|
||||
case 'team':
|
||||
rtnTitle = i18n._('TEAMS');
|
||||
break;
|
||||
case 'notification_template':
|
||||
rtnTitle = i18n._('NOTIFICATION TEMPLATES');
|
||||
break;
|
||||
case 'organization':
|
||||
rtnTitle = i18n._('ORGANIZATIONS');
|
||||
break;
|
||||
case 'job':
|
||||
rtnTitle = i18n._('JOBS');
|
||||
break;
|
||||
case 'custom_inventory_script':
|
||||
rtnTitle = i18n._('INVENTORY SCRIPTS');
|
||||
break;
|
||||
case 'schedule':
|
||||
rtnTitle = i18n._('SCHEDULES');
|
||||
break;
|
||||
case 'host':
|
||||
rtnTitle = i18n._('HOSTS');
|
||||
break;
|
||||
case 'template':
|
||||
rtnTitle = i18n._('TEMPLATES');
|
||||
break;
|
||||
}
|
||||
|
||||
return rtnTitle;
|
||||
return rtnTitle;
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GetTargetTitle.$inject = ['i18n'];
|
||||
|
||||
@ -14,6 +14,8 @@ import ShowDetail from './factories/show-detail.factory';
|
||||
import Stream from './factories/stream.factory';
|
||||
import GetTargetTitle from './get-target-title.factory';
|
||||
import ModelToBasePathKey from './model-to-base-path-key.factory';
|
||||
import ActivityDetailForm from './activity-detail.form';
|
||||
import StreamList from './streams.list';
|
||||
|
||||
export default angular.module('activityStream', [streamDetailModal.name])
|
||||
.controller('activityStreamController', activityStreamController)
|
||||
@ -24,6 +26,8 @@ export default angular.module('activityStream', [streamDetailModal.name])
|
||||
.factory('Stream', Stream)
|
||||
.factory('GetTargetTitle', GetTargetTitle)
|
||||
.factory('ModelToBasePathKey', ModelToBasePathKey)
|
||||
.factory('ActivityDetailForm', ActivityDetailForm)
|
||||
.factory('StreamList', StreamList)
|
||||
.run(['$stateExtender', function($stateExtender) {
|
||||
$stateExtender.addState(activityStreamRoute);
|
||||
}]);
|
||||
|
||||
@ -10,50 +10,49 @@
|
||||
* @description Helper functions to convert singular/plural versions of our models to the opposite
|
||||
*/
|
||||
|
||||
export default
|
||||
function ModelToBasePathKey() {
|
||||
return function(model) {
|
||||
// This function takes in the singular model string and returns the key needed
|
||||
// to get the base path from $rootScope/local storage.
|
||||
export default function ModelToBasePathKey() {
|
||||
return function(model) {
|
||||
// This function takes in the singular model string and returns the key needed
|
||||
// to get the base path from $rootScope/local storage.
|
||||
|
||||
var basePathKey;
|
||||
var basePathKey;
|
||||
|
||||
switch(model) {
|
||||
case 'project':
|
||||
basePathKey = 'projects';
|
||||
break;
|
||||
case 'inventory':
|
||||
basePathKey = 'inventory';
|
||||
break;
|
||||
case 'job_template':
|
||||
basePathKey = 'job_templates';
|
||||
break;
|
||||
case 'credential':
|
||||
basePathKey = 'credentials';
|
||||
break;
|
||||
case 'user':
|
||||
basePathKey = 'users';
|
||||
break;
|
||||
case 'team':
|
||||
basePathKey = 'teams';
|
||||
break;
|
||||
case 'notification_template':
|
||||
basePathKey = 'notification_templates';
|
||||
break;
|
||||
case 'organization':
|
||||
basePathKey = 'organizations';
|
||||
break;
|
||||
case 'management_job':
|
||||
basePathKey = 'management_jobs';
|
||||
break;
|
||||
case 'custom_inventory_script':
|
||||
basePathKey = 'inventory_scripts';
|
||||
break;
|
||||
case 'workflow_job_template':
|
||||
basePathKey = 'workflow_job_templates';
|
||||
break;
|
||||
}
|
||||
switch(model) {
|
||||
case 'project':
|
||||
basePathKey = 'projects';
|
||||
break;
|
||||
case 'inventory':
|
||||
basePathKey = 'inventory';
|
||||
break;
|
||||
case 'job_template':
|
||||
basePathKey = 'job_templates';
|
||||
break;
|
||||
case 'credential':
|
||||
basePathKey = 'credentials';
|
||||
break;
|
||||
case 'user':
|
||||
basePathKey = 'users';
|
||||
break;
|
||||
case 'team':
|
||||
basePathKey = 'teams';
|
||||
break;
|
||||
case 'notification_template':
|
||||
basePathKey = 'notification_templates';
|
||||
break;
|
||||
case 'organization':
|
||||
basePathKey = 'organizations';
|
||||
break;
|
||||
case 'management_job':
|
||||
basePathKey = 'management_jobs';
|
||||
break;
|
||||
case 'custom_inventory_script':
|
||||
basePathKey = 'inventory_scripts';
|
||||
break;
|
||||
case 'workflow_job_template':
|
||||
basePathKey = 'workflow_job_templates';
|
||||
break;
|
||||
}
|
||||
|
||||
return basePathKey;
|
||||
};
|
||||
}
|
||||
return basePathKey;
|
||||
};
|
||||
}
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
*************************************************/
|
||||
|
||||
|
||||
export default
|
||||
angular.module('StreamListDefinition', [])
|
||||
.factory('StreamList', ['i18n', function(i18n) {
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
|
||||
name: 'activities',
|
||||
@ -72,4 +70,4 @@ export default
|
||||
}
|
||||
}
|
||||
|
||||
};}]);
|
||||
};}];
|
||||
@ -143,8 +143,6 @@ var tower = angular.module('Tower', [
|
||||
'AllJobsDefinition',
|
||||
'JobSummaryDefinition',
|
||||
'HostGroupsFormDefinition',
|
||||
'StreamListDefinition',
|
||||
'ActivityDetailDefinition',
|
||||
'ScheduledJobsDefinition',
|
||||
'JobsListDefinition',
|
||||
'LogViewerStatusDefinition',
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import ActivityDetail from "./forms/ActivityDetail";
|
||||
import EventsViewer from "./forms/EventsViewer";
|
||||
import Groups from "./forms/Groups";
|
||||
import HostGroups from "./forms/HostGroups";
|
||||
@ -23,8 +22,7 @@ import Workflows from "./forms/Workflows";
|
||||
|
||||
|
||||
export
|
||||
{ ActivityDetail,
|
||||
EventsViewer,
|
||||
{ EventsViewer,
|
||||
Groups,
|
||||
HostGroups,
|
||||
Hosts,
|
||||
|
||||
@ -19,7 +19,6 @@ import Organizations from "./lists/Organizations";
|
||||
import PortalJobTemplates from "./lists/PortalJobTemplates";
|
||||
import PortalJobs from "./lists/PortalJobs";
|
||||
import ScheduledJobs from "./lists/ScheduledJobs";
|
||||
import Streams from "./lists/Streams";
|
||||
import Templates from "./lists/Templates";
|
||||
|
||||
export
|
||||
@ -38,6 +37,5 @@ export
|
||||
PortalJobTemplates,
|
||||
PortalJobs,
|
||||
ScheduledJobs,
|
||||
Streams,
|
||||
Templates
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user