Skip to content
This repository has been archived by the owner on Oct 20, 2021. It is now read-only.

Commit

Permalink
feat(plan): Manage API plan status
Browse files Browse the repository at this point in the history
  • Loading branch information
brasseld authored and aelamrani committed Nov 14, 2016
1 parent 7184029 commit be9019d
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 15 deletions.
13 changes: 13 additions & 0 deletions src/app/api/admin/plans/_apiPlans.scss
Expand Up @@ -24,3 +24,16 @@
margin-bottom: 40px;
}

.strike {
text-decoration: line-through;
}

.italic {
font-style: italic;
}

.md-toolbar-tools {
background: #fafafa;
color: black;
}

79 changes: 77 additions & 2 deletions src/app/api/admin/plans/apiPlans.controller.js
Expand Up @@ -14,19 +14,24 @@
* limitations under the License.
*/
class ApiPlansController {
constructor(resolvedPlans, $mdSidenav, $scope, ApiService, $stateParams, NotificationService, dragularService) {
constructor(resolvedPlans, $mdSidenav, $mdDialog, $scope, ApiService, $stateParams, NotificationService, dragularService) {
'ngInject';
this.plans = resolvedPlans.data;
this.$mdSidenav = $mdSidenav;
this.$mdDialog = $mdDialog;
this.$scope = $scope;
this.ApiService = ApiService;
this.$stateParams = $stateParams;
this.NotificationService = NotificationService;
this.DragularService = dragularService;

this.statusFilters = ['staging', 'published', 'closed'];
this.selectedStatus = ['staging', 'published'];

$scope.planEdit = true;

this.resetPlan();
this.applyFilters();

var that = this;
$scope.configure = function (plan) {
Expand Down Expand Up @@ -91,7 +96,33 @@ class ApiPlansController {
list() {
return this.ApiService.getApiPlans(this.$stateParams.apiId).then(response => {
this.plans = response.data;
return {pages: this.pages};
this.applyFilters();
return {plans: this.plans};
});
}

changeFilter(statusFilter) {
if (statusFilter === 'closed') {
this.selectedStatus.length = 0;
} else {
var idx = this.selectedStatus.indexOf('closed');
if (idx !== -1) {
this.selectedStatus.splice(idx, 1);
}
}

if (_.includes(this.selectedStatus, statusFilter)) {
_.pull(this.selectedStatus, statusFilter);
} else {
this.selectedStatus.push(statusFilter);
}
this.applyFilters();
}

applyFilters() {
var that = this;
this.filteredPlans = _.filter(this.plans, function (plan) {
return _.includes(that.selectedStatus, plan.status);
});
}

Expand Down Expand Up @@ -167,9 +198,53 @@ class ApiPlansController {
that.plans = response.data;
that.$mdSidenav('plan-edit').toggle();
that.$mdSidenav('live-preview').toggle();
that.applyFilters();
});
});
}

close(plan, ev) {
var _this = this;

this.ApiService.getPlanSubscriptions(this.$stateParams.apiId, plan.id).then(function(response) {
_this.$mdDialog.show({
controller: 'DialogClosePlanController',
templateUrl: 'app/api/admin/plans/closePlan.dialog.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
apiId: _this.$stateParams.apiId,
plan: plan,
subscriptions: response.data.length
}).then(function (plan) {
if (plan) {
_this.list();
}
}, function() {
// You cancelled the dialog
});
});
}

publish(plan, ev) {
var _this = this;

this.$mdDialog.show({
controller: 'DialogPublishPlanController',
templateUrl: 'app/api/admin/plans/publishPlan.dialog.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
apiId: this.$stateParams.apiId,
plan: plan
}).then(function (plan) {
if (plan) {
_this.list();
}
}, function() {
// You cancelled the dialog
});
}
}

export default ApiPlansController;
62 changes: 51 additions & 11 deletions src/app/api/admin/plans/apiPlans.html
Expand Up @@ -15,16 +15,54 @@
limitations under the License.
-->
<div ng-init="apiPlansCtrl.init()">
<div layout="row" layout-align="center" layout-wrap class="plans">
<div flex-xs="100" flex-sm="50" flex="33" flex-lg="25" flex-xl="20" ng-repeat="plan in apiPlansCtrl.plans | orderBy:'order'"
<div ng-init="apiPlansCtrl.init()" layout="column">

