From b60d760a9a5005645a06267ce0c1fb614fa0f618 Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Wed, 10 Feb 2016 11:07:21 -0500 Subject: [PATCH] #632 add /management-jobs/card module, replace module managementJobsList with managementJobsCard --- .../management-jobs/card/card.controller.js | 276 ++++++++++++++++++ .../management-jobs/card/card.partial.html | 24 ++ .../src/management-jobs/card/card.route.js | 27 ++ .../client/src/management-jobs/card/main.js | 15 + .../management-jobs/card/mgmtcards.block.less | 117 ++++++++ .../management-jobs/list/list.controller.js | 6 +- .../src/management-jobs/list/list.route.js | 2 +- awx/ui/client/src/management-jobs/main.js | 4 +- 8 files changed, 465 insertions(+), 6 deletions(-) create mode 100644 awx/ui/client/src/management-jobs/card/card.controller.js create mode 100644 awx/ui/client/src/management-jobs/card/card.partial.html create mode 100644 awx/ui/client/src/management-jobs/card/card.route.js create mode 100644 awx/ui/client/src/management-jobs/card/main.js create mode 100644 awx/ui/client/src/management-jobs/card/mgmtcards.block.less diff --git a/awx/ui/client/src/management-jobs/card/card.controller.js b/awx/ui/client/src/management-jobs/card/card.controller.js new file mode 100644 index 0000000000..19f987f502 --- /dev/null +++ b/awx/ui/client/src/management-jobs/card/card.controller.js @@ -0,0 +1,276 @@ +/************************************************* + * Copyright (c) 2015 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + +// import listGenerator from 'tower/shared/list-generator/main'; + +export default + [ 'Wait', '$location' , '$compile', 'CreateDialog', 'generateList', + 'GetBasePath' , 'SearchInit' , 'PaginateInit', + 'SchedulesList', + 'Rest' , 'ProcessErrors', 'managementJobsListObject', '$rootScope', + '$state', 'Stream', '$scope', + function( Wait, $location, $compile, CreateDialog, GenerateList, + GetBasePath, SearchInit, PaginateInit, + SchedulesList, + Rest, ProcessErrors, managementJobsListObject, $rootScope, + $state, Stream, $scope) { + + var defaultUrl = GetBasePath('system_job_templates'); + + var getManagementJobs = function(){ + Rest.setUrl(defaultUrl); + Rest.get() + .success(function(data){ + $scope.mgmtCards = data.results; + Wait('stop'); + }) + .error(function(data, status){ + ProcessErrors($scope, data, status, null, {hdr: 'Error!', + msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status}); + }); + }; + getManagementJobs(); + var scope = $rootScope.$new(), + parent_scope = scope, + list = managementJobsListObject, + view = GenerateList; + scope.cleanupJob = true; + view.inject( list, { + mode: 'edit', + scope: scope, + showSearch: true + }); + + SearchInit({ + scope: scope, + set: 'configure_jobs', + list: list, + url: defaultUrl + }); + + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); + + scope.search(list.iterator); + + scope.showActivity = function () { + Stream({ scope: scope }); + }; + + // Cancel + scope.cancelConfigure = function () { + try { + $('#configure-tower-dialog').dialog('close'); + $("#configure-save-button").remove(); + } + catch(e) { + //ignore + } + if (scope.searchCleanup) { + scope.searchCleanup(); + } + // if (!Empty(parent_scope) && parent_scope.restoreSearch) { + // parent_scope.restoreSearch(); + // } + else { + Wait('stop'); + } + }; + + $scope.submitCleanupJob = function(id, name){ + defaultUrl = GetBasePath('system_job_templates')+id+'/launch/'; + CreateDialog({ + id: 'prompt-for-days-facts', + title: name, + scope: scope, + width: 500, + height: 470, + minWidth: 200, + callback: 'PromptForDaysFacts', + onOpen: function(){ + scope.$watch('prompt_for_days_facts_form.$invalid', function(invalid) { + if (invalid === true) { + $('#prompt-for-days-facts-launch').prop("disabled", true); + } else { + $('#prompt-for-days-facts-launch').prop("disabled", false); + } + }); + + var fieldScope = scope.$parent; + + // set these form elements up on the scope where the form + // is the parent of the current scope + fieldScope.keep_unit_choices = [{ + "label" : "Days", + "value" : "d" + }, + { + "label": "Weeks", + "value" : "w" + }, + { + "label" : "Years", + "value" : "y" + }]; + fieldScope.granularity_keep_unit_choices = [{ + "label" : "Days", + "value" : "d" + }, + { + "label": "Weeks", + "value" : "w" + }, + { + "label" : "Years", + "value" : "y" + }]; + scope.prompt_for_days_facts_form.$setPristine(); + scope.prompt_for_days_facts_form.$invalid = false; + fieldScope.keep_unit = fieldScope.keep_unit_choices[0]; + fieldScope.granularity_keep_unit = fieldScope.granularity_keep_unit_choices[1]; + fieldScope.keep_amount = 30; + fieldScope.granularity_keep_amount = 1; + }, + buttons: [{ + "label": "Cancel", + "onClick": function() { + $(this).dialog('close'); + + }, + "icon": "fa-times", + "class": "btn btn-default", + "id": "prompt-for-days-facts-cancel" + },{ + "label": "Launch", + "onClick": function() { + var extra_vars = { + "older_than": scope.keep_amount+scope.keep_unit.value, + "granularity": scope.granularity_keep_amount+scope.granularity_keep_unit.value + }, + data = {}; + data.extra_vars = JSON.stringify(extra_vars); + + Rest.setUrl(defaultUrl); + Rest.post(data) + .success(function() { + Wait('stop'); + $("#prompt-for-days-facts").dialog("close"); + $("#configure-tower-dialog").dialog('close'); + $location.path('/jobs/'); + }) + .error(function(data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed updating job ' + scope.job_template_id + ' with variables. POST returned: ' + status }); + }); + }, + "icon": "fa-rocket", + "class": "btn btn-primary", + "id": "prompt-for-days-facts-launch" + }] + }); + + if (scope.removePromptForDays) { + scope.removePromptForDays(); + } + scope.removePromptForDays = scope.$on('PromptForDaysFacts', function() { + // $('#configure-tower-dialog').dialog('close'); + $('#prompt-for-days-facts').show(); + $('#prompt-for-days-facts').dialog('open'); + Wait('stop'); + }); + }; + + $scope.submitJob = function (id, name) { + Wait('start'); + if(this.configure_job.job_type === "cleanup_facts"){ + scope.submitCleanupJob(id, name); + } + else { + defaultUrl = GetBasePath('system_job_templates')+id+'/launch/'; + CreateDialog({ + id: 'prompt-for-days' , + title: name, + scope: scope, + width: 500, + height: 300, + minWidth: 200, + callback: 'PromptForDays', + onOpen: function(){ + scope.$watch('prompt_for_days_form.$invalid', function(invalid) { + if (invalid === true) { + $('#prompt-for-days-launch').prop("disabled", true); + } else { + $('#prompt-for-days-launch').prop("disabled", false); + } + }); + + var fieldScope = scope.$parent; + fieldScope.days_to_keep = 30; + scope.prompt_for_days_form.$setPristine(); + scope.prompt_for_days_form.$invalid = false; + }, + buttons: [{ + "label": "Cancel", + "onClick": function() { + $(this).dialog('close'); + + }, + "icon": "fa-times", + "class": "btn btn-default", + "id": "prompt-for-days-cancel" + },{ + "label": "Launch", + "onClick": function() { + var extra_vars = {"days": scope.days_to_keep }, + data = {}; + data.extra_vars = JSON.stringify(extra_vars); + + Rest.setUrl(defaultUrl); + Rest.post(data) + .success(function() { + Wait('stop'); + $("#prompt-for-days").dialog("close"); + // $("#configure-tower-dialog").dialog('close'); + $location.path('/jobs/'); + }) + .error(function(data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed updating job ' + scope.job_template_id + ' with variables. POST returned: ' + status }); + }); + }, + "icon": "fa-rocket", + "class": "btn btn-primary", + "id": "prompt-for-days-launch" + }] + }); + + if (scope.removePromptForDays) { + scope.removePromptForDays(); + } + scope.removePromptForDays = scope.$on('PromptForDays', function() { + // $('#configure-tower-dialog').dialog('close'); + $('#prompt-for-days').show(); + $('#prompt-for-days').dialog('open'); + Wait('stop'); + }); + } + }; + + $scope.configureSchedule = function() { + $state.transitionTo('managementJobsSchedule', { + management_job: this.job_type, + management_job_id: this.card.id + }); + }; + + parent_scope.refreshJobs = function(){ + scope.search(SchedulesList.iterator); + }; + } + ]; diff --git a/awx/ui/client/src/management-jobs/card/card.partial.html b/awx/ui/client/src/management-jobs/card/card.partial.html new file mode 100644 index 0000000000..3b4cfec9ba --- /dev/null +++ b/awx/ui/client/src/management-jobs/card/card.partial.html @@ -0,0 +1,24 @@ +
+
+
+ +
+

