Merge pull request #7239 from mabashian/portal-mode-jobs

Split portal mode jobs into two separate states
This commit is contained in:
Michael Abashian 2017-07-21 11:54:00 -04:00 committed by GitHub
commit 6399ea4215
18 changed files with 133 additions and 75 deletions

View File

@ -7,7 +7,6 @@
export default ['i18n', function(i18n) {
return {
searchSize: 'col-lg-12 col-md-12 col-sm-12 col-xs-12',
name: 'teams',
iterator: 'team',
listTitleBadge: false,

View File

@ -9,7 +9,6 @@ export default ['i18n', function(i18n) {
name: 'hosts',
iterator: 'host',
editTitle: '{{ selected_group }}',
searchSize: 'col-lg-12 col-md-12 col-sm-12 col-xs-12',
singleSearchParam: {
param: 'host_filter'
},

View File

@ -154,7 +154,7 @@
</a>
<a class="MainMenu-item MainMenu-item--notMobile MainMenu-item--right"
id="main_menu_portal_link"
ng-href="/#/portal"
ng-href="/#/portal/myjobs"
ng-hide="licenseMissing"
ng-class="{'is-currentRoute' : isCurrentState('portalMode'), 'is-loggedOut' : !current_user || !current_user.username}"
aw-tool-tip="{{'My View'|translate}}"

View File

@ -67,7 +67,6 @@ export default [{
ngClick: 'addUsers()'
}
};
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
return list;
}]
}
@ -107,7 +106,6 @@ export default [{
delete list.fieldActions.delete;
list.basePath = `${GetBasePath('organizations')}${$stateParams.organization_id}/teams`;
list.emptyListText = "This list is populated by teams added from the&nbsp;<a ui-sref='teams.add'>Teams</a>&nbsp;section";
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
return list;
}],
OrgTeamsDataset: ['OrgTeamList', 'QuerySet', '$stateParams', 'GetBasePath',
@ -153,7 +151,6 @@ export default [{
delete list.fieldActions.delete;
list.basePath = `${GetBasePath('organizations')}${$stateParams.organization_id}/inventories`;
list.emptyListText = "This list is populated by inventories added from the&nbsp;<a ui-sref='inventories.add'>Inventories</a>&nbsp;section";
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
return list;
}],
OrgInventoryDataset: ['OrgInventoryList', 'QuerySet', '$stateParams', 'GetBasePath',
@ -204,7 +201,6 @@ export default [{
delete list.fieldActions.delete;
list.basePath = `${GetBasePath('organizations')}${$stateParams.organization_id}/projects`;
list.emptyListText = "This list is populated by projects added from the&nbsp;<a ui-sref='projects.add'>Projects</a>&nbsp;section";
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
return list;
}],
OrgProjectDataset: ['OrgProjectList', 'QuerySet', '$stateParams', 'GetBasePath',
@ -265,7 +261,6 @@ export default [{
delete list.fields.type;
list.listTitle = N_('Job Templates');
list.emptyListText = "This list is populated by job templates added from the&nbsp;<a ui-sref='templates.addJobTemplate'>Job Templates</a>&nbsp;section";
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
list.iterator = 'template';
list.name = 'job_templates';
list.basePath = "job_templates";
@ -349,7 +344,6 @@ export default [{
ngClick: 'addUsers()'
}
};
list.searchSize = "col-lg-12 col-md-12 col-sm-12 col-xs-12";
list.listTitle = 'Admins';
return list;
}]

View File

@ -27,7 +27,6 @@
</div>
<!-- smart-search directive bindings:
djangoModel: '@', // one-way, interpolated
searchSize: '@',
basePath: '@',
iterator: '@',
dataset: '=', // two-way

View File

@ -0,0 +1,49 @@
import { PortalModeJobsController } from '../portal-mode-jobs.controller';
// Using multiple named views requires a parent layout
// https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
export default {
name: 'portalMode.allJobs',
url: '/alljobs?{job_search:queryset}',
ncyBreadcrumb: {
skip: true
},
params: {
job_search: {
value: {
page_size: '20',
order_by: '-finished'
},
dynamic: true
}
},
data: {
socket: {
"groups": {
"jobs": ["status_changed"]
}
}
},
views: {
'jobs@portalMode': {
templateProvider: function(PortalJobsList, generateList) {
let html = generateList.build({
list: PortalJobsList,
mode: 'edit'
});
return html;
},
controller: PortalModeJobsController
}
},
resolve: {
jobsDataset: ['PortalJobsList', 'QuerySet', '$rootScope', '$stateParams', 'GetBasePath',
function(list, qs, $rootScope, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return $rootScope.loginConfig.promise.then(() => {
return qs.search(path, $stateParams[`${list.iterator}_search`]);
});
}
]
}
};

View File

@ -0,0 +1,51 @@
import { PortalModeJobsController } from '../portal-mode-jobs.controller';
// Using multiple named views requires a parent layout
// https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
export default {
name: 'portalMode.myJobs',
url: '/myjobs?{job_search:queryset}',
ncyBreadcrumb: {
skip: true
},
params: {
job_search: {
value: {
page_size: '20',
order_by: '-finished',
created_by: null
},
dynamic: true
}
},
data: {
socket: {
"groups": {
"jobs": ["status_changed"]
}
}
},
views: {
'jobs@portalMode': {
templateProvider: function(PortalJobsList, generateList) {
let html = generateList.build({
list: PortalJobsList,
mode: 'edit'
});
return html;
},
controller: PortalModeJobsController
}
},
resolve: {
jobsDataset: ['PortalJobsList', 'QuerySet', '$rootScope', '$stateParams', 'GetBasePath',
function(list, qs, $rootScope, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return $rootScope.loginConfig.promise.then(() => {
$stateParams[`${list.iterator}_search`].created_by = $rootScope.current_user.id;
return qs.search(path, $stateParams[`${list.iterator}_search`]);
});
}
]
}
};

View File

@ -5,6 +5,8 @@
*************************************************/
import route from './portal-mode.route';
import myJobsRoute from './jobs/portal-mode-my-jobs.route';
import allJobsRoute from './jobs/portal-mode-all-jobs.route';
import PortalJobsList from './portal-jobs.list';
import PortalJobTemplateList from './portal-job-templates.list';
@ -14,4 +16,6 @@ export default
.factory('PortalJobTemplateList', PortalJobTemplateList)
.run(['$stateExtender', function($stateExtender){
$stateExtender.addState(route);
$stateExtender.addState(myJobsRoute);
$stateExtender.addState(allJobsRoute);
}]);

View File

@ -16,12 +16,13 @@ export default ['i18n', function(i18n) {
hover: true,
well: true,
emptyListText: i18n._('There are no job templates to display at this time'),
searchBarFullWidth: true,
fields: {
name: {
key: true,
label: i18n._('Name'),
columnClass: 'col-lg-5 col-md-5 col-sm-9 col-xs-8',
linkTo: '/#/templates/{{job_template.id}}',
linkTo: '/#/templates/job_template/{{job_template.id}}',
awToolTip: '{{job_template.description}}',
dataPlacement: 'top'
}

View File

@ -16,6 +16,7 @@ export default ['i18n', function(i18n) {
well: true,
listTitle: i18n._('JOBS'),
emptyListText: i18n._('There are no jobs to display at this time'),
searchBarFullWidth: true,
fields: {
status: {

View File

@ -29,10 +29,6 @@ export function PortalModeJobsController($scope, $state, qs, GetBasePath, Portal
$scope.iterator = list.iterator;
}
$scope.$on('filterPortalJobs', function(e, data){
init(data);
});
$scope.refresh = function() {
$state.go('.', null, {reload: true});
};

View File

@ -8,13 +8,13 @@
<div class="PortalMode-filterHolder">
<div class="FormToggle-container">
<div class="btn-group">
<button ng-class="{'btn-primary': activeFilter === 'user', 'Button-primary--hollow': activeFilter !== 'user'}"
<button ng-class="{'btn-primary': $state.is('portalMode.myJobs'), 'Button-primary--hollow': $state.is('portalMode.allJobs')}"
ng-click='filterUser()'
class="btn btn-xs"
translate>
My Jobs
</button>
<button ng-class="{'btn-primary': activeFilter === 'all', 'Button-primary--hollow': activeFilter !== 'all'}"
<button ng-class="{'btn-primary': $state.is('portalMode.allJobs'), 'Button-primary--hollow': $state.is('portalMode.myJobs')}"
ng-click='filterAll()'
class="btn btn-xs"
translate>
@ -23,7 +23,7 @@
</div>
</div>
<div class="PortalMode-refresh">
<button id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" class="btn List-buttonDefault"
<button id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" class="btn List-buttonDefault"
ng-click="refresh()" ng-show="socketStatus == 'error'">
<span>REFRESH</span>
</button>

View File

@ -1,7 +1,12 @@
@import "./client/src/shared/layouts/one-plus-one.less";
.PortalMode-container{
.OnePlusOne-container;
display: flex;
flex-direction: row;
@media screen and(max-width: 900px){
flex-direction: column;
height: 100%;
}
}
.PortalMode-panel--left{

View File

@ -1,28 +1,23 @@
import { templateUrl } from '../shared/template-url/template-url.factory';
import { PortalModeJobTemplatesController } from './portal-mode-job-templates.controller';
import { PortalModeJobsController } from './portal-mode-jobs.controller';
import { N_ } from '../i18n';
// Using multiple named views requires a parent layout
// https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
export default {
name: 'portalMode',
url: '/portal?{group_search:queryset}{host_search:queryset}',
url: '/portal?{job_template_search:queryset}',
abstract: true,
ncyBreadcrumb: {
label: N_('MY VIEW')
},
params: {
job_search: {
value: {
page_size: '20',
order_by: '-finished'
}
},
job_template_search: {
value: {
page_size: '20',
order_by: 'name'
}
},
dynamic: true
}
},
data: {
@ -35,31 +30,15 @@ export default {
views: {
'@': {
templateUrl: templateUrl('portal-mode/portal-mode-layout'),
controller: ['$scope', '$rootScope', '$state', '$stateParams', 'GetBasePath', 'QuerySet',
function($scope, $rootScope, $state, $stateParams, GetBasePath, qs) {
let path;
init();
function init() {
$scope.activeFilter = parseInt($stateParams.job_search.created_by) === $rootScope.current_user.id ? 'user' : 'all';
}
controller: ['$scope', '$state',
function($scope, $state) {
$scope.filterUser = function() {
$scope.activeFilter = 'user';
path = GetBasePath('jobs');
$stateParams.job_search.created_by = $rootScope.current_user.id;
qs.search(path, $stateParams.job_search).then((response) => {
$scope.$broadcast('filterPortalJobs', response);
});
$state.go('portalMode.myJobs');
};
$scope.filterAll = function() {
$scope.activeFilter = 'all';
delete $stateParams.job_search.created_by;
path = GetBasePath('jobs');
qs.search(path, $stateParams.job_search).then((response) => {
$scope.$broadcast('filterPortalJobs', response);
});
$state.go('portalMode.allJobs');
};
}
]
@ -74,28 +53,9 @@ export default {
return html;
},
controller: PortalModeJobTemplatesController
},
'jobs@portalMode': {
templateProvider: function(PortalJobsList, generateList) {
let html = generateList.build({
list: PortalJobsList,
mode: 'edit'
});
return html;
},
controller: PortalModeJobsController
}
},
resolve: {
jobsDataset: ['PortalJobsList', 'QuerySet', '$rootScope', '$stateParams', 'GetBasePath',
function(list, qs, $rootScope, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return $rootScope.loginConfig.promise.then(() => {
$stateParams[`${list.iterator}_search`].created_by = $rootScope.current_user.id;
return qs.search(path, $stateParams[`${list.iterator}_search`]);
});
}
],
job_templatesDataset: ['PortalJobTemplateList', 'QuerySet', '$stateParams', 'GetBasePath',
function(list, qs, $stateParams, GetBasePath) {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);

View File

@ -23,7 +23,6 @@
* | mode | Yes | One of 'edit', 'lookup', 'select', or 'summary'. Generally this will be 'edit'. helpers/Lookup.js uses 'lookup' to generate the lookup dialog. The 'select' option is used in certain controllers when multiple objects are being added to a parent object. For example, building a select list of Users that can be added to an Oranization. 'summary' is no longer used. |
* | scope | | If the HTML will be injected into the DOM by list generator, pass in an optional $scope to be used in conjuction with $compile. The list will be associated with the scope value. Otherwise, the scope of the DOM element will be fetched passed to $compile. |
* | showSearch | | true or false. Set to false, if the search widget should not be included in the generated HTML. |
* | searchSize | | Bootstrap size class (e.g. col-lg-3, col-md-4, col-sm-5, etc.) to apply to the search widget. Defaults to 'col-lg-4 col-md-6 col-sm-8 col-xs-9'. |
*
* #HTML only
*
@ -198,16 +197,12 @@ export default ['$compile', 'Attr', 'Icon',
}
html += (list.searchRowActions) ? "<div class='row'><div class=\"col-lg-8 col-md-8 col-sm-8 col-xs-12\">" : "";
if (list.searchRowActions && !list.searchSize) {
list.searchSize = 'col-lg-7 col-md-12 col-sm-12 col-xs-12';
}
if (options.showSearch === undefined || options.showSearch === true) {
let singleSearchParam = list.singleSearchParam && list.singleSearchParam.param ? `single-search-param="${list.singleSearchParam.param}"` : '';
html += `
<div ng-hide="${list.name}.length === 0 && (searchTags | isEmpty)">
<smart-search
django-model="${list.name}"
search-size="${list.searchSize}"
${singleSearchParam}
base-path="${list.basePath || list.name}"
iterator="${list.iterator}"
@ -216,6 +211,7 @@ export default ['$compile', 'Attr', 'Icon',
collection="${list.name}"
default-params="${list.iterator}_default_params"
query-set="${list.iterator}_queryset"
search-bar-full-width="${list.searchBarFullWidth}"
search-tags="searchTags">
</smart-search>
</div>

View File

@ -17,6 +17,10 @@
width: 50%;
}
.SmartSearch-bar--fullWidth {
width: 100%;
}
.SmartSearch-tags{
padding-left: 0px;
}

View File

@ -8,7 +8,6 @@ export default ['templateUrl',
},
scope: {
djangoModel: '@',
searchSize: '@',
basePath: '@',
iterator: '@',
list: '=',
@ -18,7 +17,8 @@ export default ['templateUrl',
disableSearch: '=',
defaultParams: '=',
querySet: '=',
singleSearchParam: '@'
singleSearchParam: '@',
searchBarFullWidth: '='
},
controller: 'SmartSearchController',
templateUrl: templateUrl('shared/smart-search/smart-search')

View File

@ -1,6 +1,6 @@
<div class="SmartSearch row">
<!-- input -->
<div class="SmartSearch-bar">
<div class="SmartSearch-bar" ng-class="{'SmartSearch-bar--fullWidth': searchBarFullWidth}">
<div class="SmartSearch-searchTermContainer">
<!-- string search input -->
<form name="smartSearch" class="SmartSearch-form" aw-enter-key="addTerm(searchTerm)" novalidate>