Skip to content
This repository has been archived by the owner on May 4, 2019. It is now read-only.

ng-admin role-based system #8

Open
wants to merge 3 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions build/main.css

Large diffs are not rendered by default.

245 changes: 200 additions & 45 deletions build/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/main.js.map

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions build/ng-admin.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/ng-admin.min.js.map

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions js/categories/userConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default function (nga, admin) {

var categories = admin.getEntity('categories');
categories.listView()
.fields([
nga.field('name'),
])
.batchActions([])
.listActions();
return categories;
}
57 changes: 57 additions & 0 deletions js/customers/userConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
var moment = require('moment');
var fromNow = v => moment(v).fromNow();

var segments = require('../segments/segments').choices;

export default function (nga, admin) {

var customer = admin.getEntity('customers');
customer.listView()
.title('Visitors')
.fields([
nga.field('avatar', 'template')
.label('')
.template('<img src="{{ entry.values.avatar }}" width="25" style="margin-top:-5px" />'),
nga.field('last_name', 'template') // use last_name for sorting
.label('Name')
.isDetailLink(true)
.template('{{ entry.values.first_name }} {{ entry.values.last_name }}'),
nga.field('last_seen', 'datetime')
.map(fromNow)
.cssClasses('hidden-xs'),
nga.field('nb_commands', 'template')
.label('Commands')
.template('{{ entry.values.nb_commands ? entry.values.nb_commands : "" }}')
.cssClasses('hidden-xs'),
nga.field('total_spent', 'template')
.template('<div class="amount" ng-if="::entry.values[field.name()]">$<ma-number-column field="::field" value="::entry.values[field.name()]"></ma-number-column></div>')
.cssClasses('hidden-xs text-right'),
nga.field('latest_purchase', 'datetime')
.cssClasses('hidden-xs'),
nga.field('has_newsletter', 'boolean')
.label('Newsletter')
.cssClasses('hidden-xs'),
nga.field('segments', 'template')
.template('<span ng-repeat="group in entry.values.groups track by $index" class="label label-default">{{ group }}</span>')
.cssClasses('hidden-xs'),
])
.filters([
nga.field('q', 'template')
.label('')
.pinned(true)
.template('<div class="input-group"><input type="text" ng-model="value" placeholder="Search" class="form-control"></input><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span></div>'),
nga.field('groups', 'choice')
.label('Segment')
.choices(segments),
nga.field('last_seen_gte', 'datetime')
.label('Visited since'),
nga.field('has_ordered', 'boolean'),
nga.field('has_newsletter', 'boolean'),
])
.sortField('first_seen')
.sortDir('DESC')
.batchActions([])
.listActions();

return customer;
}
11 changes: 8 additions & 3 deletions js/dashboard/dashboardSummary.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</div>
</div>
<div class="row">
<div class="col-lg-3">
<div class="col-lg-3" ng-show="{{ isAdmin }}">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
Expand All @@ -29,7 +29,9 @@

</div>
</div>
<div class="col-lg-3">


<div class="col-lg-3" ng-show="{{ isAdmin }}">
<div class="panel panel-green">
<div class="panel-heading">
<div class="row">
Expand All @@ -51,7 +53,8 @@
</a>
</div>
</div>
<div class="col-lg-3">

<div class="col-lg-3" ng-show="{{ isAdmin }}">
<div class="panel panel-yellow">
<div class="panel-heading">
<div class="row">
Expand All @@ -73,6 +76,8 @@
</a>
</div>
</div>


<div class="col-lg-3">
<div class="panel panel-red">
<div class="panel-heading">
Expand Down
41 changes: 22 additions & 19 deletions js/dashboard/dashboardSummary.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var oneMonthAgo = moment().subtract(1, 'months').toDate();

var has_seen_alert = false;