<div>
<span class="md-headline" style="padding: 24px 16px 16px;">Plans</span>

<div class="btn-group pull-right">
<button class="btn btn-default" ng-class="{'active': apiPlansCtrl.selectedStatus.indexOf(statusFilter) !== -1}"
ng-click="apiPlansCtrl.changeFilter(statusFilter)" type="button"
ng-repeat="statusFilter in apiPlansCtrl.statusFilters" style="text-transform: capitalize;">
{{statusFilter}}
</button>
</div>
</div>

<div layout="column" flex>
<div layout="row" layout-align="center" layout-wrap class="plans">
<div flex-xs="100" flex-sm="50" flex="33" flex-lg="25" flex-xl="20" ng-repeat="plan in apiPlansCtrl.filteredPlans | orderBy:'order'"
layout="row" layout-align="center"><md-card class="gravitee-card gravitee-plan-box">
<md-card-header>
<h3 layout-padding>{{plan.name}}</h3>
<md-button ng-click="configure(plan)" class="md-icon-button" aria-label="Configure">
<md-tooltip md-direction="top">Configure this page</md-tooltip>
<ng-md-icon style="top: 0;" icon="settings"></ng-md-icon>
</md-button>
<md-toolbar>
<div class="md-toolbar-tools">
<h3 ng-class="{italic: plan.status === 'staging', strike: plan.status === 'closed'}" layout-padding>{{plan.name}}</h3>
<span flex></span>
<md-fab-speed-dial md-direction="down" md-open="false" class="md-scale md-fab-bottom-right"
style="right: -20px;top: 10px;" ng-if="plan.status !== 'closed'">
<md-fab-trigger>
<md-button class="md-fab md-mini md-primary" aria-label="Expand">
<ng-md-icon icon="more_vert"></ng-md-icon>
</md-button>
</md-fab-trigger>

<md-fab-actions>
<md-button ng-if="plan.status !== 'closed'" ng-click="apiPlansCtrl.close(plan)" class="md-fab md-raised md-mini" aria-label="Close">
<md-tooltip md-direction="top">Close this plan</md-tooltip>
<ng-md-icon style="fill: rgb(255,87,34);" icon="close"></ng-md-icon>
</md-button>
<md-button ng-if="plan.status !== 'closed'" ng-click="configure(plan)" class="md-fab md-raised md-mini" aria-label="Configure">
<md-tooltip md-direction="top">Configure this plan</md-tooltip>
<ng-md-icon style="fill: #7a8288;" icon="settings"></ng-md-icon>
</md-button>
<md-button ng-if="plan.status === 'staging'" ng-click="apiPlansCtrl.publish(plan)" class="md-fab md-raised md-mini" aria-label="Publish">
<md-tooltip md-direction="top">Publish this plan</md-tooltip>
<ng-md-icon style="fill: green;" icon="publish"></ng-md-icon>
</md-button>
</md-fab-actions>
</md-fab-speed-dial>
</div>
</md-toolbar>
</md-card-header>
<md-divider></md-divider>
<md-card-content layout="column">
Expand All @@ -46,9 +84,11 @@ <h5 class="gravitee-plan-content">{{characteristic}}</h5>
</md-card-footer>
</md-card>
</div>
</div>
<div layout="row" layout-align="center" layout-wrap>
<span ng-if="apiPlansCtrl.plans.length != 0"><ng-md-icon icon="info" style="fill: #b1bdc5;"></ng-md-icon> Plans can be re-ordered by drag & dropping them.</span>
</div>

<div layout="row" layout-align="center" layout-wrap>
<span ng-if="apiPlansCtrl.plans.length != 0"><ng-md-icon icon="info" style="fill: #b1bdc5;"></ng-md-icon> Plans can be re-ordered by dragging & dropping them.</span>
</div>
</div>
</div>

