Skip to content

Commit

Permalink
Add 'Select from Project' wizard to allow project templates/images to…
Browse files Browse the repository at this point in the history
… be imported
  • Loading branch information
jeff-phillips-18 committed Aug 25, 2017
1 parent c9a5d1a commit 977c3aa
Show file tree
Hide file tree
Showing 15 changed files with 568 additions and 120 deletions.
4 changes: 4 additions & 0 deletions app/scripts/controllers/landingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ angular.module('openshiftConsole')
_.set($scope, 'ordering.panelName', 'fromFile');
};

$scope.fromProjectSelected = function() {
_.set($scope, 'ordering.panelName', 'fromProject');
};

AuthService.withUser().then(function() {
var includeTemplates = !_.get(Constants, 'ENABLE_TECH_PREVIEW_FEATURE.template_service_broker');
Catalog.getCatalogItems(includeTemplates).then(_.spread(function(items, errorMessage) {
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/directives/processTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
bindings: {
template: '<',
project: '<',
onProjectSelected: '<',
availableProjects: '<',
prefillParameters: '<',
isDialog: '<'
},
Expand Down
193 changes: 190 additions & 3 deletions app/scripts/directives/processTemplateDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,49 @@
angular.module('openshiftConsole').component('processTemplateDialog', {
controller: [
'$scope',
'$filter',
'$timeout',
'Catalog',
'DataService',
'KeywordService',
'NotificationsService',
'ProjectsService',
'RecentlyViewedProjectsService',
ProcessTemplateDialog
],
controllerAs: '$ctrl',
bindings: {
template: '<',
project: '<',
useProjectTemplate: '<',
onDialogClosed: '&'
},
templateUrl: 'views/directives/process-template-dialog.html'
});

function ProcessTemplateDialog($scope, DataService) {
function ProcessTemplateDialog($scope,
$filter,
$timeout,
Catalog,
DataService,
KeywordService,
NotificationsService,
ProjectsService,
RecentlyViewedProjectsService) {
var ctrl = this;
var validityWatcher;
var projectListWatcher;
var MAX_PROJECTS_TO_WATCH = 250;

ctrl.selectStep = {
id: 'projectTemplates',
label: 'Selection',
view: 'views/directives/process-template-dialog/process-template-select.html',
hidden: ctrl.useProjectTemplate !== true,
allowed: true,
valid: false,
onShow: showSelect
};

ctrl.configStep = {
id: 'configuration',
Expand All @@ -43,6 +72,34 @@

ctrl.$onInit = function() {
ctrl.loginBaseUrl = DataService.openshiftAPIBaseUrl();
ctrl.preSelectedProject = ctrl.selectedProject = ctrl.project;
listProjects();

ctrl.projectEmptyState = {
icon: 'pficon pficon-info',
title: 'No Project Selected',
info: 'Please select a project from the dropdown to load Templates and Images from that project'
};

ctrl.templatesEmptyState = {
icon: 'pficon pficon-info',
title: 'No Templates or Images',
info: 'The selected project has no templates or images available to import'
};

ctrl.filterConfig = {
fields: [
{
id: 'keyword',
title: 'Keyword',
placeholder: 'Filter by Keyword',
filterType: 'text'
}
],
resultsCount: 0,
appliedFilters: [],
onFilterChange: filterChange
};
};

ctrl.$onChanges = function(changes) {
Expand All @@ -52,6 +109,9 @@
ctrl.iconClass = getIconClass();
}
}
if (changes.useProjectTemplate) {
initializeSteps();
}
};

$scope.$on('templateInstantiated', function(event, message) {
Expand All @@ -61,6 +121,9 @@

ctrl.$onDestroy = function() {
clearValidityWatcher();
if (projectListWatcher) {
DataService.unwatch(projectListWatcher);
}
};

ctrl.next = function(step) {
Expand All @@ -85,13 +148,49 @@
}
};

ctrl.onProjectSelected = function(project) {
ctrl.selectedProject = project;
ctrl.configStep.valid = $scope.$ctrl.form.$valid && ctrl.selectedProject;
};

ctrl.templateSelected = function(template) {
ctrl.selectedTemplate = template;
ctrl.template = _.get(template, 'resource');
ctrl.selectStep.valid = !!template;
};

ctrl.templateProjectChange = function () {
ctrl.templateProjectName = _.get(ctrl.templateProject, 'metadata.name');

// Get the templates for the selected project
ctrl.catalogItems = {};
ctrl.templateSelected();

Catalog.getProjectCatalogItems(ctrl.templateProjectName).then( _.spread(function(catalogServiceItems, errorMessage) {
ctrl.catalogItems = catalogServiceItems;
ctrl.totalCount = ctrl.catalogItems.length;
filterItems();

if (errorMessage) {
NotificationsService.addNotification(
{
type: "error",
message: errorMessage
}
);
}
}));
};

function getIconClass() {
var icon = _.get(ctrl, 'template.metadata.annotations.iconClass', 'fa fa-clone');
return (icon.indexOf('icon-') !== -1) ? 'font-icon ' + icon : icon;
}

function initializeSteps() {
ctrl.steps = [ctrl.configStep, ctrl.resultsStep];
if (!ctrl.steps) {
ctrl.steps = [ctrl.selectStep, ctrl.configStep, ctrl.resultsStep];
}
}

function clearValidityWatcher() {
Expand All @@ -101,19 +200,30 @@
}
}

function showSelect() {
ctrl.selectStep.selected = true;
ctrl.configStep.selected = false;
ctrl.resultsStep.selected = false;
ctrl.nextTitle = "Next >";
clearValidityWatcher();
listProjects();
}

function showConfig() {
ctrl.selectStep.selected = false;
ctrl.configStep.selected = true;
ctrl.resultsStep.selected = false;
ctrl.nextTitle = "Create";
ctrl.resultsStep.allowed = ctrl.configStep.valid;

validityWatcher = $scope.$watch("$ctrl.form.$valid", function(isValid) {
ctrl.configStep.valid = isValid;
ctrl.configStep.valid = isValid && ctrl.selectedProject;
ctrl.resultsStep.allowed = isValid;
});
}

function showResults() {
ctrl.selectStep.selected = false;
ctrl.configStep.selected = false;
ctrl.resultsStep.selected = true;
ctrl.nextTitle = "Close";
Expand All @@ -124,5 +234,82 @@
function instantiateTemplate() {
$scope.$broadcast('instantiateTemplate');
}

function filterForKeywords (searchText, items) {
return KeywordService.filterForKeywords(items, ['name', 'tags'], KeywordService.generateKeywords(searchText));
}

function filterChange (filters) {
// only use filters which have a filter criteria 'value'
// prevents applying an empty keyword filter
// TODO: can remove the following line of code after angular-patternfly issue is fixed:
// https://github.com/patternfly/angular-patternfly/issues/509
filters = _.filter(filters, 'value');

ctrl.filterConfig.appliedFilters = filters;
filterItems();
}

function filterItems() {
ctrl.filteredItems = ctrl.catalogItems;
if (ctrl.filterConfig.appliedFilters && ctrl.filterConfig.appliedFilters.length > 0) {
_.each(ctrl.filterConfig.appliedFilters, function(filter) {
ctrl.filteredItems = filterForKeywords(filter.value, ctrl.filteredItems);
});
}

updateFilterControls();

// Deselect the currently selected template if it was filtered out
if (!_.includes(ctrl.filteredItems, ctrl.selectedTemplate)) {
ctrl.templateSelected();
}
}

function updateFilterControls() {
$timeout(function() {
if (ctrl.filterConfig.appliedFilters.length > 0) {
ctrl.filterConfig.resultsCount = ctrl.filteredItems.length;
$('.toolbar-pf-results h5').text(ctrl.filterConfig.resultsCount + ' of ' + ctrl.totalCount + ' items');
} else {
$('.toolbar-pf-results h5').text(ctrl.totalCount + (ctrl.totalCount === 1 ? ' item' : ' items'));
if (ctrl.totalCount <= 1) {
$('.filter-pf.filter-fields input').attr('disabled', '');
} else {
$('.filter-pf.filter-fields input').removeAttr("disabled");
}
}
}, 0);
}

var updateProjects = function() {
var filteredProjects = _.reject(ctrl.unfilteredProjects, 'metadata.deletionTimestamp');
var projects = _.sortBy(filteredProjects, $filter('displayName'));
ctrl.searchEnabled = !_.isEmpty(filteredProjects);

ctrl.templateProjects = RecentlyViewedProjectsService.orderByMostRecentlyViewed(projects);
};

var updateProjectData = function(projectData) {
ctrl.unfilteredProjects = _.toArray(projectData.by("metadata.name"));
updateProjects();
};

function listProjects() {
if (!projectListWatcher) {
ProjectsService.list().then(function(projectData) {
$scope.isProjectListIncomplete = ProjectsService.isProjectListIncomplete();
updateProjectData(projectData);

if (!$scope.isProjectListIncomplete && _.size(ctrl.unfilteredProjects) <= MAX_PROJECTS_TO_WATCH) {
projectListWatcher = ProjectsService.watch($scope, updateProjectData);
}
}, function() {
$scope.isProjectListIncomplete = true;
ctrl.unfilteredProjects = [];
updateProjects();
});
}
}
}
})();
47 changes: 47 additions & 0 deletions app/styles/_core.less
Original file line number Diff line number Diff line change
Expand Up @@ -1259,3 +1259,50 @@ pre.clipped {
width: 30px;
}
}

.order-service-config {
.order-services-filter {
margin-left: 0;
}
.blank-slate-pf {
margin-bottom: 0;
}
.select-project-for-template {
border-bottom: solid 1px @color-pf-black-300;
padding-bottom: 10px;

> h2 {
margin-bottom: 20px;
margin-top: 0;
}
.ui-select-container {
display: inline-block;
width: 275px;
}
}
.services-item {
&.show-selection {
// Clear focus settings, keep before active settings
&:focus {
color: @text-color;
.services-item-icon:after {
border: none;
}

.services-item-name {
color: @text-color;
}
}
&.active {
color: @link-hover-color;
.services-item-icon:after {
border: 2px solid @link-color;
}
.services-item-name {
color: @link-hover-color;
}
}
}
}
}

2 changes: 2 additions & 0 deletions app/views/directives/header/project-header.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<li ng-if-start="catalogLandingPageEnabled" role="menuitem"><a href="/">Browse Catalog</a></li>
<li role="menuitem"><a href="" ng-click="showOrderingPanel('deployImage')">Deploy Image</a></li>
<li ng-if-end role="menuitem"><a href="" ng-click="showOrderingPanel('fromFile')">Import YAML / JSON</a></li>
<li ng-if-end role="menuitem"><a href="" ng-click="showOrderingPanel('fromProject')">Select from Project</a></li>
</ul>
</div>
<div row
Expand All @@ -51,4 +52,5 @@
<overlay-panel show-panel="ordering.panelName" show-close="true" handle-close="closeOrderingPanel">
<deploy-image-dialog ng-if="ordering.panelName === 'deployImage'" project="project" context="context" on-dialog-closed="closeOrderingPanel"></deploy-image-dialog>
<from-file-dialog ng-if="ordering.panelName === 'fromFile'" project="project" context="context" on-dialog-closed="closeOrderingPanel"></from-file-dialog>
<process-template-dialog ng-if="ordering.panelName === 'fromProject'" project="project" use-project-template="true" on-dialog-closed="closeOrderingPanel"></process-template-dialog>
</overlay-panel>
8 changes: 4 additions & 4 deletions app/views/directives/process-template-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<pf-wizard
hide-header="true"
hide-sidebar="true"
hide-back-button="true"
hide-back-button="!$ctrl.useProjectTemplate"
step-class="order-service-wizard-step"
wizard-ready="$ctrl.wizardReady"
next-title="$ctrl.nextTitle"
Expand All @@ -11,7 +11,7 @@
on-cancel="$ctrl.close()"
wizard-done="$ctrl.wizardDone"
current-step="$ctrl.currentStep"
class="pf-wizard-no-back">
ng-class="{'pf-wizard-no-back': !$ctrl.useProjectTemplate}">
<pf-wizard-step ng-repeat="step in $ctrl.steps track by step.id"
step-title="{{step.label}}"
wz-disabled="{{step.hidden}}"
Expand All @@ -22,7 +22,7 @@
step-id="{{step.id}}"
step-priority="{{$index}}">
<div class="wizard-pf-main-inner-shadow-covers">
<div class="order-service-details">
<div class="order-service-details" ng-if="!$ctrl.selectStep.selected">
<div class="order-service-details-top">
<div class="service-icon">
<span class="icon {{$ctrl.iconClass}}"></span>
Expand All @@ -42,7 +42,7 @@
<p ng-bind-html="$ctrl.template | description | linky : '_blank'" class="description"></p>
</div>
</div>
<div class="order-service-config">
<div class="order-service-config" ng-class="{'order-service-config-single-column': $ctrl.selectStep.selected}">
<div ng-if="step.selected" ng-include="step.view" class="wizard-pf-main-form-contents"></div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="osc-form">
<form name="$ctrl.form">
<process-template template="$ctrl.template" is-dialog="true"></process-template>
<process-template template="$ctrl.template" project="$ctrl.preSelectedProject" on-project-selected="$ctrl.onProjectSelected" available-projects="$ctrl.unfilteredProjects" is-dialog="true"></process-template>
</form>
</div>
Loading

0 comments on commit 977c3aa

Please sign in to comment.