├── src
├── app
│ ├── index.scss
│ ├── app.js
│ ├── app.spec.js
│ ├── views
│ │ ├── partials
│ │ │ ├── memory.html
│ │ │ ├── visitors.html
│ │ │ ├── warnings.html
│ │ │ ├── usage.html
│ │ │ ├── messages.html
│ │ │ ├── bottomSheet.html
│ │ │ ├── performance.html
│ │ │ ├── controlPanel.html
│ │ │ ├── autocomplete.html
│ │ │ └── checkboxes.html
│ │ ├── table.html
│ │ ├── dashboard.html
│ │ ├── data-table.html
│ │ ├── profile.html
│ │ └── main.html
│ ├── controllers
│ │ ├── TableController.js
│ │ ├── MessagesController.js
│ │ ├── ProfileController.js
│ │ ├── VisitorsController.js
│ │ ├── SearchController.js
│ │ ├── UsageController.js
│ │ ├── MemoryController.js
│ │ ├── WarningsController.js
│ │ ├── ControlPanelController.js
│ │ ├── DataTableController.js
│ │ ├── PerformanceController.js
│ │ ├── TodoController.js
│ │ └── MainController.js
│ ├── components
│ │ ├── services
│ │ │ ├── TodoListService.js
│ │ │ ├── NavService.js
│ │ │ ├── MessagesService.js
│ │ │ ├── TableService.js
│ │ │ ├── PerformanceService.js
│ │ │ └── CountriesService.js
│ │ └── directives
│ │ │ ├── panelWidget.js
│ │ │ └── messagesSection.js
│ ├── index.js
│ └── stylesheets
│ │ ├── _custom.scss
│ │ └── _table.scss
├── favicon.ico
├── assets
│ └── images
│ │ ├── einstein.jpg
│ │ ├── feynman.jpg
│ │ └── promo-amd.png
├── index.html
└── 404.html
├── .bowerrc
├── .gitignore
├── gulp
├── deploy.js
├── watch.js
├── unit-tests.js
├── e2e-tests.js
├── inject.js
├── styles.js
├── server.js
├── proxy.js
└── build.js
├── e2e
├── main.spec.js
└── main.po.js
├── gulpfile.js
├── karma.conf.js
├── bower.json
├── .jshintrc
├── protractor.conf.js
├── LICENSE
├── changelog.md
├── package.json
└── README.md
/src/app/index.scss:
--------------------------------------------------------------------------------
1 | // injector
2 | // endinjector
3 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatlogic/angular-material-dashboard/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 | .sass-cache/
4 | .tmp/
5 | dist/
6 | .idea/
7 | .publish/
8 |
--------------------------------------------------------------------------------
/src/app/app.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app', [ 'ngMaterial' ]);
5 |
6 | })();
7 |
--------------------------------------------------------------------------------
/src/assets/images/einstein.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatlogic/angular-material-dashboard/HEAD/src/assets/images/einstein.jpg
--------------------------------------------------------------------------------
/src/assets/images/feynman.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatlogic/angular-material-dashboard/HEAD/src/assets/images/feynman.jpg
--------------------------------------------------------------------------------
/src/assets/images/promo-amd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatlogic/angular-material-dashboard/HEAD/src/assets/images/promo-amd.png
--------------------------------------------------------------------------------
/src/app/app.spec.js:
--------------------------------------------------------------------------------
1 | describe('Abstract test to make sure that karma works properly', function() {
2 | it('Is true always true?', function() {
3 | expect(true).toBe(true);
4 | });
5 | });
--------------------------------------------------------------------------------
/src/app/views/partials/memory.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/app/views/partials/visitors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/app/views/partials/warnings.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/gulp/deploy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 | var ghPages = require('gulp-gh-pages');
5 |
6 | gulp.task('deploy', function() {
7 | return gulp.src('./dist/**/*')
8 | .pipe(ghPages());
9 | });
10 |
--------------------------------------------------------------------------------
/e2e/main.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('The main view', function () {
4 | var page;
5 |
6 | beforeEach(function () {
7 | browser.get('http://localhost:3000/index.html');
8 | page = require('./main.po');
9 | });
10 |
11 | });
12 |
--------------------------------------------------------------------------------
/e2e/main.po.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file uses the Page Object pattern to define the main page for tests
3 | * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ
4 | */
5 |
6 | 'use strict';
7 |
8 | var MainPage = function() {
9 | };
10 |
11 | module.exports = new MainPage();
12 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | gulp.paths = {
6 | src: 'src',
7 | dist: 'dist',
8 | tmp: '.tmp',
9 | e2e: 'e2e'
10 | };
11 |
12 | require('require-dir')('./gulp');
13 |
14 | gulp.task('default', ['clean'], function () {
15 | gulp.start('build');
16 | });
17 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(config) {
4 |
5 | config.set({
6 | autoWatch : false,
7 |
8 | frameworks: ['jasmine'],
9 |
10 | browsers : ['PhantomJS'],
11 |
12 | plugins : [
13 | 'karma-phantomjs-launcher',
14 | 'karma-jasmine'
15 | ]
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/gulp/watch.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | gulp.task('watch', ['inject'], function () {
8 | gulp.watch([
9 | paths.src + '/*.html',
10 | paths.src + '/{app,components}/**/*.scss',
11 | paths.src + '/{app,components}/**/*.js',
12 | 'bower.json'
13 | ], ['inject']);
14 | });
15 |
--------------------------------------------------------------------------------
/src/app/views/partials/usage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
RAM
5 |
6 |
7 |
8 |
Storage
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/app/controllers/TableController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('TableController', [
6 | 'tableService',
7 | TableController
8 | ]);
9 |
10 | function TableController(tableService) {
11 | var vm = this;
12 |
13 | vm.tableData = [];
14 |
15 | tableService
16 | .loadAllItems()
17 | .then(function(tableData) {
18 | vm.tableData = [].concat(tableData);
19 | });
20 | }
21 |
22 | })();
23 |
--------------------------------------------------------------------------------
/src/app/controllers/MessagesController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('MessagesController', [
6 | 'messagesService',
7 | MessagesController
8 | ]);
9 |
10 | function MessagesController(messagesService) {
11 | var vm = this;
12 |
13 | vm.messages = [];
14 |
15 | messagesService
16 | .loadAllItems()
17 | .then(function(messages) {
18 | vm.messages = [].concat(messages);
19 | });
20 | }
21 |
22 | })();
23 |
--------------------------------------------------------------------------------
/src/app/views/partials/messages.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/app/views/partials/bottomSheet.html:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/app/views/partials/performance.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Last week
5 | Last month
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/app/components/services/TodoListService.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('todoListService', [
6 | '$q',
7 | todoList
8 | ]);
9 |
10 | function todoList($q){
11 | var todos = [
12 | {text: 'Continuous integration', done: false},
13 | {text: 'Implement panel-widget directive', done: true},
14 | {text: 'Add backend', done: false}
15 | ];
16 |
17 | return {
18 | loadAllItems : function() {
19 | return $q.when(todos);
20 | }
21 | };
22 | }
23 | })();
24 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-material-dashboard",
3 | "description": "Material Design Angular Admin Dashboard",
4 | "homepage": "https://github.com/micrum/angular-material-admin",
5 | "license": "MIT",
6 | "version": "1.3.0",
7 | "dependencies": {
8 | "jquery": "3.3.1",
9 | "angular-animate": "1.7.5",
10 | "angular-cookies": "1.7.5",
11 | "angular-touch": "1.7.5",
12 | "angular-sanitize": "1.7.5",
13 | "angular-ui-router": "1.0.20",
14 | "angular": "1.7.5",
15 | "angular-nvd3": "1.0.0-rc.2",
16 | "angular-material": "1.0.6",
17 | "angular-mocks": "1.7.5",
18 | "angular-material-data-table": "0.10.10"
19 | },
20 | "devDependencies": {}
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/views/partials/controlPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | Staging server
8 | Production server
9 |
10 |
11 |
12 | Reload server
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/app/controllers/ProfileController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('ProfileController', [
6 | ProfileController
7 | ]);
8 |
9 | function ProfileController() {
10 | var vm = this;
11 |
12 | vm.user = {
13 | title: 'Admin',
14 | email: 'contact@flatlogic.com',
15 | firstName: '',
16 | lastName: '' ,
17 | company: 'FlatLogic Inc.' ,
18 | address: 'Fabritsiusa str, 4' ,
19 | city: 'Minsk' ,
20 | state: '' ,
21 | biography: 'We are young and ambitious full service design and technology company. ' +
22 | 'Our focus is JavaScript development and User Interface design.',
23 | postalCode : '220007'
24 | };
25 | }
26 |
27 | })();
28 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true,
21 | "validthis": true,
22 | "globals": {
23 | "angular": false,
24 | // Angular Mocks
25 | "inject": false,
26 | // JASMINE
27 | "describe": false,
28 | "it": false,
29 | "before": false,
30 | "beforeEach": false,
31 | "after": false,
32 | "afterEach": false,
33 | "expect": false
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths;
4 |
5 | // An example configuration file.
6 | exports.config = {
7 | // The address of a running selenium server.
8 | //seleniumAddress: 'http://localhost:4444/wd/hub',
9 | //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json
10 |
11 | // Capabilities to be passed to the webdriver instance.
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 |
16 | // Spec patterns are relative to the current working directly when
17 | // protractor is called.
18 | specs: [paths.e2e + '/**/*.js'],
19 |
20 | // Options to be passed to Jasmine-node.
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/src/app/components/services/NavService.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('navService', [
6 | '$q',
7 | navService
8 | ]);
9 |
10 | function navService($q){
11 | var menuItems = [
12 | {
13 | name: 'Dashboard',
14 | icon: 'dashboard',
15 | sref: '.dashboard'
16 | },
17 | {
18 | name: 'Profile',
19 | icon: 'person',
20 | sref: '.profile'
21 | },
22 | {
23 | name: 'Table',
24 | icon: 'view_module',
25 | sref: '.table'
26 | },
27 | {
28 | name: 'Data Table',
29 | icon: 'view_module',
30 | sref: '.data-table'
31 | }
32 | ];
33 |
34 | return {
35 | loadAllItems : function() {
36 | return $q.when(menuItems);
37 | }
38 | };
39 | }
40 |
41 | })();
42 |
--------------------------------------------------------------------------------
/gulp/unit-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var wiredep = require('wiredep');
8 |
9 | var paths = gulp.paths;
10 |
11 | function runTests (singleRun, done) {
12 | var bowerDeps = wiredep({
13 | directory: 'bower_components',
14 | exclude: ['bootstrap-sass-official'],
15 | dependencies: true,
16 | devDependencies: true
17 | });
18 |
19 | var testFiles = bowerDeps.js.concat([
20 | paths.src + '/{app,components}/**/*.js'
21 | ]);
22 |
23 | gulp.src(testFiles)
24 | .pipe($.karma({
25 | configFile: 'karma.conf.js',
26 | action: (singleRun)? 'run': 'watch'
27 | }))
28 | .on('error', function (err) {
29 | // Make sure failed tests cause gulp to exit non-zero
30 | throw err;
31 | });
32 | }
33 |
34 | gulp.task('test', function (done) { runTests(true /* singleRun */, done) });
35 | gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) });
36 |
--------------------------------------------------------------------------------
/src/app/controllers/VisitorsController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('VisitorsController', [
5 | VisitorsController
6 | ]);
7 |
8 | function VisitorsController() {
9 | var vm = this;
10 |
11 | // TODO: move data to the service
12 | vm.visitorsChartData = [ {key: 'Mobile', y: 5264}, { key: 'Desktop', y: 3872} ];
13 |
14 | vm.chartOptions = {
15 | chart: {
16 | type: 'pieChart',
17 | height: 210,
18 | donut: true,
19 | x: function (d) { return d.key; },
20 | y: function (d) { return d.y; },
21 | valueFormat: (d3.format(".0f")),
22 | color: ['rgb(0, 150, 136)', '#E75753'],
23 | showLabels: false,
24 | showLegend: false,
25 | title: 'Over 9K',
26 | margin: { top: -10 }
27 | }
28 | };
29 | }
30 | })();
31 |
--------------------------------------------------------------------------------
/gulp/e2e-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var browserSync = require('browser-sync');
8 |
9 | var paths = gulp.paths;
10 |
11 | // Downloads the selenium webdriver
12 | gulp.task('webdriver-update', $.protractor.webdriver_update);
13 |
14 | gulp.task('webdriver-standalone', $.protractor.webdriver_standalone);
15 |
16 | function runProtractor (done) {
17 |
18 | gulp.src(paths.e2e + '/**/*.js')
19 | .pipe($.protractor.protractor({
20 | configFile: 'protractor.conf.js',
21 | }))
22 | .on('error', function (err) {
23 | // Make sure failed tests cause gulp to exit non-zero
24 | throw err;
25 | })
26 | .on('end', function () {
27 | // Close browser sync server
28 | browserSync.exit();
29 | done();
30 | });
31 | }
32 |
33 | gulp.task('protractor', ['protractor:src']);
34 | gulp.task('protractor:src', ['serve:e2e', 'webdriver-update'], runProtractor);
35 | gulp.task('protractor:dist', ['serve:e2e-dist', 'webdriver-update'], runProtractor);
36 |
--------------------------------------------------------------------------------
/src/app/controllers/SearchController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('SearchController', [
6 | '$timeout', '$q', 'countriesService',
7 | SearchController
8 | ]);
9 |
10 | function SearchController($timeout, $q, countriesService) {
11 | var vm = this;
12 |
13 | vm.countries = countriesService.loadAll();
14 | vm.selectedCountry = null;
15 | vm.searchText = null;
16 | vm.querySearch = querySearch;
17 | vm.disableCaching = true;
18 |
19 | function querySearch (query) {
20 | var results = query ? vm.countries.filter( createFilterFor(query) ) : [],
21 | deferred;
22 | deferred = $q.defer();
23 | $timeout(function () { deferred.resolve( results ); }, Math.random() * 1000, false);
24 | return deferred.promise;
25 | }
26 |
27 | function createFilterFor(query) {
28 | var lowercaseQuery = angular.lowercase(query);
29 | return function filterFn(state) {
30 | return (state.value.indexOf(lowercaseQuery) === 0);
31 | };
32 | }
33 | }
34 | })();
35 |
--------------------------------------------------------------------------------
/src/app/views/table.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #
7 | Issue
8 | Status
9 | Progress
10 |
11 |
12 |
13 |
14 | {{$index + 1}}
15 | {{data.issue}}
16 | {{data.status}}
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 flatlogic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/app/controllers/UsageController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('UsageController', [
5 | UsageController
6 | ]);
7 |
8 | function UsageController() {
9 | var vm = this;
10 |
11 | // TODO: move data to the service
12 | vm.ramChartData = [{key: 'Memory', y: 768660}, { key: 'Cache', y: 367404}, {key: 'Swap', y: 41924 }];
13 | vm.storageChartData = [{key: 'System', y: 126560}, {key: 'Other', y: 224365 }];
14 |
15 | vm.chartOptions = {
16 | chart: {
17 | type: 'pieChart',
18 | height: 130,
19 | donut: true,
20 | x: function (d) { return d.key; },
21 | y: function (d) { return d.y; },
22 | valueFormat: (d3.format(".0f")),
23 | color: ['rgb(0, 150, 136)', '#E75753', 'rgb(235, 235, 235)'],
24 | showLabels: false,
25 | showLegend: false,
26 | title: '83%',
27 | margin: { top: -10, left: -20, right: -20 }
28 | }
29 | };
30 | }
31 | })();
32 |
--------------------------------------------------------------------------------
/src/app/views/partials/autocomplete.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Disable caching
5 | Enable caching
6 |
7 |
8 |
9 |
10 |
16 | {{item.display}}
17 |
18 |
19 | Selected country:
20 | {{vm.selectedCountry.display || 'No country selected'}}
21 |
22 | Country code:
23 | {{vm.selectedCountry.code || 'No country selected'}}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | ## [1.4.1]
3 |
4 | ### Updated
5 |
6 | - Minor packages update
7 |
8 | ## [1.4.0]
9 |
10 | ### Updated
11 |
12 | - Minor packages update
13 |
14 | ## [1.3.0]
15 |
16 | ### Updated
17 |
18 | - Angular Material upgraded to 1.0
19 | - Angular upgraded to 1.5
20 | - Dependencies updated
21 |
22 | ## [1.2.0]
23 |
24 | ### Fixed
25 |
26 | - Lot of UX/UI improvements
27 | - Minor fixes
28 |
29 | ### New Features
30 |
31 | - Browsers support
32 | - Added messages section directive
33 | - Changed app structure
34 |
35 | ## [1.1.0]
36 |
37 | ### New Features
38 |
39 | - Implement message-section directive
40 |
41 | ## [1.0.1]
42 |
43 | ### Updated
44 |
45 | - Update dependencies
46 |
47 | ## [1.1.0]
48 |
49 | ### New Features
50 |
51 | - New layout
52 | - Custom theme styles
53 | - New dashboard sections
54 | - Angular Material v0.10.0
55 | - Added md-menu
56 | - Google material icons
57 | - NVD3 charts
58 | - Responsive layout
59 | - Nested views
60 |
61 | ### Fixed
62 |
63 | - Adjusted panel-widget directive
64 | - Stylesheets reorganized
65 | - Widgets reworked
66 | - Adjusted table
67 | - Reorganized app structure
68 | - Adjusted sidebars
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/gulp/inject.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | var wiredep = require('wiredep').stream;
10 |
11 | gulp.task('inject', ['styles'], function () {
12 |
13 | var injectStyles = gulp.src([
14 | paths.tmp + '/serve/{app,components}/**/*.css',
15 | '!' + paths.tmp + '/serve/app/vendor.css'
16 | ], { read: false });
17 |
18 | var injectScripts = gulp.src([
19 | paths.src + '/{app,components}/**/*.js',
20 | '!' + paths.src + '/{app,components}/**/*.spec.js',
21 | '!' + paths.src + '/{app,components}/**/*.mock.js'
22 | ]).pipe($.angularFilesort());
23 |
24 | var injectOptions = {
25 | ignorePath: [paths.src, paths.tmp + '/serve'],
26 | addRootSlash: false
27 | };
28 |
29 | var wiredepOptions = {
30 | directory: 'bower_components',
31 | exclude: [/bootstrap\.css/, /foundation\.css/]
32 | };
33 |
34 | return gulp.src(paths.src + '/*.html')
35 | .pipe($.inject(injectStyles, injectOptions))
36 | .pipe($.inject(injectScripts, injectOptions))
37 | .pipe(wiredep(wiredepOptions))
38 | .pipe(gulp.dest(paths.tmp + '/serve'));
39 |
40 | });
41 |
--------------------------------------------------------------------------------
/src/app/views/dashboard.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
17 |
--------------------------------------------------------------------------------
/src/app/views/partials/checkboxes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{vm.remaining()}} of {{vm.todos.length}} remaining
4 | Toggle All
5 |
6 |
7 |
8 |
9 | {{todo.text}}
10 |
11 |
12 |
26 |
--------------------------------------------------------------------------------
/src/app/controllers/MemoryController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('MemoryController', [
5 | MemoryController
6 | ]);
7 |
8 | function MemoryController() {
9 | var vm = this;
10 |
11 | // TODO: move data to the service
12 | vm.memoryChartData = [ {key: 'memory', y: 42}, { key: 'free', y: 58} ];
13 |
14 | vm.chartOptions = {
15 | chart: {
16 | type: 'pieChart',
17 | height: 210,
18 | donut: true,
19 | pie: {
20 | startAngle: function (d) { return d.startAngle/2 -Math.PI/2 },
21 | endAngle: function (d) { return d.endAngle/2 -Math.PI/2 }
22 | },
23 | x: function (d) { return d.key; },
24 | y: function (d) { return d.y; },
25 | valueFormat: (d3.format(".0f")),
26 | color: ['rgb(0, 150, 136)', 'rgb(191, 191, 191)'],
27 | showLabels: false,
28 | showLegend: false,
29 | tooltips: false,
30 | title: '42%',
31 | titleOffset: -10,
32 | margin: { bottom: -80, left: -20, right: -20 }
33 | }
34 | };
35 | }
36 | })();
37 |
--------------------------------------------------------------------------------
/src/app/components/directives/panelWidget.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('app')
4 | .directive('panelWidget', function() {
5 | return {
6 | restrict: 'E',
7 | replace: true,
8 | transclude: true,
9 | scope: { title: '@', template: '@', options: '@' },
10 | template: '' +
11 | '',
23 | compile: function(element, attrs, linker) {
24 | return function(scope, element) {
25 | linker(scope, function(clone) {
26 | element.append(clone);
27 | });
28 | };
29 | }
30 | };
31 | });
32 |
--------------------------------------------------------------------------------
/src/app/components/directives/messagesSection.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app')
6 | .directive('messagesSection', messagesSectionDirective);
7 |
8 | function messagesSectionDirective() {
9 | return {
10 | restrict: 'E',
11 | scope: {
12 | title: '@',
13 | theme: '@',
14 | messages: '='
15 | },
16 | template: '' +
17 | '' +
18 | ' {{title}} ' +
19 | ' ' +
20 | ' ' +
21 | ' ' +
22 | ' ' +
23 | '
{{message.subject}} ' +
24 | '
{{message.userName}} ' +
25 | '
{{message.text}}
' +
26 | '
' +
27 | ' ' +
28 | ' ' +
29 | ' ',
30 | link : function(scope, element, attrs) {
31 | }
32 | };
33 | }
34 | })();
--------------------------------------------------------------------------------
/src/app/controllers/WarningsController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('WarningsController', [
5 | WarningsController
6 | ]);
7 |
8 | function WarningsController() {
9 | var vm = this;
10 |
11 | // TODO: move data to the service
12 | vm.warningsChartData = warningFunction;
13 |
14 | function warningFunction() {
15 | var sin = [];
16 | for (var i = 0; i < 100; i++) {
17 | sin.push({x: i, y: Math.abs(Math.cos(i/10) *0.25*i + 0.9 - 0.4*i)});
18 | }
19 | return [ { values: sin, color: 'rgb(0, 150, 136)', area: true } ];
20 | }
21 |
22 | vm.chartOptions = {
23 | chart: {
24 | type: 'lineChart',
25 | height: 210,
26 | margin: { top: -10, left: -20, right: -20 },
27 | x: function (d) { return d.x },
28 | y: function (d) { return d.y },
29 | showLabels: false,
30 | showLegend: false,
31 | title: 'Over 9K',
32 | showYAxis: false,
33 | showXAxis: false,
34 | tooltip: { contentGenerator: function (d) { return '' + Math.round(d.point.y) + ' ' } }
35 | }
36 | };
37 | }
38 | })();
39 |
--------------------------------------------------------------------------------
/src/app/controllers/ControlPanelController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | angular
4 | .module('app')
5 | .controller('ControlPanelController', [
6 | '$mdDialog', '$interval',
7 | ControlPanelController
8 | ]);
9 |
10 | function ControlPanelController($mdDialog, $interval) {
11 | var vm = this;
12 |
13 | vm.buttonEnabled = false;
14 | vm.showProgress = false;
15 | vm.reloadServer = 'Staging';
16 | vm.performProgress = performProgress;
17 | vm.determinateValue = 10;
18 |
19 | function performProgress() {
20 | vm.showProgress = true;
21 | interval = $interval(function() {
22 | vm.determinateValue += 1;
23 | if (vm.determinateValue > 100) {
24 | vm.determinateValue = 10;
25 | vm.showProgress = false;
26 | showAlert();
27 | $interval.cancel(interval)
28 | }
29 | }, 50, 0, true);
30 | }
31 |
32 | function showAlert() {
33 | alert = $mdDialog.alert({
34 | title: 'Reloading done!',
35 | content: vm.reloadServer + " server reloaded.",
36 | ok: 'Close'
37 | });
38 | $mdDialog
39 | .show(alert)
40 | .finally(function () {
41 | alert = undefined;
42 | });
43 | }
44 | }
45 |
46 | })();
47 |
--------------------------------------------------------------------------------
/src/app/controllers/DataTableController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('DataTableController', [
6 | 'tableService',
7 | '$scope',
8 | TableController
9 |
10 | ]);
11 |
12 | function TableController(tableService , $scope) {
13 | var vm = this;
14 |
15 | vm.tableData = [];
16 | vm.totalItems = 0;
17 |
18 | $scope.selected = [];
19 |
20 | $scope.query = {
21 | order: 'name',
22 | limit: 10,
23 | page: 1
24 | };
25 | $scope.selected = [];
26 |
27 | $scope.render = function (T) {
28 | return T;
29 | }
30 | var lastQuery = null;
31 | vm.getItems = function () {
32 | /**
33 | * I don't know why this function is being called too many times,
34 | * it supposed to call once per pagination, so the next 3 lines are only to avoid
35 | * multiple requests.
36 | */
37 | var query = JSON.stringify($scope.query);
38 | if (query == lastQuery) return;
39 | lastQuery = query;
40 | GetItemsData($scope.query);
41 |
42 | }
43 |
44 | function GetItemsData(query) {
45 | tableService
46 | .loadByPagination(query)
47 | .then(function(tableData) {
48 | vm.tableData = tableData.items;
49 | // Represents the count of database count of records, not items array!
50 | vm.totalItems = tableData.count;
51 |
52 | });
53 |
54 | }
55 |
56 | GetItemsData($scope.query);
57 |
58 |
59 |
60 |
61 | }
62 |
63 | })();
64 |
--------------------------------------------------------------------------------
/gulp/styles.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 | // var sass = require('gulp-sass');
9 |
10 | gulp.task('styles', function () {
11 |
12 | var sassOptions = {
13 | style: 'expanded',
14 | 'sourcemap=none': true
15 | };
16 |
17 | var injectFiles = gulp.src([
18 | paths.src + '/{app,components}/**/*.scss',
19 | '!' + paths.src + '/app/index.scss',
20 | '!' + paths.src + '/app/vendor.scss'
21 | ], { read: false });
22 |
23 | var injectOptions = {
24 | transform: function(filePath) {
25 | filePath = filePath.replace(paths.src + '/app/', '');
26 | filePath = filePath.replace(paths.src + '/components/', '../components/');
27 | return '@import \'' + filePath + '\';';
28 | },
29 | starttag: '// injector',
30 | endtag: '// endinjector',
31 | addRootSlash: false
32 | };
33 |
34 | var indexFilter = $.filter('index.scss');
35 |
36 | return gulp.src([
37 | paths.src + '/app/index.scss',
38 | paths.src + '/app/vendor.scss'
39 | ])
40 | .pipe(indexFilter)
41 | .pipe($.inject(injectFiles, injectOptions))
42 | .pipe($.sass(sassOptions)
43 | // .pipe($.rubySass(sassOptions)
44 | .on('error', function (err) {
45 | console.error('Error!', err.message);
46 | })
47 | )
48 |
49 | .pipe($.autoprefixer())
50 | .on('error', function handleError(err) {
51 | console.error(err.toString());
52 | this.emit('end');
53 | })
54 | .pipe(gulp.dest(paths.tmp + '/serve/app/'));
55 | });
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-material-dashboard",
3 | "version": "1.3.0",
4 | "dependencies": {},
5 | "devDependencies": {
6 | "browser-sync": "2.26.12",
7 | "chalk": "2.4.2",
8 | "del": "3.0.0",
9 | "gulp": "3.9.1",
10 | "gulp-angular-filesort": "1.2.1",
11 | "gulp-angular-templatecache": "2.2.7",
12 | "gulp-autoprefixer": "6.0.0",
13 | "gulp-consolidate": "0.2.0",
14 | "gulp-csso": "3.0.1",
15 | "gulp-filter": "5.1.0",
16 | "gulp-flatten": "0.4.0",
17 | "gulp-gh-pages": "0.5.4",
18 | "gulp-inject": "4.3.2",
19 | "gulp-jshint": "2.1.0",
20 | "gulp-karma": "0.0.5",
21 | "gulp-load-plugins": "1.5.0",
22 | "gulp-minify-html": "1.0.6",
23 | "gulp-ng-annotate": "2.1.0",
24 | "gulp-protractor": "4.1.1",
25 | "gulp-rename": "1.4.0",
26 | "gulp-replace": "1.0.0",
27 | "gulp-rev": "8.1.1",
28 | "gulp-rev-replace": "0.4.4",
29 | "gulp-sass": "3.0.0",
30 | "gulp-size": "3.0.0",
31 | "gulp-uglify": "3.0.2",
32 | "gulp-useref": "3.1.6",
33 | "http-proxy": "1.17.0",
34 | "jasmine-core": "3.2.1",
35 | "jshint-stylish": "2.2.1",
36 | "karma": "3.0.0",
37 | "karma-jasmine": "1.1.2",
38 | "karma-phantomjs-launcher": "1.0.4",
39 | "main-bower-files": "2.13.3",
40 | "protractor": "5.4.4",
41 | "require-dir": "1.1.0",
42 | "uglify-save-license": "0.4.1",
43 | "wiredep": "4.0.0"
44 | },
45 | "engines": {
46 | "node": ">=6.5",
47 | "npm": ">=3.10"
48 | },
49 | "scripts": {
50 | "init": "npm install",
51 | "install": "bower install"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/gulp/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var util = require('util');
8 |
9 | var browserSync = require('browser-sync');
10 |
11 | var middleware = require('./proxy');
12 |
13 | function browserSyncInit(baseDir, files, browser) {
14 | browser = browser === undefined ? 'default' : browser;
15 |
16 | var routes = null;
17 | if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
18 | routes = {
19 | '/bower_components': 'bower_components'
20 | };
21 | }
22 |
23 | browserSync.instance = browserSync.init(files, {
24 | startPath: '/',
25 | server: {
26 | baseDir: baseDir,
27 | middleware: middleware,
28 | routes: routes
29 | },
30 | browser: browser
31 | });
32 | }
33 |
34 | gulp.task('serve', ['watch'], function () {
35 | browserSyncInit([
36 | paths.tmp + '/serve',
37 | paths.src
38 | ], [
39 | paths.tmp + '/serve/{app,components}/**/*.css',
40 | paths.src + '/{app,components}/**/*.js',
41 | paths.src + 'src/assets/images/**/*',
42 | paths.tmp + '/serve/*.html',
43 | paths.tmp + '/serve/{app,components}/**/*.html',
44 | paths.src + '/{app,components}/**/*.html'
45 | ]);
46 | });
47 |
48 | gulp.task('serve:dist', ['build'], function () {
49 | browserSyncInit(paths.dist);
50 | });
51 |
52 | gulp.task('serve:e2e', ['inject'], function () {
53 | browserSyncInit([paths.tmp + '/serve', paths.src], null, []);
54 | });
55 |
56 | gulp.task('serve:e2e-dist', ['build'], function () {
57 | browserSyncInit(paths.dist, null, []);
58 | });
59 |
--------------------------------------------------------------------------------
/src/app/controllers/PerformanceController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('PerformanceController', [
5 | 'performanceService', '$q',
6 | PerformanceController
7 | ]);
8 |
9 | function PerformanceController(performanceService, $q) {
10 | var vm = this;
11 |
12 | vm.chartOptions = {
13 | chart: {
14 | type: 'stackedAreaChart',
15 | height: 350,
16 | margin: { left: -15, right: -15 },
17 | x: function (d) { return d[0] },
18 | y: function (d) { return d[1] },
19 | showLabels: false,
20 | showLegend: false,
21 | title: 'Over 9K',
22 | showYAxis: false,
23 | showXAxis: false,
24 | color: ['rgb(0, 150, 136)', 'rgb(204, 203, 203)', 'rgb(149, 149, 149)', 'rgb(44, 44, 44)'],
25 | tooltip: { contentGenerator: function (d) { return '' + d.point.y + '%
' + '' + d.series[0].key + '
' } },
26 | showControls: false
27 | }
28 | };
29 |
30 | vm.performanceChartData = [];
31 | vm.performancePeriod = 'week';
32 | vm.changePeriod = changePeriod;
33 |
34 | activate();
35 |
36 | function activate() {
37 | var queries = [loadData()];
38 | $q.all(queries);
39 | }
40 |
41 |
42 | function loadData() {
43 | vm.performanceChartData = performanceService.getPerformanceData(vm.performancePeriod);
44 | }
45 |
46 | function changePeriod() {
47 | loadData();
48 | }
49 | }
50 | })();
51 |
--------------------------------------------------------------------------------
/src/app/controllers/TodoController.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | angular
3 | .module('app')
4 | .controller('TodoController', [
5 | 'todoListService',
6 | TodoController
7 | ]);
8 |
9 | function TodoController(todoListService) {
10 | var vm = this;
11 |
12 | vm.addTodo = addTodo;
13 | vm.remaining = remaining;
14 | vm.archive = archive;
15 | vm.toggleAll = toggleAll;
16 | vm.todos = [];
17 |
18 | todoListService
19 | .loadAllItems()
20 | .then(function (todos) {
21 | vm.todos = [].concat(todos);
22 | });
23 |
24 | function addTodo() {
25 | if (!vm.todoText) return;
26 | vm.todos.push({text: vm.todoText, done: false});
27 | vm.todoText = '';
28 | }
29 |
30 | function remaining() {
31 | var count = 0;
32 | angular.forEach(vm.todos, function (todo) {
33 | count += todo.done ? 0 : 1;
34 | });
35 | return count;
36 | }
37 |
38 | function archive(e) {
39 | // Prevent from submitting
40 | e.preventDefault();
41 | var oldTodos = vm.todos;
42 | vm.todos = [];
43 | angular.forEach(oldTodos, function (todo) {
44 | if (!todo.done) vm.todos.push(todo);
45 | });
46 | }
47 |
48 | function toggleAll() {
49 | if (remaining() == 0) {
50 | angular.forEach(vm.todos, function (todo) {
51 | todo.done = false;
52 | });
53 | } else {
54 | angular.forEach(vm.todos, function (todo) {
55 | todo.done = true;
56 | });
57 | }
58 | }
59 | }
60 | })();
61 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular Material Dashboard
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/views/data-table.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Nutrition
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ID
15 | Dessert (100g serving)
16 | Calories
17 | Fat (g)
18 | Carbs (g)
19 |
20 |
21 |
22 |
23 |
24 | {{item.id}}
25 | {{item.issue}}
26 | {{item.progress}}
27 | {{item.status}}
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/gulp/proxy.js:
--------------------------------------------------------------------------------
1 | /*jshint unused:false */
2 |
3 | /***************
4 |
5 | This file allow to configure a proxy system plugged into BrowserSync
6 | in order to redirect backend requests while still serving and watching
7 | files from the web project
8 |
9 | IMPORTANT: The proxy is disabled by default.
10 |
11 | If you want to enable it, watch at the configuration options and finally
12 | change the `module.exports` at the end of the file
13 |
14 | ***************/
15 |
16 | 'use strict';
17 |
18 | var httpProxy = require('http-proxy');
19 | var chalk = require('chalk');
20 |
21 | /*
22 | * Location of your backend server
23 | */
24 | var proxyTarget = 'http://server/context/';
25 |
26 | var proxy = httpProxy.createProxyServer({
27 | target: proxyTarget
28 | });
29 |
30 | proxy.on('error', function(error, req, res) {
31 | res.writeHead(500, {
32 | 'Content-Type': 'text/plain'
33 | });
34 |
35 | console.error(chalk.red('[Proxy]'), error);
36 | });
37 |
38 | /*
39 | * The proxy middleware is an Express middleware added to BrowserSync to
40 | * handle backend request and proxy them to your backend.
41 | */
42 | function proxyMiddleware(req, res, next) {
43 | /*
44 | * This test is the switch of each request to determine if the request is
45 | * for a static file to be handled by BrowserSync or a backend request to proxy.
46 | *
47 | * The existing test is a standard check on the files extensions but it may fail
48 | * for your needs. If you can, you could also check on a context in the url which
49 | * may be more reliable but can't be generic.
50 | */
51 | if (/\.(html|css|js|png|jpg|jpeg|gif|ico|xml|rss|txt|eot|svg|ttf|woff|cur)(\?((r|v|rel|rev)=[\-\.\w]*)?)?$/.test(req.url)) {
52 | next();
53 | } else {
54 | proxy.web(req, res);
55 | }
56 | }
57 |
58 | /*
59 | * This is where you activate or not your proxy.
60 | *
61 | * The first line activate if and the second one ignored it
62 | */
63 |
64 | //module.exports = [proxyMiddleware];
65 | module.exports = [];
66 |
--------------------------------------------------------------------------------
/src/app/components/services/MessagesService.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('messagesService', [
6 | '$q',
7 | messagesService
8 | ]);
9 |
10 | function messagesService($q){
11 | var messages = [
12 | {
13 | userPhoto : '/assets/images/user.svg',
14 | subject: 'Electromagnetic radiation',
15 | userName: 'Wilhelm Conrad Röntgen',
16 | date: '1901',
17 | text: 'In recognition of the extraordinary services he has rendered by the discovery of the remarkable rays subsequently named after him'
18 | },
19 | {
20 | userPhoto : '/assets/images/user.svg',
21 | subject: 'Quantum theory',
22 | userName: 'Max Planck',
23 | date: '1918',
24 | text: 'For the services he rendered to the advancement of physics by his discovery of energy quanta.'
25 | },
26 | {
27 | userPhoto : '/assets/images/user.svg',
28 | subject: 'Photoelectric effect',
29 | userName: 'Albert Einstein',
30 | date: '1921',
31 | text: 'For his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect'
32 | },
33 | {
34 | userPhoto : '/assets/images/user.svg',
35 | subject: 'Atomic structure',
36 | userName: 'Niels Bohr',
37 | date: '1922',
38 | text: 'For his services in the investigation of the structure of atoms and of the radiation emanating from them'
39 | },
40 | {
41 | userPhoto : '/assets/images/user.svg',
42 | subject: 'Wave equation',
43 | userName: 'Erwin Schrödinger',
44 | date: '1933',
45 | text: 'For the discovery of new productive forms of atomic theory'
46 | },
47 | {
48 | userPhoto : '/assets/images/user.svg',
49 | subject: 'Spin theory',
50 | userName: 'Wolfgang Pauli',
51 | date: '1945',
52 | text: 'For the discovery of the Exclusion Principle, also called the Pauli principle'
53 | }
54 | ];
55 |
56 | return {
57 | loadAllItems : function() {
58 | return $q.when(messages);
59 | }
60 | };
61 | }
62 |
63 | })();
64 |
--------------------------------------------------------------------------------
/src/app/components/services/TableService.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('tableService', [
6 | '$q',
7 | tableService
8 | ]);
9 |
10 | function tableService($q){
11 | var tableData = [
12 | {
13 | issue: 'Nested views',
14 | progress: 100,
15 | status: 'Done',
16 | class: 'md-accent'
17 | },
18 | {
19 | issue: 'Table component',
20 | progress: 40,
21 | status: 'Feedback',
22 | class: ''
23 | },
24 | {
25 | issue: 'Dashboard tiles',
26 | progress: 100,
27 | status: 'Done',
28 | class: 'md-accent'
29 | },
30 | {
31 | issue: 'Panel widget',
32 | progress: 84,
33 | status: 'In progress',
34 | class: 'orange'
35 | },
36 | {
37 | issue: 'Form',
38 | progress: 100,
39 | status: 'Done',
40 | class: 'md-accent'
41 | },
42 | {
43 | issue: 'Custom CSS',
44 | progress: 20,
45 | status: 'Feedback',
46 | class: ''
47 | },
48 | {
49 | issue: 'Add backend',
50 | progress: 1,
51 | status: 'To do',
52 | class: 'md-warn'
53 | },
54 | {
55 | issue: 'Layout with sidebar',
56 | progress: 100,
57 | status: 'Done',
58 | class: 'md-accent'
59 | }
60 | ];
61 |
62 | function PickRandom() {
63 | return Object.assign({}, tableData[Math.floor(Math.random()*tableData.length)]);
64 | }
65 |
66 | return {
67 | loadAllItems : function() {
68 | return $q.when(tableData);
69 | },
70 | /**
71 | * Query expects that `limit`,`page`, and `order` fields be present
72 | */
73 | loadByPagination: function (query) {
74 | query = query || {limit:10,page:1};
75 |
76 | var list = [];
77 | var start = (query.page-1)*query.limit;
78 | var end = start + query.limit;
79 | for (var i = start; i < end; i++) {
80 | var f = PickRandom();
81 | f.id = i+1;
82 | list.push(f);
83 | }
84 | return $q.when({items:list,count:800});
85 | }
86 | };
87 | }
88 | })();
89 |
--------------------------------------------------------------------------------
/src/app/views/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Username
5 |
6 |
7 |
8 | Email
9 |
10 |
11 |
12 |
13 |
59 |
60 |
--------------------------------------------------------------------------------
/gulp/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')({
8 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
9 | });
10 |
11 | gulp.task('partials', function () {
12 | return gulp.src([
13 | paths.src + '/{app,components}/**/*.html',
14 | paths.tmp + '/{app,components}/**/*.html'
15 | ])
16 | .pipe($.minifyHtml({
17 | empty: true,
18 | spare: true,
19 | quotes: true
20 | }))
21 | .pipe($.angularTemplatecache('templateCacheHtml.js', {
22 | module: 'angularMaterialAdmin'
23 | }))
24 | .pipe(gulp.dest(paths.tmp + '/partials/'));
25 | });
26 |
27 | gulp.task('html', ['inject', 'partials'], function () {
28 | var partialsInjectFile = gulp.src(paths.tmp + '/partials/templateCacheHtml.js', { read: false });
29 | var partialsInjectOptions = {
30 | starttag: '',
31 | ignorePath: paths.tmp + '/partials',
32 | addRootSlash: false
33 | };
34 |
35 | var htmlFilter = $.filter('*.html');
36 | var jsFilter = $.filter('**/*.js');
37 | var cssFilter = $.filter('**/*.css');
38 | var assets;
39 |
40 | return gulp.src(paths.tmp + '/serve/*.html')
41 | .pipe($.inject(partialsInjectFile, partialsInjectOptions))
42 | .pipe(assets = $.useref.assets())
43 | .pipe($.rev())
44 | .pipe(jsFilter)
45 | .pipe($.ngAnnotate())
46 | .pipe($.uglify({preserveComments: $.uglifySaveLicense}))
47 | .pipe(jsFilter.restore())
48 | .pipe(cssFilter)
49 | .pipe($.csso())
50 | .pipe(cssFilter.restore())
51 | .pipe(assets.restore())
52 | .pipe($.useref())
53 | .pipe($.revReplace())
54 | .pipe(htmlFilter)
55 | .pipe($.minifyHtml({
56 | empty: true,
57 | spare: true,
58 | quotes: true
59 | }))
60 | .pipe(htmlFilter.restore())
61 | .pipe(gulp.dest(paths.dist + '/'))
62 | .pipe($.size({ title: paths.dist + '/', showFiles: true }));
63 | });
64 |
65 | gulp.task('images', function () {
66 | return gulp.src(paths.src + '/assets/images/**/*')
67 | .pipe(gulp.dest(paths.dist + '/assets/images/'));
68 | });
69 |
70 | gulp.task('fonts', function () {
71 | return gulp.src($.mainBowerFiles())
72 | .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
73 | .pipe($.flatten())
74 | .pipe(gulp.dest(paths.dist + '/fonts/'));
75 | });
76 |
77 | gulp.task('misc', function () {
78 | return gulp.src(paths.src + '/**/*.ico')
79 | .pipe(gulp.dest(paths.dist + '/'));
80 | });
81 |
82 | gulp.task('clean', function (done) {
83 | $.del([paths.dist + '/', paths.tmp + '/'], done);
84 | });
85 |
86 | gulp.task('build', ['html', 'images', 'fonts', 'misc']);
87 |
--------------------------------------------------------------------------------
/src/app/controllers/MainController.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | angular
4 | .module('app')
5 | .controller('MainController', [
6 | 'navService', '$mdSidenav', '$mdBottomSheet', '$log', '$q', '$state', '$mdToast',
7 | MainController
8 | ]);
9 |
10 | function MainController(navService, $mdSidenav, $mdBottomSheet, $log, $q, $state, $mdToast) {
11 | var vm = this;
12 |
13 | vm.menuItems = [ ];
14 | vm.selectItem = selectItem;
15 | vm.toggleItemsList = toggleItemsList;
16 | vm.showActions = showActions;
17 | vm.title = $state.current.data.title;
18 | vm.showSimpleToast = showSimpleToast;
19 | vm.toggleRightSidebar = toggleRightSidebar;
20 |
21 | navService
22 | .loadAllItems()
23 | .then(function(menuItems) {
24 | vm.menuItems = [].concat(menuItems);
25 | });
26 |
27 | function toggleRightSidebar() {
28 | $mdSidenav('right').toggle();
29 | }
30 |
31 | function toggleItemsList() {
32 | var pending = $mdBottomSheet.hide() || $q.when(true);
33 |
34 | pending.then(function(){
35 | $mdSidenav('left').toggle();
36 | });
37 | }
38 |
39 | function selectItem (item) {
40 | vm.title = item.name;
41 | vm.toggleItemsList();
42 | vm.showSimpleToast(vm.title);
43 | }
44 |
45 | function showActions($event) {
46 | $mdBottomSheet.show({
47 | parent: angular.element(document.getElementById('content')),
48 | templateUrl: 'app/views/partials/bottomSheet.html',
49 | controller: [ '$mdBottomSheet', SheetController],
50 | controllerAs: "vm",
51 | bindToController : true,
52 | targetEvent: $event
53 | }).then(function(clickedItem) {
54 | clickedItem && $log.debug( clickedItem.name + ' clicked!');
55 | });
56 |
57 | function SheetController( $mdBottomSheet ) {
58 | var vm = this;
59 |
60 | vm.actions = [
61 | { name: 'Share', icon: 'share', url: 'https://twitter.com/intent/tweet?text=Angular%20Material%20Dashboard%20https://github.com/flatlogic/angular-material-dashboard%20via%20@flatlogicinc' },
62 | { name: 'Star', icon: 'star', url: 'https://github.com/flatlogic/angular-material-dashboard/stargazers' }
63 | ];
64 |
65 | vm.performAction = function(action) {
66 | $mdBottomSheet.hide(action);
67 | };
68 | }
69 | }
70 |
71 | function showSimpleToast(title) {
72 | $mdToast.show(
73 | $mdToast.simple()
74 | .content(title)
75 | .hideDelay(2000)
76 | .position('bottom right')
77 | );
78 | }
79 | }
80 |
81 | })();
82 |
--------------------------------------------------------------------------------
/src/app/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularMaterialAdmin', ['ngAnimate', 'ngCookies',
4 | 'ngSanitize', 'ui.router', 'ngMaterial', 'nvd3', 'app' , 'md.data.table'])
5 |
6 | .config(function ($stateProvider, $urlRouterProvider, $mdThemingProvider,
7 | $mdIconProvider) {
8 | $stateProvider
9 | .state('home', {
10 | url: '',
11 | templateUrl: 'app/views/main.html',
12 | controller: 'MainController',
13 | controllerAs: 'vm',
14 | abstract: true
15 | })
16 | .state('home.dashboard', {
17 | url: '/dashboard',
18 | templateUrl: 'app/views/dashboard.html',
19 | data: {
20 | title: 'Dashboard'
21 | }
22 | })
23 | .state('home.profile', {
24 | url: '/profile',
25 | templateUrl: 'app/views/profile.html',
26 | controller: 'ProfileController',
27 | controllerAs: 'vm',
28 | data: {
29 | title: 'Profile'
30 | }
31 | })
32 | .state('home.table', {
33 | url: '/table',
34 | controller: 'TableController',
35 | controllerAs: 'vm',
36 | templateUrl: 'app/views/table.html',
37 | data: {
38 | title: 'Table'
39 | }
40 | })
41 | .state('home.data-table', {
42 | url: '/data-table',
43 | controller: 'DataTableController',
44 | controllerAs: 'vm',
45 | templateUrl: 'app/views/data-table.html',
46 | data: {
47 | title: 'Table'
48 | }
49 | });
50 |
51 | $urlRouterProvider.otherwise('/dashboard');
52 |
53 | $mdThemingProvider
54 | .theme('default')
55 | .primaryPalette('grey', {
56 | 'default': '600'
57 | })
58 | .accentPalette('teal', {
59 | 'default': '500'
60 | })
61 | .warnPalette('defaultPrimary');
62 |
63 | $mdThemingProvider.theme('dark', 'default')
64 | .primaryPalette('defaultPrimary')
65 | .dark();
66 |
67 | $mdThemingProvider.theme('grey', 'default')
68 | .primaryPalette('grey');
69 |
70 | $mdThemingProvider.theme('custom', 'default')
71 | .primaryPalette('defaultPrimary', {
72 | 'hue-1': '50'
73 | });
74 |
75 | $mdThemingProvider.definePalette('defaultPrimary', {
76 | '50': '#FFFFFF',
77 | '100': 'rgb(255, 198, 197)',
78 | '200': '#E75753',
79 | '300': '#E75753',
80 | '400': '#E75753',
81 | '500': '#E75753',
82 | '600': '#E75753',
83 | '700': '#E75753',
84 | '800': '#E75753',
85 | '900': '#E75753',
86 | 'A100': '#E75753',
87 | 'A200': '#E75753',
88 | 'A400': '#E75753',
89 | 'A700': '#E75753'
90 | });
91 |
92 | $mdIconProvider.icon('user', 'assets/images/user.svg', 64);
93 | });
94 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular Material Dashboard
2 |
3 | [](https://gitter.im/flatlogic/angular-material-dashboard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 |
5 | [View Demo](https://flatlogic.com/admin-dashboards/angular-material-dashboard/demo) | [Download](https://github.com/flatlogic/angular-material-dashboard.git) | [More templates](https://flatlogic.com/templates) | [Support forum](https://flatlogic.com/forum)
6 |
7 | The Angular Material Dashboard provides a responsive admin interface that leverages [Angular Material](https://github.com/angular/material). for its design principles. It embodies the principles of material design, ensuring a cohesive and intuitive user experience, ideal for developing sophisticated [business software](https://flatlogic.com/) dashboards.
8 |
9 | 
10 |
11 | ## Getting started
12 |
13 | Clone project:
14 |
15 | $ git clone https://github.com/flatlogic/angular-material-dashboard.git
16 |
17 | Install dependencies:
18 |
19 | $ cd angular-material-dashboard
20 | $ yarn install
21 |
22 | Run development web-server:
23 |
24 | $ gulp serve
25 |
26 | ## Features
27 |
28 | * AngularJS
29 | * Angular UI Router
30 | * Angular Material
31 | * Sass styles
32 | * Gulp build
33 | * Stylish, clean, responsive layout with original design
34 | * BrowserSync for the ease of development
35 |
36 | ## Project structure and credits
37 |
38 | Project structure based on [gulp-angular yeoman generator](https://github.com/Swiip/generator-gulp-angular).
39 | If you have any questions about the build or project structure please check out their documentation.
40 |
41 | UI components built with [Angular Material](https://material.angularjs.org/).
42 |
43 | Design by [flatlogic.com](http://flatlogic.com/)
44 |
45 | ## Deploy to Github pages
46 |
47 | $ gulp build
48 | $ gulp deploy
49 |
50 | ## Support
51 | For any additional information please go to our [**support forum**](https://flatlogic.com/forum) and raise your questions or feedback provide there. We highly appreciate your participation!
52 |
53 | ## Community
54 | - [Tweet about it](https://twitter.com/intent/tweet?text=Angular%20Material%20Dashboard%20https://github.com/flatlogic/angular-material-dashboard%20via%20@flatlogicinc) to support revolution in classic paid templates market.
55 | - Follow [@flatlogicinc on Twitter](https://twitter.com/flatlogicinc).
56 | - Subscribe to Flatlogic newsletter at [flatlogic.com](http://flatlogic.com/)
57 |
58 | ## More from Flatlogic
59 | - [💥Sing App Dashboard](https://github.com/flatlogic/sing-app) - Free and open-source admin dashboard template built with Bootstrap 4
60 | - [React Native Starter](https://github.com/flatlogic/react-native-starter) - 🚀 A powerful react native starter template that bootstraps development of your mobile application
61 |
62 | ## Premium themes
63 | Looking for premium themes and templates? Check out our other template at [flatlogic.com](https://flatlogic.com/templates).
64 |
--------------------------------------------------------------------------------
/src/app/stylesheets/_custom.scss:
--------------------------------------------------------------------------------
1 | // COLORS
2 | $main-bg-color: #ECECEC;
3 | $text-color: #7A7A7A;
4 | $accent-color: rgb(0, 150, 136);
5 | $warning-color: #E75753;
6 |
7 |
8 | // VARIABLES
9 | $left-sidenav-width: 110px;
10 | $widget-height: 310px;
11 | $font-weight-bold: 600;
12 | $font-size-large: 22px;
13 |
14 |
15 | // LAYOUT
16 | body {
17 | color: $text-color;
18 | }
19 |
20 | .toolbar-button {
21 | min-width: 20px;
22 | }
23 |
24 | .share-label {
25 | vert-align: middle;
26 | margin-left: 10px;
27 | }
28 |
29 | .page-content {
30 | background-color: $main-bg-color;
31 | }
32 |
33 | .widget-progress {
34 | width: 95% !important;
35 | margin-left: 10px;
36 | }
37 |
38 |
39 | // UTILS
40 | .capitalize {
41 | text-transform: capitalize;
42 | }
43 |
44 | .img-circle {
45 | height: 50px;
46 | border-radius: 50%;
47 | margin: 0 10px;
48 | }
49 |
50 |
51 | // COMPONENTS
52 | .messages {
53 | position: relative;
54 |
55 | &-content {
56 | height: 100vh;
57 | }
58 | }
59 |
60 | .notifications-label {
61 | width: 16px;
62 | height: 16px;
63 | line-height: 16px;
64 | text-align: center;
65 | border-radius: 50%;
66 | position: absolute;
67 | font-size: 12px;
68 | top: 2px;
69 | right: 2px;
70 | background-color: $warning-color;
71 | }
72 |
73 | // panel-widget
74 | .panel-widget {
75 | background-color: white;
76 |
77 | &-toolbar {
78 | box-shadow: none;
79 | margin: 0;
80 | }
81 |
82 | &-tittle {
83 | color: $text-color;
84 | }
85 | }
86 |
87 | .options {
88 | -webkit-transition:all linear 0.5s;
89 | transition:all linear 0.5s;
90 | }
91 |
92 | .options.ng-hide {
93 | opacity:0;
94 | }
95 |
96 | .fixed-height-widget {
97 | height: $widget-height;
98 | }
99 |
100 | // charts
101 | .donut-chart-title{
102 | text-align: center;
103 | }
104 |
105 | .custom-tooltip {
106 | font-size: $font-size-large;
107 | color: $text-color;
108 | text-align: center;
109 | }
110 |
111 |
112 | // OVERRIDES
113 | // angular material overrides
114 | md-radio-group {
115 | border: none;
116 | }
117 |
118 | md-icon {
119 | height: auto;
120 | }
121 |
122 | md-sidenav.md-locked-open.md-sidenav-left {
123 | width: $left-sidenav-width;
124 | min-width: $left-sidenav-width;
125 | max-width: $left-sidenav-width;
126 | }
127 |
128 | a.md-button.md-warn.md-raised, a.md-button.md-warn.md-fab, .md-button.md-warn.md-raised, .md-button.md-warn.md-fab {
129 | color: white;
130 | }
131 |
132 | md-radio-button.md-accent.md-checked .md-label span {
133 | color: $accent-color;
134 | }
135 |
136 | .md-toolbar-tools h1 {
137 | font-size: $font-size-large;
138 | }
139 |
140 |
141 | md-backdrop.md-sidenav-backdrop {
142 | position: fixed;
143 | }
144 |
145 | // libs overrides
146 | .material-icons {
147 | vertical-align: middle;
148 | }
149 |
150 | .material-icons.md-18 { font-size: 18px; }
151 | .material-icons.md-24 { font-size: 24px; }
152 | .material-icons.md-36 { font-size: 36px; }
153 | .material-icons.md-48 { font-size: 48px; }
154 |
155 | .nvd3.nv-pie .nv-pie-title {
156 | fill: rgb(68, 68, 68);
157 | font-weight: $font-weight-bold;
158 | font-size: $font-size-large !important;
159 | }
160 |
161 | .nvtooltip {
162 | background-color: transparent;
163 | border: none;
164 | font-weight: $font-weight-bold;
165 | }
166 |
167 | .orange .md-bar2 {
168 | background-color: orange;
169 | }
170 |
171 | .orange .md-container {
172 | background-color: rgb(255, 236, 201)
173 | }
--------------------------------------------------------------------------------
/src/app/views/main.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 | AMD
7 |
8 |
9 |
12 |
13 | {{item.icon}}
14 |
15 |
16 | {{item.name}}
17 |
18 |
19 |
20 |
21 |
22 | Actions
23 |
24 |
25 |
26 |
27 |
28 |
29 |
34 |
35 |
36 | search
37 |
38 |
39 | notifications
40 | 7
41 |
42 |
43 | menu
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
60 | Richard Feynman
61 | keyboard_arrow_down
62 |
63 |
64 | Profile
65 | Log out
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
Messages
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/app/components/services/PerformanceService.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('performanceService', [
6 | performanceService
7 | ]);
8 |
9 | function performanceService() {
10 |
11 | var service = {
12 | getPerformanceData: getPerformanceData
13 | };
14 |
15 | return service;
16 |
17 | function getPerformanceData(performancePeriod) {
18 | if (performancePeriod === 'week') {
19 | return [
20 | {
21 | "key": 'Middleware',
22 | "values": [[1, 11], [2, 10], [3, 14], [4, 21], [5, 13], [6, 21], [7, 21], [8, 18], [9, 11], [10, 11], [11, 18], [12, 14], [13, 10], [14, 20], [15, 21], [16, 28], [17, 12], [18, 16], [19, 22], [20, 18], [21, 21], [22, 10], [23, 11], [24, 14], [25, 9], [26, 14], [27, 10], [28, 21], [29, 11]]
23 | },
24 |
25 | {
26 | "key": 'Ruby',
27 | "values": [[1, 29], [2, 36], [3, 42], [4, 25], [5, 22], [6, 34], [7, 41], [8, 19], [9, 45], [10, 31], [11, 28], [12, 36], [13, 54], [14, 41], [15, 36], [16, 39], [17, 21], [18, 20], [19, 22], [20, 44], [21, 32], [22, 20], [23, 28], [24, 24], [25, 29], [26, 19], [27, 20], [28, 31], [29, 49]]
28 | },
29 |
30 | {
31 | "key": 'Web External',
32 | "values": [[1, 54], [2, 74], [3, 64], [4, 68], [5, 56], [6, 44], [7, 61], [8, 63], [9, 45], [10, 51], [11, 68], [12, 46], [13, 64], [14, 51], [15, 42], [16, 63], [17, 72], [18, 60], [19, 52], [20, 58], [21, 41], [22, 40], [23, 58], [24, 30], [25, 49], [26, 54], [27, 60], [28, 41], [29, 66]]
33 | },
34 | {
35 | "key": 'Database',
36 | "values": [[1, 64], [2, 84], [3, 64], [4, 68], [5, 86], [6, 74], [7, 81], [8, 83], [9, 65], [10, 61], [11, 88], [12, 76], [13, 84], [14, 71], [15, 82], [16, 73], [17, 92], [18, 80], [19, 62], [20, 68], [21, 71], [22, 50], [23, 78], [24, 60], [25, 59], [26, 74], [27, 80], [28, 51], [29, 97]]
37 | }
38 | ]
39 | } else {
40 | return [
41 | {
42 | "key": 'Middleware',
43 | "values": [[1, 13], [2, 14], [3, 24], [4, 18], [5, 16], [6, 14], [7, 11], [8, 13], [9, 15], [10, 11], [11, 18], [12, 16], [13, 28], [14, 11], [15, 12], [16, 13], [17, 12], [18, 20], [19, 22], [20, 18], [21, 11], [22, 10], [23, 18], [24, 20], [25, 9], [26, 14], [27, 10], [28, 11], [29, 17]]
44 | },
45 |
46 | {
47 | "key": 'Ruby',
48 | "values": [[1, 29], [2, 36], [3, 42], [4, 25], [5, 22], [6, 34], [7, 41], [8, 19], [9, 45], [10, 31], [11, 28], [12, 36], [13, 54], [14, 41], [15, 36], [16, 39], [17, 21], [18, 20], [19, 22], [20, 44], [21, 32], [22, 20], [23, 28], [24, 24], [25, 29], [26, 19], [27, 20], [28, 31], [29, 49]]
49 | },
50 |
51 | {
52 | "key": 'Web External',
53 | "values": [[1, 54], [2, 74], [3, 64], [4, 68], [5, 56], [6, 44], [7, 61], [8, 63], [9, 45], [10, 51], [11, 68], [12, 46], [13, 64], [14, 51], [15, 42], [16, 63], [17, 72], [18, 60], [19, 52], [20, 58], [21, 41], [22, 40], [23, 58], [24, 30], [25, 49], [26, 54], [27, 60], [28, 41], [29, 66]]
54 | },
55 | {
56 | "key": 'Database',
57 | "values": [[1, 74], [2, 64], [3, 84], [4, 78], [5, 66], [6, 64], [7, 71], [8, 83], [9, 55], [10, 81], [11, 88], [12, 76], [13, 84], [14, 71], [15, 62], [16, 73], [17, 82], [18, 80], [19, 92], [20, 68], [21, 71], [22, 70], [23, 78], [24, 80], [25, 59], [26, 74], [27, 80], [28, 51], [29, 67]]
58 | }
59 | ]
60 | }
61 | }
62 | }
63 | })();
64 |
--------------------------------------------------------------------------------
/src/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found :(
6 |
141 |
142 |
143 |
144 |
Not found :(
145 |
Sorry, but the page you were trying to view does not exist.
146 |
It looks like this was the result of either:
147 |
148 | a mistyped address
149 | an out-of-date link
150 |
151 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/src/app/stylesheets/_table.scss:
--------------------------------------------------------------------------------
1 | // This file based on http://codepen.io/zavoloklom/pen/IGkDz
2 |
3 | // VARIABLES
4 | $table-header-font-weight: 400;
5 | $table-header-font-color: #757575;
6 |
7 | $table-cell-padding: 1.2rem;
8 |
9 | $table-bg: #fff;
10 | $table-bg-accent: #f5f5f5;
11 | $table-bg-hover: rgba(0,0,0,.12);
12 | $table-bg-active: $table-bg-hover;
13 | $table-border-color: #e0e0e0;
14 |
15 |
16 | // MIXINS
17 | @mixin transition($transition-property, $transition-time, $method) {
18 | -webkit-transition: $transition-property $transition-time $method;
19 | -moz-transition: $transition-property $transition-time $method;
20 | -ms-transition: $transition-property $transition-time $method;
21 | -o-transition: $transition-property $transition-time $method;
22 | transition: $transition-property $transition-time $method;
23 | }
24 |
25 |
26 | //TABLES
27 | .table {
28 | border-spacing: 0;
29 | width: 100%;
30 | max-width: 100%;
31 | margin-bottom: 2rem;
32 | background-color: $table-bg;
33 | > thead,
34 | > tbody,
35 | > tfoot {
36 | > tr {
37 | @include transition(all, 0.3s, ease);
38 | > th,
39 | > td {
40 | text-align: left;
41 | padding: $table-cell-padding;
42 | vertical-align: top;
43 | border-top: 0;
44 | @include transition(all, 0.3s, ease);
45 | }
46 | }
47 | }
48 | > thead > tr > th {
49 | font-weight: $table-header-font-weight;
50 | color: $table-header-font-color;
51 | vertical-align: bottom;
52 | border-bottom: 1px solid rgba(0,0,0,.12);
53 | }
54 | > caption + thead,
55 | > colgroup + thead,
56 | > thead:first-child {
57 | > tr:first-child {
58 | > th,
59 | > td {
60 | border-top: 0;
61 | }
62 | }
63 | }
64 | > tbody + tbody {
65 | border-top: 1px solid rgba(0,0,0,.12);
66 | }
67 |
68 | // Nesting
69 | .table {
70 | background-color: $table-bg;
71 | }
72 |
73 | // Remove border
74 | .no-border {
75 | border: 0;
76 | }
77 | }
78 |
79 | // Bordered version
80 | //
81 | // Add horizontal borders between columns.
82 | .table-bordered {
83 | border: 0;
84 | > thead,
85 | > tbody,
86 | > tfoot {
87 | > tr {
88 | > th,
89 | > td {
90 | border: 0;
91 | border-bottom: 1px solid $table-border-color;
92 | }
93 | }
94 | }
95 | > thead > tr {
96 | > th,
97 | > td {
98 | border-bottom-width: 2px;
99 | }
100 | }
101 | }
102 |
103 |
104 | // Hover effect
105 | //
106 | .table-hover {
107 | > tbody > tr:hover {
108 | > td,
109 | > th {
110 | background-color: $table-bg-hover;
111 | }
112 | }
113 | }
114 |
115 | // Responsive tables (vertical)
116 | //
117 | // Wrap your tables in `.table-responsive-vertical` and we'll make them mobile friendly
118 | // by vertical table-cell display. Only applies <768px. Everything above that will display normally.
119 | // For correct display you must add 'data-title' to each 'td'
120 | .table-responsive-vertical {
121 |
122 | @media screen and (max-width: 768px) {
123 |
124 | // Tighten up spacing
125 | > .table {
126 | margin-bottom: 0;
127 | background-color: transparent;
128 | > thead,
129 | > tfoot {
130 | display: none;
131 | }
132 |
133 | > tbody {
134 | display: block;
135 |
136 | > tr {
137 | display: block;
138 | border: 1px solid $table-border-color;
139 | border-radius: 2px;
140 | margin-bottom: $table-cell-padding;
141 |
142 | > td {
143 | background-color: $table-bg;
144 | display: block;
145 | vertical-align: middle;
146 | text-align: right;
147 | }
148 | > td[data-title]:before {
149 | content: attr(data-title);
150 | float: left;
151 | font-size: inherit;
152 | font-weight: $table-header-font-weight;
153 | color: $table-header-font-color;
154 | padding-right: 10px;
155 | }
156 | }
157 | }
158 | }
159 |
160 | // Special overrides for shadows
161 | &.shadow-z-1 {
162 | -webkit-box-shadow: none;
163 | -moz-box-shadow: none;
164 | box-shadow: none;
165 | > .table > tbody > tr {
166 | border: none;
167 | }
168 | }
169 |
170 | // Special overrides for the bordered tables
171 | > .table-bordered {
172 | border: 0;
173 |
174 | // Nuke the appropriate borders so that the parent can handle them
175 | > tbody {
176 | > tr {
177 | > td {
178 | border: 0;
179 | border-bottom: 1px solid $table-border-color;
180 | }
181 | > td:last-child {
182 | border-bottom: 0;
183 | }
184 | }
185 | }
186 | }
187 |
188 | // Special overrides for the striped tables
189 | > .table-striped {
190 | > tbody > tr > td,
191 | > tbody > tr:nth-child(odd) {
192 | background-color: $table-bg;
193 | }
194 | > tbody > tr > td:nth-child(odd) {
195 | background-color: $table-bg-accent;
196 | }
197 | }
198 |
199 | // Special overrides for hover tables
200 | > .table-hover {
201 | > tbody {
202 | > tr:hover > td,
203 | > tr:hover {
204 | background-color: $table-bg;
205 | }
206 | > tr > td:hover {
207 | background-color: $table-bg-hover;
208 | }
209 | }
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/src/app/components/services/CountriesService.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('app')
5 | .service('countriesService', [
6 | countriesService
7 | ]);
8 |
9 | function countriesService(){
10 | var allCountries = [
11 | {name: 'Afghanistan', code: 'AF'},
12 | {name: 'Åland Islands', code: 'AX'},
13 | {name: 'Albania', code: 'AL'},
14 | {name: 'Algeria', code: 'DZ'},
15 | {name: 'American Samoa', code: 'AS'},
16 | {name: 'AndorrA', code: 'AD'},
17 | {name: 'Angola', code: 'AO'},
18 | {name: 'Anguilla', code: 'AI'},
19 | {name: 'Antarctica', code: 'AQ'},
20 | {name: 'Antigua and Barbuda', code: 'AG'},
21 | {name: 'Argentina', code: 'AR'},
22 | {name: 'Armenia', code: 'AM'},
23 | {name: 'Aruba', code: 'AW'},
24 | {name: 'Australia', code: 'AU'},
25 | {name: 'Austria', code: 'AT'},
26 | {name: 'Azerbaijan', code: 'AZ'},
27 | {name: 'Bahamas', code: 'BS'},
28 | {name: 'Bahrain', code: 'BH'},
29 | {name: 'Bangladesh', code: 'BD'},
30 | {name: 'Barbados', code: 'BB'},
31 | {name: 'Belarus', code: 'BY'},
32 | {name: 'Belgium', code: 'BE'},
33 | {name: 'Belize', code: 'BZ'},
34 | {name: 'Benin', code: 'BJ'},
35 | {name: 'Bermuda', code: 'BM'},
36 | {name: 'Bhutan', code: 'BT'},
37 | {name: 'Bolivia', code: 'BO'},
38 | {name: 'Bosnia and Herzegovina', code: 'BA'},
39 | {name: 'Botswana', code: 'BW'},
40 | {name: 'Bouvet Island', code: 'BV'},
41 | {name: 'Brazil', code: 'BR'},
42 | {name: 'British Indian Ocean Territory', code: 'IO'},
43 | {name: 'Brunei Darussalam', code: 'BN'},
44 | {name: 'Bulgaria', code: 'BG'},
45 | {name: 'Burkina Faso', code: 'BF'},
46 | {name: 'Burundi', code: 'BI'},
47 | {name: 'Cambodia', code: 'KH'},
48 | {name: 'Cameroon', code: 'CM'},
49 | {name: 'Canada', code: 'CA'},
50 | {name: 'Cape Verde', code: 'CV'},
51 | {name: 'Cayman Islands', code: 'KY'},
52 | {name: 'Central African Republic', code: 'CF'},
53 | {name: 'Chad', code: 'TD'},
54 | {name: 'Chile', code: 'CL'},
55 | {name: 'China', code: 'CN'},
56 | {name: 'Christmas Island', code: 'CX'},
57 | {name: 'Cocos (Keeling) Islands', code: 'CC'},
58 | {name: 'Colombia', code: 'CO'},
59 | {name: 'Comoros', code: 'KM'},
60 | {name: 'Congo', code: 'CG'},
61 | {name: 'Congo, The Democratic Republic of the', code: 'CD'},
62 | {name: 'Cook Islands', code: 'CK'},
63 | {name: 'Costa Rica', code: 'CR'},
64 | {name: 'Cote D\'Ivoire', code: 'CI'},
65 | {name: 'Croatia', code: 'HR'},
66 | {name: 'Cuba', code: 'CU'},
67 | {name: 'Cyprus', code: 'CY'},
68 | {name: 'Czech Republic', code: 'CZ'},
69 | {name: 'Denmark', code: 'DK'},
70 | {name: 'Djibouti', code: 'DJ'},
71 | {name: 'Dominica', code: 'DM'},
72 | {name: 'Dominican Republic', code: 'DO'},
73 | {name: 'Ecuador', code: 'EC'},
74 | {name: 'Egypt', code: 'EG'},
75 | {name: 'El Salvador', code: 'SV'},
76 | {name: 'Equatorial Guinea', code: 'GQ'},
77 | {name: 'Eritrea', code: 'ER'},
78 | {name: 'Estonia', code: 'EE'},
79 | {name: 'Ethiopia', code: 'ET'},
80 | {name: 'Falkland Islands (Malvinas)', code: 'FK'},
81 | {name: 'Faroe Islands', code: 'FO'},
82 | {name: 'Fiji', code: 'FJ'},
83 | {name: 'Finland', code: 'FI'},
84 | {name: 'France', code: 'FR'},
85 | {name: 'French Guiana', code: 'GF'},
86 | {name: 'French Polynesia', code: 'PF'},
87 | {name: 'French Southern Territories', code: 'TF'},
88 | {name: 'Gabon', code: 'GA'},
89 | {name: 'Gambia', code: 'GM'},
90 | {name: 'Georgia', code: 'GE'},
91 | {name: 'Germany', code: 'DE'},
92 | {name: 'Ghana', code: 'GH'},
93 | {name: 'Gibraltar', code: 'GI'},
94 | {name: 'Greece', code: 'GR'},
95 | {name: 'Greenland', code: 'GL'},
96 | {name: 'Grenada', code: 'GD'},
97 | {name: 'Guadeloupe', code: 'GP'},
98 | {name: 'Guam', code: 'GU'},
99 | {name: 'Guatemala', code: 'GT'},
100 | {name: 'Guernsey', code: 'GG'},
101 | {name: 'Guinea', code: 'GN'},
102 | {name: 'Guinea-Bissau', code: 'GW'},
103 | {name: 'Guyana', code: 'GY'},
104 | {name: 'Haiti', code: 'HT'},
105 | {name: 'Heard Island and Mcdonald Islands', code: 'HM'},
106 | {name: 'Holy See (Vatican City State)', code: 'VA'},
107 | {name: 'Honduras', code: 'HN'},
108 | {name: 'Hong Kong', code: 'HK'},
109 | {name: 'Hungary', code: 'HU'},
110 | {name: 'Iceland', code: 'IS'},
111 | {name: 'India', code: 'IN'},
112 | {name: 'Indonesia', code: 'ID'},
113 | {name: 'Iran, Islamic Republic Of', code: 'IR'},
114 | {name: 'Iraq', code: 'IQ'},
115 | {name: 'Ireland', code: 'IE'},
116 | {name: 'Isle of Man', code: 'IM'},
117 | {name: 'Israel', code: 'IL'},
118 | {name: 'Italy', code: 'IT'},
119 | {name: 'Jamaica', code: 'JM'},
120 | {name: 'Japan', code: 'JP'},
121 | {name: 'Jersey', code: 'JE'},
122 | {name: 'Jordan', code: 'JO'},
123 | {name: 'Kazakhstan', code: 'KZ'},
124 | {name: 'Kenya', code: 'KE'},
125 | {name: 'Kiribati', code: 'KI'},
126 | {name: 'Korea, Democratic People\'S Republic of', code: 'KP'},
127 | {name: 'Korea, Republic of', code: 'KR'},
128 | {name: 'Kuwait', code: 'KW'},
129 | {name: 'Kyrgyzstan', code: 'KG'},
130 | {name: 'Lao People\'S Democratic Republic', code: 'LA'},
131 | {name: 'Latvia', code: 'LV'},
132 | {name: 'Lebanon', code: 'LB'},
133 | {name: 'Lesotho', code: 'LS'},
134 | {name: 'Liberia', code: 'LR'},
135 | {name: 'Libyan Arab Jamahiriya', code: 'LY'},
136 | {name: 'Liechtenstein', code: 'LI'},
137 | {name: 'Lithuania', code: 'LT'},
138 | {name: 'Luxembourg', code: 'LU'},
139 | {name: 'Macao', code: 'MO'},
140 | {name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK'},
141 | {name: 'Madagascar', code: 'MG'},
142 | {name: 'Malawi', code: 'MW'},
143 | {name: 'Malaysia', code: 'MY'},
144 | {name: 'Maldives', code: 'MV'},
145 | {name: 'Mali', code: 'ML'},
146 | {name: 'Malta', code: 'MT'},
147 | {name: 'Marshall Islands', code: 'MH'},
148 | {name: 'Martinique', code: 'MQ'},
149 | {name: 'Mauritania', code: 'MR'},
150 | {name: 'Mauritius', code: 'MU'},
151 | {name: 'Mayotte', code: 'YT'},
152 | {name: 'Mexico', code: 'MX'},
153 | {name: 'Micronesia, Federated States of', code: 'FM'},
154 | {name: 'Moldova, Republic of', code: 'MD'},
155 | {name: 'Monaco', code: 'MC'},
156 | {name: 'Mongolia', code: 'MN'},
157 | {name: 'Montserrat', code: 'MS'},
158 | {name: 'Morocco', code: 'MA'},
159 | {name: 'Mozambique', code: 'MZ'},
160 | {name: 'Myanmar', code: 'MM'},
161 | {name: 'Namibia', code: 'NA'},
162 | {name: 'Nauru', code: 'NR'},
163 | {name: 'Nepal', code: 'NP'},
164 | {name: 'Netherlands', code: 'NL'},
165 | {name: 'Netherlands Antilles', code: 'AN'},
166 | {name: 'New Caledonia', code: 'NC'},
167 | {name: 'New Zealand', code: 'NZ'},
168 | {name: 'Nicaragua', code: 'NI'},
169 | {name: 'Niger', code: 'NE'},
170 | {name: 'Nigeria', code: 'NG'},
171 | {name: 'Niue', code: 'NU'},
172 | {name: 'Norfolk Island', code: 'NF'},
173 | {name: 'Northern Mariana Islands', code: 'MP'},
174 | {name: 'Norway', code: 'NO'},
175 | {name: 'Oman', code: 'OM'},
176 | {name: 'Pakistan', code: 'PK'},
177 | {name: 'Palau', code: 'PW'},
178 | {name: 'Palestinian Territory, Occupied', code: 'PS'},
179 | {name: 'Panama', code: 'PA'},
180 | {name: 'Papua New Guinea', code: 'PG'},
181 | {name: 'Paraguay', code: 'PY'},
182 | {name: 'Peru', code: 'PE'},
183 | {name: 'Philippines', code: 'PH'},
184 | {name: 'Pitcairn', code: 'PN'},
185 | {name: 'Poland', code: 'PL'},
186 | {name: 'Portugal', code: 'PT'},
187 | {name: 'Puerto Rico', code: 'PR'},
188 | {name: 'Qatar', code: 'QA'},
189 | {name: 'Reunion', code: 'RE'},
190 | {name: 'Romania', code: 'RO'},
191 | {name: 'Russian Federation', code: 'RU'},
192 | {name: 'RWANDA', code: 'RW'},
193 | {name: 'Saint Helena', code: 'SH'},
194 | {name: 'Saint Kitts and Nevis', code: 'KN'},
195 | {name: 'Saint Lucia', code: 'LC'},
196 | {name: 'Saint Pierre and Miquelon', code: 'PM'},
197 | {name: 'Saint Vincent and the Grenadines', code: 'VC'},
198 | {name: 'Samoa', code: 'WS'},
199 | {name: 'San Marino', code: 'SM'},
200 | {name: 'Sao Tome and Principe', code: 'ST'},
201 | {name: 'Saudi Arabia', code: 'SA'},
202 | {name: 'Senegal', code: 'SN'},
203 | {name: 'Serbia and Montenegro', code: 'CS'},
204 | {name: 'Seychelles', code: 'SC'},
205 | {name: 'Sierra Leone', code: 'SL'},
206 | {name: 'Singapore', code: 'SG'},
207 | {name: 'Slovakia', code: 'SK'},
208 | {name: 'Slovenia', code: 'SI'},
209 | {name: 'Solomon Islands', code: 'SB'},
210 | {name: 'Somalia', code: 'SO'},
211 | {name: 'South Africa', code: 'ZA'},
212 | {name: 'South Georgia and the South Sandwich Islands', code: 'GS'},
213 | {name: 'Spain', code: 'ES'},
214 | {name: 'Sri Lanka', code: 'LK'},
215 | {name: 'Sudan', code: 'SD'},
216 | {name: 'Suriname', code: 'SR'},
217 | {name: 'Svalbard and Jan Mayen', code: 'SJ'},
218 | {name: 'Swaziland', code: 'SZ'},
219 | {name: 'Sweden', code: 'SE'},
220 | {name: 'Switzerland', code: 'CH'},
221 | {name: 'Syrian Arab Republic', code: 'SY'},
222 | {name: 'Taiwan, Province of China', code: 'TW'},
223 | {name: 'Tajikistan', code: 'TJ'},
224 | {name: 'Tanzania, United Republic of', code: 'TZ'},
225 | {name: 'Thailand', code: 'TH'},
226 | {name: 'Timor-Leste', code: 'TL'},
227 | {name: 'Togo', code: 'TG'},
228 | {name: 'Tokelau', code: 'TK'},
229 | {name: 'Tonga', code: 'TO'},
230 | {name: 'Trinidad and Tobago', code: 'TT'},
231 | {name: 'Tunisia', code: 'TN'},
232 | {name: 'Turkey', code: 'TR'},
233 | {name: 'Turkmenistan', code: 'TM'},
234 | {name: 'Turks and Caicos Islands', code: 'TC'},
235 | {name: 'Tuvalu', code: 'TV'},
236 | {name: 'Uganda', code: 'UG'},
237 | {name: 'Ukraine', code: 'UA'},
238 | {name: 'United Arab Emirates', code: 'AE'},
239 | {name: 'United Kingdom', code: 'GB'},
240 | {name: 'United States', code: 'US'},
241 | {name: 'United States Minor Outlying Islands', code: 'UM'},
242 | {name: 'Uruguay', code: 'UY'},
243 | {name: 'Uzbekistan', code: 'UZ'},
244 | {name: 'Vanuatu', code: 'VU'},
245 | {name: 'Venezuela', code: 'VE'},
246 | {name: 'Viet Nam', code: 'VN'},
247 | {name: 'Virgin Islands, British', code: 'VG'},
248 | {name: 'Virgin Islands, U.S.', code: 'VI'},
249 | {name: 'Wallis and Futuna', code: 'WF'},
250 | {name: 'Western Sahara', code: 'EH'},
251 | {name: 'Yemen', code: 'YE'},
252 | {name: 'Zambia', code: 'ZM'},
253 | {name: 'Zimbabwe', code: 'ZW'}
254 | ];
255 |
256 | return {
257 | loadAll : function() {
258 | return allCountries.map(function(country) {
259 | return {
260 | value: country.name.toLowerCase(),
261 | display: country.name,
262 | code: country.code
263 | };
264 | });
265 | }
266 | };
267 | }
268 |
269 | })();
270 |
--------------------------------------------------------------------------------