function dashboardSummary(Restangular) {
function dashboardSummary(Restangular, $window) {
'use strict';

return {
Expand All @@ -14,38 +14,41 @@ function dashboardSummary(Restangular) {
controller: function($scope) {
$scope.stats = {};
$scope.has_seen_alert = has_seen_alert;
$scope.isAdmin = $window.localStorage.getItem('posters_galore_login') == 'admin';
$scope.dismissAlert = () => {
has_seen_alert = true;
$scope.has_seen_alert = true;
};
Restangular
.all('commands')
.getList({filter: '{"date_gte":"' + oneMonthAgo.toISOString() +'"}', sort: '["date","DESC"]'})
.then(commands => {
$scope.stats.commands = commands.data
.reduce((stats, command) => {
if (command.status != 'cancelled') stats.revenue += command.total;
if (command.status == 'ordered') stats.pending_orders++;
return stats;
}, { revenue: 0, pending_orders: 0})
});
if ($scope.isAdmin) {
Restangular
.all('commands')
.getList({filter: '{"date_gte":"' + oneMonthAgo.toISOString() +'"}', sort: '["date","DESC"]'})
.then(commands => {
$scope.stats.commands = commands.data
.reduce((stats, command) => {
if (command.status != 'cancelled') stats.revenue += command.total;
if (command.status == 'ordered') stats.pending_orders++;
return stats;
}, { revenue: 0, pending_orders: 0})
});
Restangular
.all('reviews')
.getList({range: '[1,100]', sort: '["date","DESC"]', filter: '{"status":"pending"}'})
.then(reviews => {
$scope.stats.reviews = reviews.data.reduce(nb => ++nb, 0)
});
}
Restangular
.all('customers')
.getList({range: '[1,100]', sort: '["first_seen","DESC"]', filter: '{"has_ordered":true,"first_seen_gte":"' +oneMonthAgo.toISOString() + '"}'})
.then(customers => {
$scope.stats.customers = customers.data.reduce(nb => ++nb, 0)
});
Restangular
.all('reviews')
.getList({range: '[1,100]', sort: '["date","DESC"]', filter: '{"status":"pending"}'})
.then(reviews => {
$scope.stats.reviews = reviews.data.reduce(nb => ++nb, 0)
});
},
template: dashboardSummaryTemplate
};
}

dashboardSummary.$inject = ['Restangular'];
dashboardSummary.$inject = ['Restangular', '$window'];

export default dashboardSummary;
61 changes: 61 additions & 0 deletions js/dashboard/userConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
var moment = require('moment');
var fromNow = v => moment(v).fromNow();

export default function (nga, admin, $window) {

var dashboard = nga.dashboard()
.addCollection(nga.collection(admin.getEntity('customers'))
.name('new_customers')
.title('New customers')
.fields([
nga.field('avatar', 'template')
.label('')
.template('<img src="{{ entry.values.avatar }}" width="25" />'),
nga.field('last_name', 'template') // use last_name for sorting
.label('Name')
.isDetailLink(true)
.template('{{ entry.values.first_name }} {{ entry.values.last_name }}'),
nga.field('last_seen', 'datetime')
.map(fromNow),
])
.permanentFilters({ has_ordered: true })
.sortField('first_seen')
.sortDir('DESC')
.perPage(10)
)

if ($window.localStorage.getItem('posters_galore_login') == 'admin') {
dashboard.template(`
<div class="row dashboard-starter"></div>
<dashboard-summary></dashboard-summary>
<div class="row dashboard-content">
<div class="col-lg-6">
<div class="panel panel-default">
<ma-dashboard-panel collection="dashboardController.collections.pending_orders" entries="dashboardController.entries.pending_orders"></ma-dashboard-panel>
</div>
</div>
<div class="col-lg-6">
<div class="panel panel-default">
<ma-dashboard-panel collection="dashboardController.collections.latest_reviews" entries="dashboardController.entries.latest_reviews"></ma-dashboard-panel>
</div>
<div class="panel panel-default">
<ma-dashboard-panel collection="dashboardController.collections.new_customers" entries="dashboardController.entries.new_customers"></ma-dashboard-panel>
</div>
</div>
</div>
`);
} else {
dashboard.template(`
<div class="row dashboard-starter"></div>
<dashboard-summary></dashboard-summary>
<div class="row dashboard-content">
<div class="col-lg-6">
<div class="panel panel-default">
<ma-dashboard-panel collection="dashboardController.collections.new_customers" entries="dashboardController.entries.new_customers"></ma-dashboard-panel>
</div>
</div>
</div>
`);
}
return dashboard;
}
62 changes: 41 additions & 21 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,49 @@ myApp.controller('username', ['$scope', '$window', function($scope, $window) { /
// custom states (pages)
myApp.config(['$stateProvider', require('./segments/segmentsState')]);

myApp.config(['NgAdminConfigurationProvider', function (nga) {
myApp.config(['NgAdminConfigurationProvider', '$windowProvider', function (nga, $window) {
// create the admin application
var admin = nga.application('My First Admin')
.baseApiUrl('/');

// add entities
admin.addEntity(nga.entity('customers'));
admin.addEntity(nga.entity('categories'));
admin.addEntity(nga.entity('products'));
admin.addEntity(nga.entity('reviews'));
admin.addEntity(nga.entity('commands'));

// configure entities
require('./customers/config')(nga, admin);
require('./categories/config')(nga, admin);
require('./products/config')(nga, admin);
require('./reviews/config')(nga, admin);
require('./commands/config')(nga, admin);

admin.dashboard(require('./dashboard/config')(nga, admin));
admin.header(require('./header.html'));
admin.menu(require('./menu')(nga, admin));

// attach the admin application to the DOM and execute it
nga.configure(admin);
if ($window.$get().localStorage.getItem('posters_galore_login') == 'admin') { //retrieving current role
// add entities
admin.addEntity(nga.entity('customers'));
admin.addEntity(nga.entity('categories'));
admin.addEntity(nga.entity('products'));
admin.addEntity(nga.entity('reviews'));
admin.addEntity(nga.entity('commands'));

// configure entities
require('./customers/config')(nga, admin);
require('./categories/config')(nga, admin);
require('./products/config')(nga, admin);
require('./reviews/config')(nga, admin);
require('./commands/config')(nga, admin);

admin.dashboard(require('./dashboard/config')(nga, admin));
admin.header(require('./header.html'));
admin.menu(require('./menu')(nga, admin));

// attach the admin application to the DOM and execute it
nga.configure(admin);
} else {
// add entities
admin.addEntity(nga.entity('customers').readOnly());
admin.addEntity(nga.entity('categories').readOnly());
admin.addEntity(nga.entity('products').readOnly());

// configure entities
require('./customers/userConfig')(nga, admin);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of duplicating the conf, I'd pass the roles as a parameter to the config function and let it decide how to configure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you talking about creating a provider/wrapper for handling configurations for different roles?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm saying that you shouldn't put the if here, but in the config files. Something like:

const roles = $window.$get().localStorage.getItem('posters_galore_roles')
admin.addEntity(nga.entity('customers'));
require('./customers/config')(nga, admin, roles);

And then, in the config files, decide what to add according to roles.

require('./categories/userConfig')(nga, admin);
require('./products/userConfig')(nga, admin);

admin.dashboard(require('./dashboard/userConfig')(nga, admin, $window.$get()));
admin.header(require('./header.html'));
admin.menu(require('./userMenu')(nga, admin));

// attach the admin application to the DOM and execute it
nga.configure(admin);
}

}]);
59 changes: 59 additions & 0 deletions js/products/userConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import moment from 'moment';
import productsEditionTemplate from './productsEditionTemplate.html';

var fromNow = v => moment(v).fromNow();

export default function (nga, admin) {

var products = admin.getEntity('products')
.label('Posters');
products.listView()
.title('All Posters')
.fields([
nga.field('i', 'template')
.isDetailLink(true)
.label('')
.template('<img src="{{ entry.values.thumbnail }}" class="poster_mini_thumbnail" />'),
nga.field('reference').isDetailLink(true),
nga.field('price', 'amount')
.cssClasses('hidden-xs'),
nga.field('width', 'float')
.format('0.00')
.cssClasses('hidden-xs'),
nga.field('height', 'float')
.format('0.00')
.cssClasses('hidden-xs'),
nga.field('category_id', 'reference')
.label('Category')
.targetEntity(admin.getEntity('categories'))
.targetField(nga.field('name'))
.cssClasses('hidden-xs'),
nga.field('stock', 'number')
.cssClasses('hidden-xs'),
])
.filters([
nga.field('q', 'template')
.label('')
.pinned(true)
.template('<div class="input-group"><input type="text" ng-model="value" placeholder="Search" class="form-control"></input><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span></div>'),
nga.field('category_id', 'reference')
.label('Category')
.targetEntity(admin.getEntity('categories'))
.targetField(nga.field('name')),
nga.field('width_gte', 'number')
.label('Min width'),
nga.field('width_lte', 'number')
.label('Max width'),
nga.field('height_gte', 'number')
.label('Min height'),
nga.field('height_lte', 'number')
.label('Max height'),
nga.field('stock_lte', 'template')
.label('Low stock')
.defaultValue(10)
])
.batchActions([])
.listActions();

return products;
}
Loading