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

Commit

Permalink
feat: Implementation of rating of APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
aelamrani committed Nov 12, 2017
1 parent 08c0465 commit d42ff8a
Show file tree
Hide file tree
Showing 32 changed files with 810 additions and 98 deletions.
2 changes: 1 addition & 1 deletion build.json
@@ -1,3 +1,3 @@
{
"version": "1.10.4"
"version": "1.11.0-SNAPSHOT"
}
3 changes: 3 additions & 0 deletions constants.json
Expand Up @@ -18,5 +18,8 @@
},
"support": {
"enabled": false
},
"rating": {
"enabled": true
}
}
4 changes: 4 additions & 0 deletions constants.tpl.json
Expand Up @@ -43,5 +43,9 @@
// Enable the creation of support tickets
"support": {
"enabled": false
},
// Enable rating on APIs
"rating": {
"enabled": false
}
}
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "gravitee-management-webui",
"version": "1.10.4",
"version": "1.11.0-SNAPSHOT",
"description": "Gravitee.io APIM - Portal",
"dependencies": {
"angular": "^1.5.0",
Expand Down
Binary file added src/assets/stars.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/emptystate/emptystate.directive.ts
Expand Up @@ -24,7 +24,8 @@ class EmptyStateDirective {
model: '@model',
message: '@message',
subMessage: '@subMessage',
createMode: '='
createMode: '=',
fill: '@fill'
},
template: require('./emptystate.html')
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/emptystate/emptystate.html
Expand Up @@ -16,7 +16,7 @@
-->
<div layout="column" flex layout-align="center center" style="color: #424E5A;">
<ng-md-icon icon="{{icon}}" style="fill: #cdcccc;" size="120"></ng-md-icon>
<ng-md-icon icon="{{icon}}" ng-style="{'fill':fill?fill:'#cdcccc'}" size="120"></ng-md-icon>
<h2>{{message}}</h2>
<div>
<h5>{{subMessage}}</h5>
Expand Down
21 changes: 18 additions & 3 deletions src/index.scss
Expand Up @@ -366,12 +366,12 @@ md-list-item::before {
}
}


.api-box {
width: 98%;
min-width: 320px;
max-width: 480px;
margin: 14px;
outline: none;
}

.apis-box {
Expand Down Expand Up @@ -472,9 +472,24 @@ md-card.no-box-shadow {
}

.gv-button-toggled {
background-color: rgba(158,158,158,0.2);
background-color: rgba(158, 158, 158, 0.2);
}

.md-select-menu-container {
z-index: 99999 !important;
}
}

.disabled {
pointer-events: none;
opacity: 0.7;
}

.readonly > [role=button] {
cursor: inherit;
}

.md-dialog-container {
height: 100vh !important;
top: 0 !important;
position: fixed !important;
}
4 changes: 2 additions & 2 deletions src/management/management.module.ts
Expand Up @@ -548,7 +548,7 @@ angular.module('gravitee-management', [uiRouter, permission, uiPermission, 'ngMa
if (!moment().subtract(1, 'weeks').isAfter(input)) {
return moment(input).fromNow();
} else {
return moment(input).format('D MMM. YYYY');
return moment(input).format('ll');
}
};
})
Expand All @@ -557,7 +557,7 @@ angular.module('gravitee-management', [uiRouter, permission, uiPermission, 'ngMa
if (!moment().subtract(1, 'weeks').isAfter(input)) {
return moment(input).fromNow();
} else {
return moment(input).format('D MMM. YYYY HH:mm:ss');
return moment(input).format('D MMM YYYY HH:mm:ss');
}
};
})
Expand Down
6 changes: 6 additions & 0 deletions src/portal/api/_api.scss
@@ -1,4 +1,5 @@
@import 'plan/api-plan';
@import 'rating/api.rating';

#header {
color: #000;
Expand Down Expand Up @@ -26,6 +27,10 @@
}
}

.api-rating {
margin-left: 25px;
}

