/*global angular*/
/*
* This is an example ng-admin configuration for a blog administration composed
* of three entities: post, comment, and tag. Reading the code and the comments
* will help you understand how a typical ng-admin application works.
*
* The remote REST API is simulated in the browser, using FakeRest
* (https://github.com/marmelab/FakeRest). Look at the JSON responses in the
* browser console to see the data used by ng-admin.
*
* For simplicity's sake, the entire configuration is written in a single file,
* but in a real world situation, you would probably split that configuration
* into one file per entity. For another example configuration on a larger set
* of entities, and using the best development practices, check out the
* Posters Galore demo (http://marmelab.com/ng-admin-demo/).
*/
(function () {
"use strict";
var app = angular.module('myApp', ['ng-admin']);
// API Mapping
app.config(['RestangularProvider', function (RestangularProvider) {
// use the custom query parameters function to format the API request correctly
RestangularProvider.addFullRequestInterceptor(function(element, operation, what, url, headers, params) {
if (operation === 'getList') {
// custom pagination params
if (params._page) {
var start = (params._page - 1) * params._perPage;
var end = params._page * params._perPage - 1;
params.range = "[" + start + "," + end + "]";
delete params._page;
delete params._perPage;
}
// custom sort params
if (params._sortField) {
params.sort = '["' + params._sortField + '","' + params._sortDir + '"]';
delete params._sortField;
delete params._sortDir;
}
// custom filters
if (params._filters) {
params.filter = params._filters;
delete params._filters;
}
}
return { params: params };
});
RestangularProvider.addResponseInterceptor(function(data, operation, what, url, response) {
if (operation === "getList") {
var headers = response.headers();
if (headers['content-range']) {
response.totalCount = headers['content-range'].split('/').pop();
}
}
return data;
});
}]);
// Admin definition
app.config(['NgAdminConfigurationProvider', function (NgAdminConfigurationProvider) {
var nga = NgAdminConfigurationProvider;
function truncate(value) {
if (!value) {
return '';
}
return value.length > 50 ? value.substr(0, 50) + '...' : value;
}
var admin = nga.application('ng-admin blog demo') // application main title
.debug(false) // debug disabled
.baseApiUrl('http://localhost:3000/'); // main API endpoint
// define all entities at the top to allow references between them
var post = nga.entity('posts'); // the API endpoint for posts will be http://localhost:3000/posts/:id
var comment = nga.entity('comments')
.baseApiUrl('http://localhost:3000/') // The base API endpoint can be customized by entity
.identifier(nga.field('id')); // you can optionally customize the identifier used in the api ('id' by default)
var tag = nga.entity('tags');
var subCategories = [
{ category: 'tech', label: 'Computers', value: 'computers' },
{ category: 'tech', label: 'Gadgets', value: 'gadgets' },
{ category: 'lifestyle', label: 'Travel', value: 'travel' },
{ category: 'lifestyle', label: 'Fitness', value: 'fitness' }
];
// set the application entities
admin
.addEntity(post)
.addEntity(tag)
.addEntity(comment);
// customize entities and views
/*****************************
* post entity customization *
*****************************/
post.listView()
.title('All posts') // default title is "[Entity_name] list"
.description('List of posts with infinite pagination') // description appears under the title
.infinitePagination(true) // load pages as the user scrolls
.fields([
nga.field('id').label('id'), // The default displayed name is the camelCase field name. label() overrides id
nga.field('title'), // the default list field type is "string", and displays as a string
nga.field('published_at', 'date'), // Date field type allows date formatting
nga.field('average_note', 'float') // Float type also displays decimal digits
.cssClasses('hidden-xs'),
nga.field('views', 'number')
.cssClasses('hidden-xs'),
nga.field('backlinks', 'embedded_list') // display list of related comments
.label('Links')
.map(links => links ? links.length : '')
.template('{{ value }}'),
nga.field('tags', 'reference_many') // a Reference is a particular type of field that references another entity
.targetEntity(tag) // the tag entity is defined later in this file
.targetField(nga.field('name')) // the field to be displayed in this list
.cssClasses('hidden-xs')
.singleApiCall(ids => { return {'id': ids }; })
])
.filters([
nga.field('category', 'choice').choices([
{ label: 'Tech', value: 'tech' },
{ label: 'Lifestyle', value: 'lifestyle' }
]).label('Category'),
nga.field('subcategory', 'choice').choices(subCategories).label('Subcategory')
])
.listActions(['show', 'edit', 'delete'])
.entryCssClasses(function(entry) { // set row class according to entry
return (entry.views > 300) ? 'is-popular' : '';
})
.exportFields([
post.listView().fields(), // fields() without arguments returns the list of fields. That way you can reuse fields from another view to avoid repetition
nga.field('category', 'choice') // a choice field is rendered as a dropdown in the edition view
.choices([ // List the choice as object literals
{ label: 'Tech', value: 'tech' },
{ label: 'Lifestyle', value: 'lifestyle' }
]),
nga.field('subcategory', 'choice')
.choices(function(entry) { // choices also accepts a function to return a list of choices based on the current entry
return subCategories.filter(function (c) {
return c.category === entry.values.category;
});
}),
])
.exportOptions({
quotes: true,
delimiter: ';'
});
post.creationView()
.fields([
nga.field('title') // the default edit field type is "string", and displays as a text input
.attributes({ placeholder: 'the post title' }) // you can add custom attributes, too
.validation({ required: true, minlength: 3, maxlength: 100 }), // add validation rules for fields
nga.field('teaser', 'text'), // text field type translates to a textarea
nga.field('body', 'wysiwyg'), // overriding the type allows rich text editing for the body
nga.field('published_at', 'date') // Date field type translates to a datepicker
]);
post.editionView()
.title('Edit post "{{ entry.values.title }}"') // title() accepts a template string, which has access to the entry
.actions(['list', 'show', 'delete']) // choose which buttons appear in the top action bar. Show is disabled by default
.fields([
post.creationView().fields(), // fields() without arguments returns the list of fields. That way you can reuse fields from another view to avoid repetition
nga.field('category', 'choice') // a choice field is rendered as a dropdown in the edition view
.choices([ // List the choice as object literals
{ label: 'Tech', value: 'tech' },
{ label: 'Lifestyle', value: 'lifestyle' }
]),
nga.field('subcategory', 'choice')
.choices(function(entry) { // choices also accepts a function to return a list of choices based on the current entry
return subCategories.filter(function (c) {
return c.category === entry.values.category;
});
})
.template('
You can add custom pages, too
' + 'You can add custom pages, too
' + '