Expand Down
47 changes: 47 additions & 0 deletions src/app/api/admin/plans/closePlan.dialog.html
@@ -0,0 +1,47 @@
<!--
Copyright (C) 2015 The Gravitee team (http://gravitee.io)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<md-dialog aria-label="Close plan" style="width: 60%">
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Close plan</h2>
<span flex></span>
<md-button class="md-icon-button" aria-label="Hide dialog" ng-click="hide()">
<ng-md-icon icon="close"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-dialog-content>
<div class="md-dialog-content">
<h5 ng-if="subscriptions == 0">No subscription is associated to this plan. You can delete it safely.</h5>
<h5 ng-if="subscriptions > 0">There are <code>{{subscriptions}}</code> subscriptions associated to this plan.</h5>
<p ng-if="subscriptions > 0">
By closing this plan, all relative subscriptions will also be closed and associated api-keys will be no longer
available.
</p>
</div>
</md-dialog-content>

<md-dialog-actions layout="row">
<md-button type="button" ng-click="hide()" class="md-primary" md-autofocus>
Cancel
</md-button>
<md-button type="submit" class="md-primary" ng-click="close()">
{{subscriptions == 0 ? 'Delete' : 'Close'}}
</md-button>
</md-dialog-actions>
</md-dialog>
48 changes: 48 additions & 0 deletions src/app/api/admin/plans/closePlanDialog.controller.js
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function DialogClosePlanController($scope, $mdDialog, ApiService, NotificationService, apiId, plan, subscriptions) {
'ngInject';

$scope.apiId = apiId;
$scope.plan = plan;
$scope.subscriptions = subscriptions;

$scope.hide = function () {
$mdDialog.cancel();
};

$scope.close = function () {
if ($scope.subscriptions === 0) {
ApiService.deletePlan($scope.apiId, $scope.plan.id).then(function() {
NotificationService.show('Plan ' + plan.name + ' has been deleted');
}).catch(function (error) {
NotificationService.show('Error while deleting plan ' + plan.name);
$scope.error = error;
});
} else {
ApiService.closePlan($scope.apiId, $scope.plan.id).then(function() {
NotificationService.show('Plan ' + plan.name + ' has been closed');
}).catch(function (error) {
NotificationService.show('Error while closing plan ' + plan.name);
$scope.error = error;
});
}

$mdDialog.hide($scope.plan);
};
}

export default DialogClosePlanController;
45 changes: 45 additions & 0 deletions src/app/api/admin/plans/publishPlan.dialog.html
@@ -0,0 +1,45 @@
<!--
Copyright (C) 2015 The Gravitee team (http://gravitee.io)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<md-dialog aria-label="Publish plan" style="width: 60%">
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Publish plan</h2>
<span flex></span>
<md-button class="md-icon-button" aria-label="Hide dialog" ng-click="hide()">
<ng-md-icon icon="close"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-dialog-content>
<div class="md-dialog-content">
<h5>Would you like to publish plan <code>{{plan.name}}</code> ?</h5>
<p>
By publishing this plan, users will now be able to subscribe to it.
</p>
</div>
</md-dialog-content>

<md-dialog-actions layout="row">
<md-button type="button" ng-click="hide()" class="md-primary" md-autofocus>
Cancel
</md-button>
<md-button type="submit" class="md-primary" ng-click="publish()">
Publish
</md-button>
</md-dialog-actions>
</md-dialog>
38 changes: 38 additions & 0 deletions src/app/api/admin/plans/publishPlanDialog.controller.js
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function DialogPublishPlanController($scope, $mdDialog, ApiService, NotificationService, apiId, plan) {
'ngInject';

$scope.apiId = apiId;
$scope.plan = plan;

$scope.hide = function () {
$mdDialog.cancel();
};

$scope.publish = function () {
ApiService.publishPlan($scope.apiId, $scope.plan.id).then(function() {
NotificationService.show('Plan ' + plan.name + ' has been published');
}).catch(function (error) {
NotificationService.show('Error while publishing plan ' + plan.name);
$scope.error = error;
});

$mdDialog.hide($scope.plan);
};
}

export default DialogPublishPlanController;

0 comments on commit be9019d

Please sign in to comment.