.md-button {
width: 180px;
}
Expand Down Expand Up @@ -153,6 +158,7 @@ md-card-content {
.api-views {
border-top: 1px solid rgba(0, 0, 0, 0.05);
padding-top: 10px;
height: 34px;
}

.ui.label {
Expand Down
12 changes: 10 additions & 2 deletions src/portal/api/apis.controller.ts
Expand Up @@ -21,15 +21,18 @@ export class PortalApisController {
private apis: any[];
private views: any[];
private view: any;
private ratingEnabled: boolean;

constructor (private resolvedApis,
private resolvedViews,
private $scope: IScope,
private $state,
private $stateParams) {
private $stateParams,
private Constants) {
'ngInject';
this.apis = resolvedApis.data;
this.views = resolvedViews;
this.ratingEnabled = Constants.rating.enabled;

this.view = _.find(this.views, function (view) {
return $stateParams.view === view.id;
Expand All @@ -41,11 +44,16 @@ export class PortalApisController {
}

goToApi(api) {
this.$state.go('portal.api.plans', {apiId: api.id});
this.$state.go('portal.api.detail', {apiId: api.id});
}

changeView(event, view) {
event.stopPropagation();
this.$state.go('portal.apis.list', {view: view});
}

goToRating(event, api) {
event.stopPropagation();
this.$state.go('portal.api.rating', {apiId: api.id});
}
}
12 changes: 9 additions & 3 deletions src/portal/api/apisList.html
Expand Up @@ -59,9 +59,15 @@ <h5 class="gravitee-view-description" ng-if="apisCtrl.view && apisCtrl.view.desc
<div class="api-infos">
<small>{{::api.description}}</small>
</div>
<div class="api-views">
<a ng-if="api.views" ng-repeat="view in api.views" class="ui label" ng-click="apisCtrl.changeView($event, view)">{{view}}</a>
<div ng-if="!api.views || api.views.length === 0" class="no-view"></div>
<div class="api-views" layout="row">
<div flex="65">
<a ng-if="api.views" ng-repeat="view in api.views" class="ui label" ng-click="apisCtrl.changeView($event, view)">{{view}}</a>
<div ng-if="!api.views || api.views.length === 0" class="no-view"></div>
</div>

<gv-star-rating flex ng-if="apisCtrl.ratingEnabled && api.rate" value="api.rate"
message="'api.rating.rate' | translate:{numberOfRatings: api.numberOfRatings}" display-none-message="true"
ng-click="apisCtrl.goToRating($event, api)"></gv-star-rating>
</div>
</md-card-content>
</md-card>
Expand Down
16 changes: 13 additions & 3 deletions src/portal/api/header/api-header.component.ts
Expand Up @@ -13,17 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import ApiService from "../../../services/api.service";

const ApiHeaderComponent: ng.IComponentOptions = {
bindings: {
api: '<'
api: '<',
apiRatingSummary: '<'
},
template: require('./api-header.html'),
controller: function(Constants) {
controller: function(Constants, ApiService: ApiService, $stateParams, $rootScope) {
'ngInject';
this.ratingEnabled = Constants.rating.enabled;

this.getEndpoint = function () {
return Constants.portal.entrypoint + this.api.context_path;
}
};

$rootScope.$on('onRatingSave', () => {
ApiService.getApiRatingSummaryByApi($stateParams.apiId).then((response) => {
this.apiRatingSummary = response.data;
});
});
}
};

Expand Down
16 changes: 14 additions & 2 deletions src/portal/api/header/api-header.html
Expand Up @@ -20,7 +20,19 @@
<div layout="column" flex="65">
<div layout="row" layout-align="start center">
<img width="60" height="60" ng-src="{{$ctrl.api.picture_url}}" alt="api-logo" />
<span class="api-title" ui-sref="portal.api.plans({apiId: $ctrl.api.id})">{{::$ctrl.api.name}}</span>
<div layout="column">
<span class="api-title" ui-sref="portal.api.detail({apiId: $ctrl.api.id})">{{::$ctrl.api.name}}</span>

<a permission permission-only="'api-rating-r'" ui-sref="portal.api.rating({apiId: $ctrl.api.id})">
<gv-star-rating ng-if="$ctrl.ratingEnabled" class="api-rating" summary="$ctrl.apiRatingSummary"
message="'api.rating.rate' | translate:{numberOfRatings: $ctrl.apiRatingSummary.numberOfRatings}"
display-none-message="true"></gv-star-rating>
</a>
<gv-star-rating permission permission-except="'api-rating-r'"
ng-if="$ctrl.ratingEnabled" class="api-rating" summary="$ctrl.apiRatingSummary"
message="'api.rating.rate' | translate:{numberOfRatings: $ctrl.apiRatingSummary.numberOfRatings}"
display-none-message="true"></gv-star-rating>
</div>
</div>

<div layout="row" style="margin-top: 18px;">
Expand All @@ -38,7 +50,7 @@
<div layout="column" layout-align="center center" flex="20">
<md-button class="md-raised" ui-sref="portal.api.pages({apiId: $ctrl.api.id})">{{'api.documentation.title' | translate}}</md-button>
<md-button class="md-raised md-primary" style="background-color: #006CAB"
ui-sref="portal.api.plans({apiId: $ctrl.api.id, '#': 'plans'})">{{'api.plan.subscribe' | translate}}</md-button>
ui-sref="portal.api.detail({apiId: $ctrl.api.id, '#': 'plans'})">{{'api.plan.subscribe' | translate}}</md-button>
</div>

<div flex></div>
Expand Down
58 changes: 0 additions & 58 deletions src/portal/api/plan/apiPlan.controller.ts

This file was deleted.

22 changes: 22 additions & 0 deletions src/portal/api/rating/_api.rating.scss
@@ -0,0 +1,22 @@
#ratings {
width: 70%;
margin: 30px auto;

& md-card p {
text-align: center;
}
}

.rating-comment {
margin: 20px;
white-space: pre-line;
}

.rating-answers {
margin: 10px 50px;
}

.rating-delete {
fill: #cdcccc;
float: right;
}
29 changes: 29 additions & 0 deletions src/portal/api/rating/api-ratings.component.ts
@@ -0,0 +1,29 @@
/*
* 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.
*/
import ApiPortalRatingController from "./apiRating.controller";

const ApiRatingsComponent: ng.IComponentOptions = {
bindings: {
api: '<',
rating: '<',
ratings: '<',
isAuthenticated: '<'
},
template: require('./api-ratings.html'),
controller: ApiPortalRatingController
};

export default ApiRatingsComponent;

0 comments on commit d42ff8a

Please sign in to comment.