{{ card.name }}

+
+ + +
+
+ + +

{{card.description || "Place organization description here"}}

+ +
+
\ No newline at end of file diff --git a/awx/ui/client/src/management-jobs/card/card.route.js b/awx/ui/client/src/management-jobs/card/card.route.js new file mode 100644 index 0000000000..7f177b9b5a --- /dev/null +++ b/awx/ui/client/src/management-jobs/card/card.route.js @@ -0,0 +1,27 @@ +/************************************************* + * Copyright (c) 2015 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + +import {templateUrl} from '../../shared/template-url/template-url.factory'; + +export default { + name: 'managementJobsList', + route: '/management_jobs', + templateUrl: templateUrl('management-jobs/card/card'), + controller: 'managementJobsCardController', + data: { + activityStream: true, + activityStreamTarget: 'management_job' + }, + resolve: { + features: ['FeaturesService', function(FeaturesService) { + return FeaturesService.get(); + }] + }, + ncyBreadcrumb: { + parent: 'setup', + label: 'MANAGEMENT JOBS' + }, +}; diff --git a/awx/ui/client/src/management-jobs/card/main.js b/awx/ui/client/src/management-jobs/card/main.js new file mode 100644 index 0000000000..e21f7f7e73 --- /dev/null +++ b/awx/ui/client/src/management-jobs/card/main.js @@ -0,0 +1,15 @@ +/************************************************* + * Copyright (c) 2015 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + +import route from './card.route'; +import controller from './card.controller'; + +export default + angular.module('managementJobsCard', []) + .controller('managementJobsCardController', controller) + .run(['$stateExtender', function($stateExtender) { + $stateExtender.addState(route); + }]); diff --git a/awx/ui/client/src/management-jobs/card/mgmtcards.block.less b/awx/ui/client/src/management-jobs/card/mgmtcards.block.less new file mode 100644 index 0000000000..66f11e489c --- /dev/null +++ b/awx/ui/client/src/management-jobs/card/mgmtcards.block.less @@ -0,0 +1,117 @@ +/** @define MgmtCards */ + +.MgmtCards { + display: flex; + flex-wrap: wrap; +} + +.MgmtCards-card { + background-color: #fff; + padding: 20px; + padding-bottom: 0px; + border-radius: 5px; + border: 1px solid #e8e8e8; + display: flex; + flex-wrap: wrap; + align-items: baseline; + margin-top: 20px; +} + +.MgmtCards-card--selected { + padding-left: 16px; + border-left: 5px solid #1678C4; +} + +.MgmtCards-header { + display: flex; + flex-wrap: nowrap; + align-items: baseline; + width: 100%; +} + +.MgmtCards-label { + margin-top: 0px; + text-transform: uppercase; + font-size: 14px; + font-weight: bold; + color: #848992; + margin-bottom: 25px; + white-space: nowrap; +} + +.MgmtCards-actionItems { + margin-left: auto; + display: flex; + flex-wrap: nowrap; +} + +.MgmtCards-actionItem { + margin-left: 15px; +} + +.MgmtCards-description { + margin-bottom: 20px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.MgmtCards-links { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.MgmtCards-link { + flex: initial; + width: ~"calc(50% - 20px)"; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin-bottom: 20px; +} + +.MgmtCards-linkBadge { + margin-right: 10px; +} + +@media (min-width: 1179px) { + .MgmtCards-card { + width: ~"calc(25% - 15px)"; + margin-right: 20px; + } + + .MgmtCards-card:nth-child(4n+4) { + margin-right: 0px; + } +} + +@media (min-width: 901px) and (max-width: 1178px) { + .MgmtCards-card { + width: ~"calc(33% - 11px)"; + margin-right: 20px; + } + + .MgmtCards-card:nth-child(3n+3) { + margin-right: 0px; + } +} + +@media (min-width: 616px) and (max-width: 900px) { + .MgmtCards-card { + width: ~"calc(50% - 10px)"; + margin-right: 20px; + } + + .MgmtCards-card:nth-child(2n+2) { + margin-right: 0px; + } +} + +@media (max-width: 615px) { + .MgmtCards-card { + width: 100%; + margin-right: 0px; + } +} diff --git a/awx/ui/client/src/management-jobs/list/list.controller.js b/awx/ui/client/src/management-jobs/list/list.controller.js index fbc098f0b1..f18d3132fb 100644 --- a/awx/ui/client/src/management-jobs/list/list.controller.js +++ b/awx/ui/client/src/management-jobs/list/list.controller.js @@ -17,15 +17,15 @@ export default SchedulesList, Rest, ProcessErrors, managementJobsListObject, $rootScope, $state, Stream) { - + console.log('rootScope ', $rootScope); var scope = $rootScope.$new(), parent_scope = scope, defaultUrl = GetBasePath('system_job_templates'), list = managementJobsListObject, view = GenerateList; - + console.log('managementJobsListObject: ', list, + 'view: ', view); scope.cleanupJob = true; - view.inject( list, { mode: 'edit', scope: scope, diff --git a/awx/ui/client/src/management-jobs/list/list.route.js b/awx/ui/client/src/management-jobs/list/list.route.js index 7301ebffe2..5743517b46 100644 --- a/awx/ui/client/src/management-jobs/list/list.route.js +++ b/awx/ui/client/src/management-jobs/list/list.route.js @@ -9,7 +9,7 @@ import {templateUrl} from '../../shared/template-url/template-url.factory'; export default { name: 'managementJobsList', route: '/management_jobs', - templateUrl: templateUrl('management-jobs/list/list'), + templateUrl: templateUrl('management-jobs/card/card'), controller: 'managementJobsListController', data: { activityStream: true, diff --git a/awx/ui/client/src/management-jobs/main.js b/awx/ui/client/src/management-jobs/main.js index 392e5edd41..b374b84857 100644 --- a/awx/ui/client/src/management-jobs/main.js +++ b/awx/ui/client/src/management-jobs/main.js @@ -4,13 +4,13 @@ * All Rights Reserved *************************************************/ -import managementJobsList from './list/main'; +import managementJobsCard from './card/main'; import managementJobsSchedule from './schedule/main'; import list from './management-jobs.list'; export default angular.module('managementJobs', [ - managementJobsList.name, + managementJobsCard.name, managementJobsSchedule.name ]) .factory('managementJobsListObject', list);